# frozen_string_literal: true
module ActiveRecord
module ConnectionAdapters
module CipherStashPG
# Value Object to hold a schema qualified name.
# This is usually the name of a PostgreSQL relation but it can also represent
# schema qualified type names. +schema+ and +identifier+ are unquoted to prevent
# double quoting.
class Name # :nodoc:
SEPARATOR = "."
attr_reader :schema, :identifier
def initialize(schema, identifier)
@schema, @identifier = Utils.unquote_identifier(schema), Utils.unquote_identifier(identifier)
end
def to_s
parts.join SEPARATOR
end
def quoted
if schema
::CipherStashPG::Connection.quote_ident(schema) << SEPARATOR << ::CipherStashPG::Connection.quote_ident(identifier)
else
::CipherStashPG::Connection.quote_ident(identifier)
end
end
def ==(o)
o.class == self.class && o.parts == parts
end
alias_method :eql?, :==
def hash
parts.hash
end
protected
def parts
@parts ||= [@schema, @identifier].compact
end
end
module Utils # :nodoc:
extend self
# Returns an instance of ActiveRecord::ConnectionAdapters::PostgreSQL::Name
# extracted from +string+.
# +schema+ is +nil+ if not specified in +string+.
# +schema+ and +identifier+ exclude surrounding quotes (regardless of whether provided in +string+)
# +string+ supports the range of schema/table references understood by PostgreSQL, for example:
#
# * table_name
# * "table.name"
# * schema_name.table_name
# * schema_name."table.name"
# * "schema_name".table_name
# * "schema.name"."table name"
def extract_schema_qualified_name(string)
schema, table = string.scan(/[^".]+|"[^"]*"/)
if table.nil?
table = schema
schema = nil
end
CipherStashPG::Name.new(schema, table)
end
def unquote_identifier(identifier)
if identifier && identifier.start_with?('"')
identifier[1..-2]
else
identifier
end
end
end
end
end
end