-
-
Notifications
You must be signed in to change notification settings - Fork 166
Description
Currently, Skunk's Identifier models a Postgres Unquoted Identifier:
SQL identifiers and key words must begin with a letter or an underscore (_). Subsequent characters in an identifier or key word can be letters, underscores, digits (0-9), or dollar signs ($)
However, Skunk currently has no way to represent Postgres Quoted Identifiers:
There is a second kind of identifier: the delimited identifier or quoted identifier. It is formed by enclosing an arbitrary sequence of characters in double-quotes ("). (...) Quoted identifiers can contain any character, except the character with code zero.
Source: Lexical Structure
The Use Case / Blocker
I am currently building a Scala integration for PGMQ (a popular Postgres message queue extension). PGMQ uses LISTEN / NOTIFY channels formatted with dots, for example: pgmq.q_my_queue.INSERT. Because this contains a dot (.), it is an invalid unquoted identifier, but a perfectly valid quoted identifier in Postgres.
Since Identifier is a sealed abstract case class, library authors are completely locked out of constructing these valid quoted identifiers, forced to use raw #$ string interpolation to execute LISTEN commands.
Proposed Solution
I propose adding a new smart constructor to the Identifier companion object:
def fromStringQuoted(s: String): Either[String, Identifier] = {
if (s.length > maxLen)
Left(s"Identifier too long: ${s.length} (max allowed is $maxLen)")
else if (s.contains("\u0000"))
Left("Illegal identifier: cannot contain the null byte (\\u0000).")
else
// Wraps the valid string in double quotes so it is sent to Postgres correctly
Right(new Identifier(s""""$s"""") {})
}Alternatively, if expanding the safe API is not desired, exposing an unsafeFromString(s: String): Identifier escape hatch would allow library authors to handle the quoting and validation themselves.