Repository: tediousjs/node-mssql (js)

Issue:
Connection strings formatted like "Data source=address\instance,port..." are not parsed correctly
The code that parses the connection strings seems to correctly parse

`Data source=address,port`

and

`Data source=address\instance`

and 

`Data source=address,port\instance`

but not

`Data source=address\instance,port`

which is a valid format when using ADO.NET. But when using mssql to connect using this format the port is always left as the default 1433.

Pull request description:
Support named instances with ports
What this does:

At the moment this port will be ignored by tedious, but this at least parses the port out as requested.

Related issues:

Fixes #1519

Pre/Post merge checklist:

- [x] Update change log


Patch:
diff --git a/CHANGELOG.txt b/CHANGELOG.txt
index 27cf725..959a094 100644
--- a/CHANGELOG.txt
+++ b/CHANGELOG.txt
@@ -1,4 +1,9 @@
-v9.1.1 (2023-01-??)
+v9.1.2 (2023-08-01)
+-------------------
+[fix] Support more named instance formats ([#1520](https://github.com/tediousjs/node-mssql/pull/1520))
+[refactor] Stop using deprecated regex symbols ([#1520](https://github.com/tediousjs/node-mssql/pull/1520))
+
+v9.1.1 (2023-01-19)
 -------------------
 [revert] Add support for AAD authentication via connection string ((#1436)[https://github.com/tediousjs/node-mssql/pull/1436])
 
diff --git a/README.md b/README.md
index c34aa8b..63f2fa2 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
 
 Microsoft SQL Server client for Node.js
 
-[![NPM Version][npm-image]][npm-url] [![NPM Downloads][downloads-image]][downloads-url] [![Travis CI][travis-image]][travis-url] [![Appveyor CI][appveyor-image]][appveyor-url] [![Join the chat at https://gitter.im/patriksimek/node-mssql](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/patriksimek/node-mssql?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
+[![NPM Version][npm-image]][npm-url] [![NPM Downloads][downloads-image]][downloads-url] [![Appveyor CI][appveyor-image]][appveyor-url] [![Join the chat at https://gitter.im/patriksimek/node-mssql](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/patriksimek/node-mssql?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
 
 Supported TDS drivers:
 - [Tedious][tedious-url] (pure JavaScript - Windows/macOS/Linux, default)
@@ -2093,8 +2093,6 @@ to create new connections or not
 [downloads-url]: https://www.npmjs.com/package/mssql
 [david-image]: https://img.shields.io/david/tediousjs/node-mssql.svg?style=flat-square
 [david-url]: https://david-dm.org/tediousjs/node-mssql
-[travis-image]: https://img.shields.io/travis/tediousjs/node-mssql/master.svg?style=flat-square&label=unit
-[travis-url]: https://travis-ci.org/tediousjs/node-mssql
 [appveyor-image]: https://ci.appveyor.com/api/projects/status/e5gq1a0ujwams9t7/branch/master?svg=true
 [appveyor-url]: https://ci.appveyor.com/project/tediousjs/node-mssql
 
diff --git a/lib/base/connection-pool.js b/lib/base/connection-pool.js
index eb468f2..6dcc6fa 100644
--- a/lib/base/connection-pool.js
+++ b/lib/base/connection-pool.js
@@ -64,9 +64,10 @@ class ConnectionPool extends EventEmitter {
     this.config.arrayRowMode = this.config.arrayRowMode || false
     this.config.validateConnection = 'validateConnection' in this.config ? this.config.validateConnection : true
 
-    if (/^(.*)\\(.*)$/.exec(this.config.server)) {
-      this.config.server = RegExp.$1
-      this.config.options.instanceName = RegExp.$2
+    const namedServer = /^(.*)\\(.*)$/.exec(this.config.server)
+    if (namedServer) {
+      this.config.server = namedServer[1]
+      this.config.options.instanceName = namedServer[2]
     }
 
     if (typeof this.config.options.useColumnNames !== 'undefined' && this.config.options.useColumnNames !== true) {
@@ -149,13 +150,21 @@ class ConnectionPool extends EventEmitter {
           if (/^tcp:/i.test(server)) {
             server = server.substr(4)
           }
-          if (/^(.*)\\(.*)$/.exec(server)) {
-            server = RegExp.$1
-            instanceName = RegExp.$2
+          const namedServerParts = /^(.*)\\(.*)$/.exec(server)
+          if (namedServerParts) {
+            server = namedServerParts[1].trim()
+            instanceName = namedServerParts[2].trim()
           }
-          if (/^(.*),(.*)$/.exec(server)) {
-            server = RegExp.$1.trim()
-            port = parseInt(RegExp.$2.trim(), 10)
+          const serverParts = /^(.*),(.*)$/.exec(server)
+          if (serverParts) {
+            server = serverParts[1].trim()
+            port = parseInt(serverParts[2].trim(), 10)
+          } else {
+            const instanceParts = /^(.*),(.*)$/.exec(instanceName)
+            if (instanceParts) {
+              instanceName = instanceParts[1].trim()
+              port = parseInt(instanceParts[2].trim(), 10)
+            }
           }
           if (server === '.' || server === '(.)' || server.toLowerCase() === '(localdb)' || server.toLowerCase() === '(local)') {
             server = 'localhost'
@@ -239,9 +248,10 @@ class ConnectionPool extends EventEmitter {
         case 'user id': {
           let user = value
           let domain
-          if (/^(.*)\\(.*)$/.exec(user)) {
-            domain = RegExp.$1
-            user = RegExp.$2
+          const domainUser = /^(.*)\\(.*)$/.exec(user)
+          if (domainUser) {
+            domain = domainUser[1]
+            user = domainUser[2]
           }
           Object.assign(config, {
             domain,
diff --git a/lib/error/request-error.js b/lib/error/request-error.js
index e97eeb8..454ef0b 100644
--- a/lib/error/request-error.js
+++ b/lib/error/request-error.js
@@ -43,8 +43,9 @@ class RequestError extends MSSQLError {
     }
 
     this.name = 'RequestError'
-    if ((/^\[Microsoft\]\[SQL Server Native Client 11\.0\](?:\[SQL Server\])?([\s\S]*)$/).exec(this.message)) {
-      this.message = RegExp.$1
+    const parsedMessage = (/^\[Microsoft\]\[SQL Server Native Client 11\.0\](?:\[SQL Server\])?([\s\S]*)$/).exec(this.message)
+    if (parsedMessage) {
+      this.message = parsedMessage[1]
     }
   }
 }
diff --git a/lib/msnodesqlv8/request.js b/lib/msnodesqlv8/request.js
index 05852cc..c43502e 100644
--- a/lib/msnodesqlv8/request.js
+++ b/lib/msnodesqlv8/request.js
@@ -531,8 +531,9 @@ class Request extends BaseRequest {
         })
 
         req.on('info', msg => {
-          if ((/^\[Microsoft\]\[SQL Server Native Client 11\.0\](?:\[SQL Server\])?([\s\S]*)$/).exec(msg.message)) {
-            msg.message = RegExp.$1
+          const parsedMessage = (/^\[Microsoft\]\[SQL Server Native Client 11\.0\](?:\[SQL Server\])?([\s\S]*)$/).exec(msg.message)
+          if (parsedMessage) {
+            msg.message = parsedMessage[1]
           }
 
           this.emit('info', {


Test patch:
diff --git a/test/common/unit.js b/test/common/unit.js
index 0c98965..03418ad 100644
--- a/test/common/unit.js
+++ b/test/common/unit.js
@@ -386,3 +386,39 @@ describe('value handlers', () => {
     assert.strictEqual(sql.valueHandler.size, 0)
   })
 })
+
+describe('connection string parser', () => {
+  it('parses named instance and port', () => {
+    const config = BasePool.parseConnectionString('Data source=instance\\database,1234')
+    assert.deepStrictEqual(config, {
+      options: {
+        instanceName: 'database'
+      },
+      pool: {},
+      port: 1234,
+      server: 'instance'
+    })
+  })
+  it('parses named instance and port (with instance port)', () => {
+    const config = BasePool.parseConnectionString('Data source=instance,1234\\database')
+    assert.deepStrictEqual(config, {
+      options: {
+        instanceName: 'database'
+      },
+      pool: {},
+      port: 1234,
+      server: 'instance'
+    })
+  })
+  it('parses named instance', () => {
+    const config = BasePool.parseConnectionString('Data source=instance\\database')
+    assert.deepStrictEqual(config, {
+      options: {
+        instanceName: 'database'
+      },
+      pool: {},
+      port: 1433,
+      server: 'instance'
+    })
+  })
+})