Skip to content

Commit 473e93d

Browse files
cbandygkech
authored andcommitted
Move SQL escape functions to the Postgres package
These are specific to Postgres. Add tests and remove unused functions.
1 parent eab9b88 commit 473e93d

File tree

5 files changed

+44
-68
lines changed

5 files changed

+44
-68
lines changed

internal/pgbouncer/postgres.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ func sqlAuthenticationQuery(sqlFunctionName string, exposeSuperusers bool) strin
4040
// No replicators.
4141
`NOT pg_authid.rolreplication`,
4242
// Not the PgBouncer role itself.
43-
`pg_authid.rolname <> ` + util.SQLQuoteLiteral(postgresqlUser),
43+
`pg_authid.rolname <> ` + postgres.QuoteLiteral(postgresqlUser),
4444
// Those without a password expiration or an expiration in the future.
4545
`(pg_authid.rolvaliduntil IS NULL OR pg_authid.rolvaliduntil >= CURRENT_TIMESTAMP)`,
4646
}
@@ -57,7 +57,7 @@ func sqlAuthenticationQuery(sqlFunctionName string, exposeSuperusers bool) strin
5757

5858
return strings.TrimSpace(`
5959
CREATE OR REPLACE FUNCTION ` + sqlFunctionName + `(username TEXT)
60-
RETURNS TABLE(username TEXT, password TEXT) AS ` + util.SQLQuoteLiteral(`
60+
RETURNS TABLE(username TEXT, password TEXT) AS ` + postgres.QuoteLiteral(`
6161
SELECT rolname::TEXT, rolpassword::TEXT
6262
FROM pg_catalog.pg_authid
6363
WHERE pg_authid.rolname = $1

internal/pgbouncer/postgres_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,14 @@ import (
1919
func TestSQLAuthenticationQuery(t *testing.T) {
2020
assert.Equal(t, sqlAuthenticationQuery("some.fn_name", false),
2121
`CREATE OR REPLACE FUNCTION some.fn_name(username TEXT)
22-
RETURNS TABLE(username TEXT, password TEXT) AS '
22+
RETURNS TABLE(username TEXT, password TEXT) AS E'
2323
SELECT rolname::TEXT, rolpassword::TEXT
2424
FROM pg_catalog.pg_authid
2525
WHERE pg_authid.rolname = $1
2626
AND pg_authid.rolcanlogin
2727
AND NOT pg_authid.rolsuper
2828
AND NOT pg_authid.rolreplication
29-
AND pg_authid.rolname <> ''_crunchypgbouncer''
29+
AND pg_authid.rolname <> E''_crunchypgbouncer''
3030
AND (pg_authid.rolvaliduntil IS NULL OR pg_authid.rolvaliduntil >= CURRENT_TIMESTAMP)'
3131
LANGUAGE SQL STABLE SECURITY DEFINER;`)
3232
}
@@ -164,14 +164,14 @@ REVOKE ALL PRIVILEGES
164164
GRANT USAGE
165165
ON SCHEMA :"namespace" TO :"username";
166166
CREATE OR REPLACE FUNCTION :"namespace".get_auth(username TEXT)
167-
RETURNS TABLE(username TEXT, password TEXT) AS '
167+
RETURNS TABLE(username TEXT, password TEXT) AS E'
168168
SELECT rolname::TEXT, rolpassword::TEXT
169169
FROM pg_catalog.pg_authid
170170
WHERE pg_authid.rolname = $1
171171
AND pg_authid.rolcanlogin
172172
AND NOT pg_authid.rolsuper
173173
AND NOT pg_authid.rolreplication
174-
AND pg_authid.rolname <> ''_crunchypgbouncer''
174+
AND pg_authid.rolname <> E''_crunchypgbouncer''
175175
AND (pg_authid.rolvaliduntil IS NULL OR pg_authid.rolvaliduntil >= CURRENT_TIMESTAMP)'
176176
LANGUAGE SQL STABLE SECURITY DEFINER;
177177
REVOKE ALL PRIVILEGES

internal/postgres/sql.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright 2021 - 2024 Crunchy Data Solutions, Inc.
2+
//
3+
// SPDX-License-Identifier: Apache-2.0
4+
5+
package postgres
6+
7+
import "strings"
8+
9+
// escapeLiteral is called by QuoteLiteral to add backslashes before special
10+
// characters of the "escape" string syntax. Double quote marks to escape them
11+
// regardless of the "backslash_quote" parameter.
12+
var escapeLiteral = strings.NewReplacer(`'`, `''`, `\`, `\\`).Replace
13+
14+
// QuoteLiteral escapes v so it can be safely used as a literal (or constant)
15+
// in an SQL statement.
16+
func QuoteLiteral(v string) string {
17+
// Use the "escape" syntax to ensure that backslashes behave consistently regardless
18+
// of the "standard_conforming_strings" parameter. Include a space before so
19+
// the "E" cannot change the meaning of an adjacent SQL keyword or identifier.
20+
// - https://www.postgresql.org/docs/current/sql-syntax-lexical.html
21+
return ` E'` + escapeLiteral(v) + `'`
22+
}

internal/postgres/sql_test.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Copyright 2021 - 2024 Crunchy Data Solutions, Inc.
2+
//
3+
// SPDX-License-Identifier: Apache-2.0
4+
5+
package postgres
6+
7+
import (
8+
"testing"
9+
10+
"gotest.tools/v3/assert"
11+
)
12+
13+
func TestQuoteLiteral(t *testing.T) {
14+
assert.Equal(t, QuoteLiteral(``), ` E''`)
15+
assert.Equal(t, QuoteLiteral(`ab"cd\ef'gh`), ` E'ab"cd\\ef''gh'`)
16+
}

internal/util/util.go

Lines changed: 0 additions & 62 deletions
This file was deleted.

0 commit comments

Comments
 (0)