Skip to content

Commit 6ebbd10

Browse files
committed
Make option parsing more conformant to libpq behaviour.
Fixes #162
1 parent 192bc5d commit 6ebbd10

File tree

2 files changed

+20
-14
lines changed

2 files changed

+20
-14
lines changed

conn.go

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,6 @@ func (s *scanner) SkipSpaces() (rune, bool) {
187187
func parseOpts(name string, o values) error {
188188
s := newScanner(name)
189189

190-
top:
191190
for {
192191
var (
193192
keyRunes, valRunes []rune
@@ -203,25 +202,25 @@ top:
203202
for !unicode.IsSpace(r) && r != '=' {
204203
keyRunes = append(keyRunes, r)
205204
if r, ok = s.Next(); !ok {
206-
break top
205+
break
207206
}
208207
}
209208

210209
// Skip any whitespace if we're not at the = yet
211210
if r != '=' {
212-
if r, ok = s.SkipSpaces(); !ok {
213-
break
214-
}
211+
r, ok = s.SkipSpaces()
215212
}
216213

217214
// The current character should be =
218-
if r != '=' {
215+
if r != '=' || !ok {
219216
return fmt.Errorf(`missing "=" after %q in connection info string"`, string(keyRunes))
220217
}
221218

222219
// Skip any whitespace after the =
223220
if r, ok = s.SkipSpaces(); !ok {
224-
break top
221+
// If we reach the end here, the last value is just an empty string as per libpq.
222+
o.Set(string(keyRunes), "")
223+
break
225224
}
226225

227226
if r != '\'' {

conn_test.go

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -678,28 +678,35 @@ func TestParseOpts(t *testing.T) {
678678
{"dbname=hello user= goodbye", values{"dbname": "hello", "user": "goodbye"}, true},
679679
{"host=localhost password='correct horse battery staple'", values{"host": "localhost", "password": "correct horse battery staple"}, true},
680680
{"dbname=データベース password=パスワード", values{"dbname": "データベース", "password": "パスワード"}, true},
681+
{"dbname=hello user=''", values{"dbname": "hello", "user": ""}, true},
682+
{"user='' dbname=hello", values{"dbname": "hello", "user": ""}, true},
683+
// The last option value is an empty string if there's no non-whitespace after its =
684+
{"dbname=hello user= ", values{"dbname": "hello", "user": ""}, true},
681685

682686
// The parser ignores spaces after = and interprets the next set of non-whitespace characters as the value.
683687
{"user= password=foo", values{"user": "password=foo"}, true},
684688

685-
// The parser ignores trailing keys
686-
{"user=foo blah", values{"user": "foo"}, true},
687-
{"user=foo blah ", values{"user": "foo"}, true},
688-
{"user=foo blah= ", values{"user": "foo"}, true},
689-
690689
// No '=' after the key
690+
{"postgre://marko@internet", values{}, false},
691691
{"dbname user=goodbye", values{}, false},
692+
{"user=foo blah", values{}, false},
693+
{"user=foo blah ", values{}, false},
694+
692695
// Unterminated quoted value
693696
{"dbname=hello user='unterminated", values{}, false},
694697
}
695698

696699
for _, test := range tests {
697700
o := make(values)
698701
err := parseOpts(test.in, o)
699-
if err != nil && test.valid {
702+
703+
switch {
704+
case err != nil && test.valid:
700705
t.Errorf("%q got unexpected error: %s", test.in, err)
701-
} else if err == nil && !reflect.DeepEqual(test.expected, o) {
706+
case err == nil && test.valid && !reflect.DeepEqual(test.expected, o):
702707
t.Errorf("%q got: %#v want: %#v", test.in, o, test.expected)
708+
case err == nil && !test.valid:
709+
t.Errorf("%q expected an error", test.in)
703710
}
704711
}
705712
}

0 commit comments

Comments
 (0)