Skip to content

fix mssql connection provider #28

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Sep 9, 2021
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 18 additions & 4 deletions packages/external-db-mssql/lib/connection_provider.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const { ConnectionPool } = require('mssql')
const SchemaProvider = require('./mssql_schema_provider')
const DataProvider = require('./mssql_data_provider')
const DataProvider = require('./mssql_data_provider')
const FilterParser = require('./sql_filter_transformer')
const DatabaseOperations = require('./mssql_operations')

Expand All @@ -22,6 +22,14 @@ const extraOptions = () => {
}
}

const notConnectedPool = (pool, err) => {
return {
...pool,
query: async () => { throw err },
request: async () => { throw err },
connect: async () => { return await pool.connect() }
}
}

const init = async (cfg, _poolOptions) => {
const config = {
Expand All @@ -39,15 +47,21 @@ const init = async (cfg, _poolOptions) => {
const poolOptions = _poolOptions || {}

const _pool = new ConnectionPool(Object.assign({}, config, extraOptions(), poolOptions))
const pool = await _pool.connect()

const { pool, cleanup } = await _pool.connect().then((res) => {
return { pool: res, cleanup: async () => await pool.close() }
}).catch((e) => {
return {
pool: notConnectedPool(_pool, e),
cleanup: () => { }
}
})
const databaseOperations = new DatabaseOperations(pool)

const filterParser = new FilterParser()
const dataProvider = new DataProvider(pool, filterParser)
const schemaProvider = new SchemaProvider(pool)

return { dataProvider: dataProvider, schemaProvider: schemaProvider, databaseOperations, connection: pool, cleanup: async () => await pool.close() }
return { dataProvider: dataProvider, schemaProvider: schemaProvider, databaseOperations, connection: pool, cleanup }
}

module.exports = init
21 changes: 8 additions & 13 deletions packages/external-db-mssql/lib/mssql_operations.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,21 @@
const { notThrowingTranslateErrorCodes } = require('./sql_exception_translator')
const { DbConnectionError } = require('velo-external-db-commons').errors

class DatabaseOperations {
constructor(pool) {
this.sql = pool
}

async validateConnection() {
try {
const sql = await this.sql
const sql = await this.sql
if (sql._connected) {
return await sql.query('SELECT 1')
.then(() => { return { valid: true } })
.catch((e) => { return { valid: false, error: notThrowingTranslateErrorCodes(e) } })
} catch (err) {
switch (err.code) {
case 'ELOGIN':
return { valid: false, error: new DbConnectionError(`Access to database denied - probably wrong credentials, sql message: ${err.message}`) }
case 'ESOCKET':
return { valid: false, error: new DbConnectionError(`Access to database denied - host is unavailable, sql message: ${err.message}`) }
}
throw new Error(`Unrecognized error: ${err.message}`)
.then(() => { return { valid: true } })
.catch((e) => { return { valid: false, error: notThrowingTranslateErrorCodes(e) } })
}
return await sql.connect()
.then(() => { return { valid: true } })
.catch((e) => { return { valid: false, error: notThrowingTranslateErrorCodes(e) } })

}
}

Expand Down
40 changes: 26 additions & 14 deletions packages/external-db-mssql/lib/sql_exception_translator.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,31 @@
const { CollectionDoesNotExists, FieldAlreadyExists, FieldDoesNotExist, CollectionAlreadyExists } = require('velo-external-db-commons').errors
const { CollectionDoesNotExists, FieldAlreadyExists, FieldDoesNotExist, CollectionAlreadyExists,DbConnectionError } = require('velo-external-db-commons').errors

const notThrowingTranslateErrorCodes = err => {
switch (err.number) {
case 4902:
return new CollectionDoesNotExists('Collection does not exists')
case 2705:
return new FieldAlreadyExists('Collection already has a field with the same name')
case 4924:
return new FieldDoesNotExist('Collection does not contain a field with this name')
case 2714:
return new CollectionAlreadyExists('Collection already exists')
default:
console.log(err.number)
console.log(err)
return new Error(`default ${err.sqlMessage}`)
if (err.number) {
switch (err.number) {
case 4902:
return new CollectionDoesNotExists('Collection does not exists')
case 2705:
return new FieldAlreadyExists('Collection already has a field with the same name')
case 4924:
return new FieldDoesNotExist('Collection does not contain a field with this name')
case 2714:
return new CollectionAlreadyExists('Collection already exists')
default:
console.log(err.number)
console.log(err)
return new Error(`default ${err.sqlMessage}`)
}
}
else {
switch (err.code){
case 'ELOGIN':
return new DbConnectionError(`Access to database denied - probably wrong credentials, sql message: ${err.message}`)
case 'ESOCKET':
return new DbConnectionError(`Access to database denied - host is unavailable, sql message: ${err.message}`)
default:
return new Error(`default ${err.sqlMessage}`)
}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const { ConnectionPool } = require('mssql')
const DatabaseOperations = require('../../lib/mssql_operations')

const createPool = modify => {
const createPool = async modify => {
const config = {
user: 'sa',
password: 't9D4:EHfU6Xgccs-',
Expand All @@ -20,17 +20,18 @@ const createPool = modify => {
}

const _pool = new ConnectionPool(Object.assign({}, config, modify ))
return _pool.connect()
const pool = await _pool.connect().then((pool) => { return pool }).catch(() => { return _pool })
return pool
}

const dbOperationWithMisconfiguredPassword = () => new DatabaseOperations(createPool( { password: 'wrong'} ))
const dbOperationWithMisconfiguredPassword = async () => new DatabaseOperations(await createPool({ password: 'wrong' }))

const dbOperationWithMisconfiguredDatabase = () => new DatabaseOperations(createPool( { database: 'wrong'} ))
const dbOperationWithMisconfiguredDatabase = async () => new DatabaseOperations(await createPool({ database: 'wrong' }))

const dbOperationWithMisconfiguredHost = () => new DatabaseOperations(createPool( { server: 'wrong'} ))
const dbOperationWithMisconfiguredHost = async () => new DatabaseOperations(await createPool({ server: 'wrong' }))

const dbOperationWithValidDB = () => {
const connection = createPool({ } )
const dbOperationWithValidDB = async () => {
const connection = await createPool({ })
const dbOperations = new DatabaseOperations( connection )

return { dbOperations, cleanup: async () => await (await connection).close()}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const testSuits = () => [
['Postgres', postgresTestEnvInit],
['Spanner', spannerTestEnvInit],
['Firestore', firestoreTestEnvInit],
// ['Sql Server', mssqlTestEnvInit],
['Sql Server', mssqlTestEnvInit],
].filter( ([name]) => name.toLowerCase() === process.env.TEST_ENGINE || (name === 'Sql Server' && process.env.TEST_ENGINE === 'mssql') )


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ describe('Check Pool Connection', () => {
})

test('pool connection with wrong password will throw AccessDeniedError.', async () => {
const dbOperation = env.driver.dbOperationWithMisconfiguredPassword()
const dbOperation = await env.driver.dbOperationWithMisconfiguredPassword()

const validateConnection = await dbOperation.validateConnection()

Expand All @@ -22,7 +22,7 @@ describe('Check Pool Connection', () => {

test('pool connection with wrong database will throw DatabaseDoesNotExists.', async () => {
if (dbType !== 'Firestore') {
const dbOperation = env.driver.dbOperationWithMisconfiguredDatabase()
const dbOperation = await env.driver.dbOperationWithMisconfiguredDatabase()

const validateConnection = await dbOperation.validateConnection()

Expand All @@ -33,7 +33,7 @@ describe('Check Pool Connection', () => {

test('pool connection with wrong host will throw HostDoesNotExists.', async () => {
if (dbType !== 'Firestore') {
const dbOperation = env.driver.dbOperationWithMisconfiguredHost()
const dbOperation = await env.driver.dbOperationWithMisconfiguredHost()

const validateConnection = await dbOperation.validateConnection()

Expand All @@ -44,7 +44,7 @@ describe('Check Pool Connection', () => {
})

test('pool connection with valid DB will not throw', async () => {
const { dbOperations, cleanup } = env.driver.dbOperationWithValidDB()
const { dbOperations, cleanup } = await env.driver.dbOperationWithValidDB()

const validateConnection = await dbOperations.validateConnection()

Expand Down