Skip to content

Feature Request: Support for Quoted Identifiers #1276

@matejcerny

Description

@matejcerny

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions