mirror of
https://github.com/Kaelio/ktx.git
synced 2026-07-01 08:59:39 +02:00
feat(connectors): add sqlserver maxConnections
This commit is contained in:
parent
0222778a36
commit
b741baf680
2 changed files with 65 additions and 2 deletions
|
|
@ -1,6 +1,6 @@
|
||||||
import { describe, expect, it, vi } from 'vitest';
|
import { describe, expect, it, vi } from 'vitest';
|
||||||
import { createSqlServerLiveDatabaseIntrospection } from '../../connectors/sqlserver/live-database-introspection.js';
|
import { createSqlServerLiveDatabaseIntrospection } from '../../connectors/sqlserver/live-database-introspection.js';
|
||||||
import { isKtxSqlServerConnectionConfig, KtxSqlServerScanConnector, sqlServerConnectionPoolConfigFromConfig, type KtxSqlServerPoolFactory, type KtxSqlServerQueryResult } from '../../connectors/sqlserver/connector.js';
|
import { isKtxSqlServerConnectionConfig, KtxSqlServerScanConnector, sqlServerConnectionPoolConfigFromConfig, type KtxSqlServerConnectionConfig, type KtxSqlServerPoolFactory, type KtxSqlServerQueryResult } from '../../connectors/sqlserver/connector.js';
|
||||||
import { tableRefSet } from '../../context/scan/table-ref.js';
|
import { tableRefSet } from '../../context/scan/table-ref.js';
|
||||||
|
|
||||||
function recordset<T extends Record<string, unknown>>(
|
function recordset<T extends Record<string, unknown>>(
|
||||||
|
|
@ -164,6 +164,45 @@ describe('KtxSqlServerScanConnector', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('defaults and validates SQL Server maxConnections', () => {
|
||||||
|
const baseConnection: KtxSqlServerConnectionConfig = {
|
||||||
|
driver: 'sqlserver',
|
||||||
|
host: 'db.example.test',
|
||||||
|
database: 'analytics',
|
||||||
|
username: 'reader',
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(
|
||||||
|
sqlServerConnectionPoolConfigFromConfig({
|
||||||
|
connectionId: 'warehouse',
|
||||||
|
connection: baseConnection,
|
||||||
|
}),
|
||||||
|
).toMatchObject({ pool: { max: 10 } });
|
||||||
|
|
||||||
|
expect(
|
||||||
|
sqlServerConnectionPoolConfigFromConfig({
|
||||||
|
connectionId: 'warehouse',
|
||||||
|
connection: { ...baseConnection, maxConnections: 15 },
|
||||||
|
}),
|
||||||
|
).toMatchObject({ pool: { max: 15 } });
|
||||||
|
|
||||||
|
expect(
|
||||||
|
sqlServerConnectionPoolConfigFromConfig({
|
||||||
|
connectionId: 'warehouse',
|
||||||
|
connection: { ...baseConnection, maxConnections: '12' as never },
|
||||||
|
}),
|
||||||
|
).toMatchObject({ pool: { max: 12 } });
|
||||||
|
|
||||||
|
for (const maxConnections of [0, -1, 1.5, Number.NaN, 'abc' as never]) {
|
||||||
|
expect(() =>
|
||||||
|
sqlServerConnectionPoolConfigFromConfig({
|
||||||
|
connectionId: 'warehouse',
|
||||||
|
connection: { ...baseConnection, maxConnections },
|
||||||
|
}),
|
||||||
|
).toThrow('connections.warehouse.maxConnections must be a positive integer');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
it('introspects schema, primary keys, comments, row counts, views, and foreign keys', async () => {
|
it('introspects schema, primary keys, comments, row counts, views, and foreign keys', async () => {
|
||||||
const connector = new KtxSqlServerScanConnector({
|
const connector = new KtxSqlServerScanConnector({
|
||||||
connectionId: 'warehouse',
|
connectionId: 'warehouse',
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ export interface KtxSqlServerConnectionConfig {
|
||||||
schema?: string;
|
schema?: string;
|
||||||
schemas?: string[];
|
schemas?: string[];
|
||||||
trustServerCertificate?: boolean;
|
trustServerCertificate?: boolean;
|
||||||
|
maxConnections?: number;
|
||||||
[key: string]: unknown;
|
[key: string]: unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -197,6 +198,23 @@ function maybeNumber(value: unknown): number | undefined {
|
||||||
return typeof value === 'number' && Number.isFinite(value) ? value : undefined;
|
return typeof value === 'number' && Number.isFinite(value) ? value : undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function positiveIntegerConfigValue(input: {
|
||||||
|
connection: KtxSqlServerConnectionConfig;
|
||||||
|
key: keyof KtxSqlServerConnectionConfig;
|
||||||
|
connectionId: string;
|
||||||
|
defaultValue: number;
|
||||||
|
}): number {
|
||||||
|
const value = input.connection[input.key];
|
||||||
|
if (value === undefined) {
|
||||||
|
return input.defaultValue;
|
||||||
|
}
|
||||||
|
const numberValue = Number(value);
|
||||||
|
if (!Number.isInteger(numberValue) || numberValue < 1) {
|
||||||
|
throw new Error(`connections.${input.connectionId}.${String(input.key)} must be a positive integer`);
|
||||||
|
}
|
||||||
|
return numberValue;
|
||||||
|
}
|
||||||
|
|
||||||
function schemaNames(connection: KtxSqlServerConnectionConfig, env: NodeJS.ProcessEnv): string[] {
|
function schemaNames(connection: KtxSqlServerConnectionConfig, env: NodeJS.ProcessEnv): string[] {
|
||||||
if (Array.isArray(connection.schemas) && connection.schemas.length > 0) {
|
if (Array.isArray(connection.schemas) && connection.schemas.length > 0) {
|
||||||
return connection.schemas.filter((schema) => schema.trim().length > 0).map((schema) => resolveStringReference(schema, env));
|
return connection.schemas.filter((schema) => schema.trim().length > 0).map((schema) => resolveStringReference(schema, env));
|
||||||
|
|
@ -254,6 +272,12 @@ export function sqlServerConnectionPoolConfigFromConfig(input: {
|
||||||
const server = stringConfigValue(merged, 'host', env);
|
const server = stringConfigValue(merged, 'host', env);
|
||||||
const database = stringConfigValue(merged, 'database', env);
|
const database = stringConfigValue(merged, 'database', env);
|
||||||
const user = stringConfigValue(merged, 'username', env) ?? stringConfigValue(merged, 'user', env);
|
const user = stringConfigValue(merged, 'username', env) ?? stringConfigValue(merged, 'user', env);
|
||||||
|
const maxConnections = positiveIntegerConfigValue({
|
||||||
|
connection: merged,
|
||||||
|
key: 'maxConnections',
|
||||||
|
connectionId: input.connectionId,
|
||||||
|
defaultValue: 10,
|
||||||
|
});
|
||||||
|
|
||||||
if (!server) {
|
if (!server) {
|
||||||
throw new Error(`Native SQL Server connector requires connections.${input.connectionId}.host or url`);
|
throw new Error(`Native SQL Server connector requires connections.${input.connectionId}.host or url`);
|
||||||
|
|
@ -272,7 +296,7 @@ export function sqlServerConnectionPoolConfigFromConfig(input: {
|
||||||
user,
|
user,
|
||||||
password: stringConfigValue(merged, 'password', env),
|
password: stringConfigValue(merged, 'password', env),
|
||||||
options: { encrypt: true, trustServerCertificate: merged.trustServerCertificate ?? true },
|
options: { encrypt: true, trustServerCertificate: merged.trustServerCertificate ?? true },
|
||||||
pool: { max: 10, min: 0, idleTimeoutMillis: 30000 },
|
pool: { max: maxConnections, min: 0, idleTimeoutMillis: 30000 },
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue