8
8
*/
9
9
10
10
var dns = require ( 'dns' )
11
+ var async = require ( 'async' )
11
12
12
13
var defaults = require ( './defaults' )
13
14
14
- var parse = require ( 'pg-connection-string' ) . parse // parses a connection string
15
+ var parse = require ( 'connection-string' ) // parses a connection string
16
+ var pgparse = require ( 'pg-connection-string' ) . parse // parses unix domain a connection string
15
17
16
18
var val = function ( key , config , envVar ) {
17
19
if ( envVar === undefined ) {
@@ -41,30 +43,88 @@ var useSsl = function () {
41
43
}
42
44
43
45
var ConnectionParameters = function ( config ) {
44
- // if a string is passed, it is a raw connection string so we parse it into a config
45
- config = typeof config === 'string' ? parse ( config ) : config || { }
46
+ config = config || { }
47
+
48
+ // if a string is passed, it is a raw connection string so we define it as
49
+ // connectionString option and convert config to object
50
+ if ( typeof config === 'string' ) {
51
+ config = { connectionString : config }
52
+ }
46
53
47
54
// if the config has a connectionString defined, parse IT into the config we use
48
55
// this will override other default values with what is stored in connectionString
49
56
if ( config . connectionString ) {
50
- config = Object . assign ( { } , config , parse ( config . connectionString ) )
57
+ // a unix socket connection string starts from '/' or 'socket:'
58
+ if ( config . connectionString . indexOf ( '/' ) === 0 || config . connectionString . indexOf ( 'socket:' ) === 0 ) {
59
+ config = Object . assign ( { isDomainSocket : true } , config , pgparse ( config . connectionString ) )
60
+ // connection uri
61
+ } else {
62
+ config = Object . assign ( { } , config , parse ( config . connectionString ) )
63
+
64
+ // mimicrate connection-string object to postgrsql compatible
65
+ // convert path to database name
66
+ if ( Array . isArray ( config . path ) ) {
67
+ config . database = config . path [ 0 ]
68
+ }
69
+
70
+ // convert hosts list to host and port
71
+ if ( Array . isArray ( config . hosts ) ) {
72
+ config . host = config . hosts . map ( function ( host ) {
73
+ return host . name
74
+ } )
75
+ // take first port in hosts list
76
+ config . port = config . hosts [ 0 ] . port
77
+ }
78
+
79
+ // convert params to separeted options
80
+ if ( config . params && typeof config . params === 'object' ) {
81
+ Object . keys ( config . params ) . forEach ( function ( key ) {
82
+ var val = config . params [ key ]
83
+
84
+ switch ( val ) {
85
+ case 'true' :
86
+ val = true
87
+ break
88
+ case 'false' :
89
+ val = false
90
+ break
91
+ default :
92
+ var intVal = parseInt ( val )
93
+ if ( ! isNaN ( intVal ) ) {
94
+ val = intVal
95
+ }
96
+ }
97
+ config [ key ] = val
98
+ } )
99
+ }
100
+ }
51
101
}
52
102
53
103
this . user = val ( 'user' , config )
54
104
this . database = val ( 'database' , config )
55
105
this . port = parseInt ( val ( 'port' , config ) , 10 )
56
- this . host = val ( 'host' , config )
106
+ this . host = Array . isArray ( config . host ) ? config . host : val ( 'host' , config )
57
107
this . password = val ( 'password' , config )
58
108
this . binary = val ( 'binary' , config )
59
109
this . ssl = typeof config . ssl === 'undefined' ? useSsl ( ) : config . ssl
60
110
this . client_encoding = val ( 'client_encoding' , config )
61
111
this . replication = val ( 'replication' , config )
62
- // a domain socket begins with '/'
63
- this . isDomainSocket = ( ! ( this . host || '' ) . indexOf ( '/' ) )
112
+
113
+ this . isDomainSocket = false
114
+ if ( config . isDomainSocket ) {
115
+ this . isDomainSocket = config . isDomainSocket
116
+ }
117
+
118
+ // if host is string and its start from / use it as unix socket
119
+ if ( typeof this . host === 'string' && this . host . indexOf ( '/' ) === 0 ) {
120
+ this . isDomainSocket = true
121
+ }
64
122
65
123
this . application_name = val ( 'application_name' , config , 'PGAPPNAME' )
66
124
this . fallback_application_name = val ( 'fallback_application_name' , config , false )
67
125
this . statement_timeout = val ( 'statement_timeout' , config , false )
126
+
127
+ this . target_session_attrs = val ( 'target_session_attrs' , config )
68
128
}
69
129
70
130
// Convert arg to a string, surround in single quotes, and escape single quotes and backslashes
@@ -86,6 +146,7 @@ ConnectionParameters.prototype.getLibpqConnectionString = function (cb) {
86
146
add ( params , this , 'port' )
87
147
add ( params , this , 'application_name' )
88
148
add ( params , this , 'fallback_application_name' )
149
+ add ( params , this , 'target_session_attrs' )
89
150
90
151
var ssl = typeof this . ssl === 'object' ? this . ssl : { sslmode : this . ssl }
91
152
add ( params , ssl , 'sslmode' )
@@ -101,17 +162,17 @@ ConnectionParameters.prototype.getLibpqConnectionString = function (cb) {
101
162
params . push ( 'replication=' + quoteParamValue ( this . replication ) )
102
163
}
103
164
if ( this . host ) {
104
- params . push ( 'host=' + quoteParamValue ( this . host ) )
165
+ params . push ( 'host=' + quoteParamValue ( Array . isArray ( this . host ) ? this . host . join ( ',' ) : this . host ) )
105
166
}
106
167
if ( this . isDomainSocket ) {
107
168
return cb ( null , params . join ( ' ' ) )
108
169
}
109
170
if ( this . client_encoding ) {
110
171
params . push ( 'client_encoding=' + quoteParamValue ( this . client_encoding ) )
111
172
}
112
- dns . lookup ( this . host , function ( err , address ) {
173
+ async . map ( ( Array . isArray ( this . host ) ? this . host : [ this . host ] ) , dns . lookup , function ( err , addresses ) {
113
174
if ( err ) return cb ( err , null )
114
- params . push ( 'hostaddr=' + quoteParamValue ( address ) )
175
+ params . push ( 'hostaddr=' + quoteParamValue ( addresses . join ( ',' ) ) )
115
176
return cb ( null , params . join ( ' ' ) )
116
177
} )
117
178
}
0 commit comments