# 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