72 lines
2.7 KiB
Go
72 lines
2.7 KiB
Go
package pq
|
|
|
|
import (
|
|
"bytes"
|
|
"strings"
|
|
)
|
|
|
|
// QuoteIdentifier quotes an "identifier" (e.g. a table or a column name) to be
|
|
// used as part of an SQL statement. For example:
|
|
//
|
|
// tblname := "my_table"
|
|
// data := "my_data"
|
|
// quoted := pq.QuoteIdentifier(tblname)
|
|
// err := db.Exec(fmt.Sprintf("INSERT INTO %s VALUES ($1)", quoted), data)
|
|
//
|
|
// Any double quotes in name will be escaped. The quoted identifier will be case
|
|
// sensitive when used in a query. If the input string contains a zero byte, the
|
|
// result will be truncated immediately before it.
|
|
func QuoteIdentifier(name string) string {
|
|
end := strings.IndexRune(name, 0)
|
|
if end > -1 {
|
|
name = name[:end]
|
|
}
|
|
return `"` + strings.Replace(name, `"`, `""`, -1) + `"`
|
|
}
|
|
|
|
// BufferQuoteIdentifier satisfies the same purpose as QuoteIdentifier, but backed by a
|
|
// byte buffer.
|
|
func BufferQuoteIdentifier(name string, buffer *bytes.Buffer) {
|
|
// TODO(v2): this should have accepted an io.Writer, not *bytes.Buffer.
|
|
end := strings.IndexRune(name, 0)
|
|
if end > -1 {
|
|
name = name[:end]
|
|
}
|
|
buffer.WriteRune('"')
|
|
buffer.WriteString(strings.Replace(name, `"`, `""`, -1))
|
|
buffer.WriteRune('"')
|
|
}
|
|
|
|
// QuoteLiteral quotes a 'literal' (e.g. a parameter, often used to pass literal
|
|
// to DDL and other statements that do not accept parameters) to be used as part
|
|
// of an SQL statement. For example:
|
|
//
|
|
// exp_date := pq.QuoteLiteral("2023-01-05 15:00:00Z")
|
|
// err := db.Exec(fmt.Sprintf("CREATE ROLE my_user VALID UNTIL %s", exp_date))
|
|
//
|
|
// Any single quotes in name will be escaped. Any backslashes (i.e. "\") will be
|
|
// replaced by two backslashes (i.e. "\\") and the C-style escape identifier
|
|
// that PostgreSQL provides ('E') will be prepended to the string.
|
|
func QuoteLiteral(literal string) string {
|
|
// This follows the PostgreSQL internal algorithm for handling quoted literals
|
|
// from libpq, which can be found in the "PQEscapeStringInternal" function,
|
|
// which is found in the libpq/fe-exec.c source file:
|
|
// https://git.postgresql.org/gitweb/?p=postgresql.git;a=blob;f=src/interfaces/libpq/fe-exec.c
|
|
//
|
|
// substitute any single-quotes (') with two single-quotes ('')
|
|
literal = strings.Replace(literal, `'`, `''`, -1)
|
|
// determine if the string has any backslashes (\) in it.
|
|
// if it does, replace any backslashes (\) with two backslashes (\\)
|
|
// then, we need to wrap the entire string with a PostgreSQL
|
|
// C-style escape. Per how "PQEscapeStringInternal" handles this case, we
|
|
// also add a space before the "E"
|
|
if strings.Contains(literal, `\`) {
|
|
literal = strings.Replace(literal, `\`, `\\`, -1)
|
|
literal = ` E'` + literal + `'`
|
|
} else {
|
|
// otherwise, we can just wrap the literal with a pair of single quotes
|
|
literal = `'` + literal + `'`
|
|
}
|
|
return literal
|
|
}
|