Skip to content

Commit 1f3e3d9

Browse files
Send datestyle as a startup parameter (#1312)
Previously it would gather all settings in a map and send everything except those in isDriverSetting() as a startup parameter. Most settings should not be sent as a startup parameter, except Options, ApplicationName, ClientEncoding, and Datestyle, but the Datestyle got lost with c8c8c81 Fixes #1306 Co-authored-by: Martin Tournoij <martin@arp242.net>
1 parent 32ba56b commit 1f3e3d9

File tree

3 files changed

+62
-22
lines changed

3 files changed

+62
-22
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@ unreleased
22
----------
33

44

5+
v1.12.3 (2026-04-03)
6+
--------------------
7+
- Send datestyle startup parameter, improving compatbility with database engines
8+
that use a different default datestyle such as EnterpriseDB ([#1312]).
9+
10+
[#1312]: https://github.com/lib/pq/pull/1312
11+
512
v1.12.2 (2026-04-02)
613
--------------------
714

conn.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1237,6 +1237,10 @@ func (cn *conn) startup(cfg Config) error {
12371237
w.string("client_encoding")
12381238
w.string(cfg.ClientEncoding)
12391239
}
1240+
if cfg.Datestyle != "" {
1241+
w.string("datestyle")
1242+
w.string(cfg.Datestyle)
1243+
}
12401244
for k, v := range cfg.Runtime {
12411245
w.string(k)
12421246
w.string(v)

connector_test.go

Lines changed: 51 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -113,28 +113,6 @@ func TestNewConnector(t *testing.T) {
113113
defer db.Close()
114114
useConn(t, db)
115115
})
116-
117-
t.Run("database=", func(t *testing.T) {
118-
// Cockroach allows connecting to any database name, although it does
119-
// give an error on DDL statements (but not "select;" / Ping()). Pretty
120-
// weird, but not really important to run this test there so whatever.
121-
pqtest.SkipCockroach(t)
122-
123-
want1, want2 := `or:pq: database "err" does not exist (3D000)|pq: no such database: err (08P01)`,
124-
`or:pq: database "two" does not exist (3D000)|pq: no such database: two (08P01)`
125-
126-
// Make sure database= consistently take precedence over dbname=
127-
for i := 0; i < 10; i++ {
128-
_, err := pqtest.DB(t, "database=err")
129-
if !pqtest.ErrorContains(err, want1) {
130-
t.Errorf("wrong error:\nhave: %s\nwant: %s", err, want1)
131-
}
132-
_, err = pqtest.DB(t, "dbname=one database=two")
133-
if !pqtest.ErrorContains(err, want2) {
134-
t.Errorf("wrong error:\nhave: %s\nwant: %s", err, want2)
135-
}
136-
}
137-
})
138116
}
139117

140118
// TODO: this can be merged with TestNewConfig, I think?
@@ -758,6 +736,57 @@ func TestConnectionTargetSessionAttrs(t *testing.T) {
758736
}
759737
}
760738

739+
func TestStartupParameters(t *testing.T) {
740+
tests := []struct {
741+
dsn string
742+
want map[string]string
743+
}{
744+
{"", map[string]string{"client_encoding": "UTF8", "database": "pqgo", "datestyle": "ISO, MDY", "user": "pqgo"}},
745+
746+
// Make sure database= works, and takes pre secede over dbname=
747+
{"dbname=A", map[string]string{"client_encoding": "UTF8", "database": "A", "datestyle": "ISO, MDY", "user": "pqgo"}},
748+
{"database=B", map[string]string{"client_encoding": "UTF8", "database": "B", "datestyle": "ISO, MDY", "user": "pqgo"}},
749+
{"dbname=A database=B", map[string]string{"client_encoding": "UTF8", "database": "B", "datestyle": "ISO, MDY", "user": "pqgo"}},
750+
}
751+
752+
pqtest.Unsetenv(t, "PGAPPNAME")
753+
for _, tt := range tests {
754+
t.Run("", func(t *testing.T) {
755+
var have map[string]string
756+
f := pqtest.NewFake(t, func(f pqtest.Fake, cn net.Conn) {
757+
_, params, ok := f.ReadStartup(cn)
758+
if !ok {
759+
return
760+
}
761+
have = params
762+
763+
f.WriteMsg(cn, proto.AuthenticationRequest, "\x00\x00\x00\x00")
764+
f.WriteMsg(cn, proto.ReadyForQuery, "I")
765+
for {
766+
code, _, ok := f.ReadMsg(cn)
767+
if !ok {
768+
return
769+
}
770+
switch code {
771+
case proto.Query:
772+
f.WriteMsg(cn, proto.EmptyQueryResponse, "")
773+
f.WriteMsg(cn, proto.ReadyForQuery, "I")
774+
case proto.Terminate:
775+
cn.Close()
776+
return
777+
}
778+
}
779+
})
780+
defer f.Close()
781+
782+
pqtest.MustDB(t, f.DSN()+" "+tt.dsn).Close()
783+
if !reflect.DeepEqual(have, tt.want) {
784+
t.Errorf("\nhave: %#v\nwant: %#v", have, tt.want)
785+
}
786+
})
787+
}
788+
}
789+
761790
func TestProtocolVersion(t *testing.T) {
762791
var (
763792
key30 = []byte{1, 2, 3, 4}

0 commit comments

Comments
 (0)