rein icon indicating copy to clipboard operation
rein copied to clipboard

Schema-prefixed table names cause error

Open owst opened this issue 6 years ago • 0 comments

Description

If I try and add a length constraint to a table whose name is given with an explicit schema, the generate SQL is not valid:

add_length_constraint 'myschema.my_relations', :test_field, less_than_or_equal_to: 10

leads to:

ALTER TABLE "myschema.my_relations" ADD CONSTRAINT myschema.my_relations_test_field_length CHECK (length("test_field") <= 10)

Which fails with:

PG::SyntaxError: ERROR:  syntax error at or near "." (ActiveRecord::StatementInvalid)
LINE 1: ...LE "myschema.my_relations" ADD CONSTRAINT myschema.my_relati...
                                                             ^

The correct quoting of the table name is:

ALTER TABLE "myschema"."my_relations" 

and the constraint name would reasonably be called myschema_my_relations_test_field_length. This can be achieved with:

add_length_constraint '"myschema"."my_relations"', :test_field, less_than_or_equal_to: 10, name: :myschema_my_relations_test_field_length

but I think it would be nicer if rein handled this itself.

ActiveRecord::ConnectionAdapters::PostgreSQL::Quoting#quote_table_name seems like it solves some of the same issues - maybe it can be reused?

Reproduction

require "bundler/inline"

gemfile(true) do
  source "https://rubygems.org"

  gem "activerecord", "5.2.0"
  gem "rein"
  gem "pg"
end

require "active_record"
require "pg"
require "rein"

ActiveRecord::Base.establish_connection(
  adapter: "postgresql",
  database: "rein_schema_issue",
  username: ENV.fetch('PGUSER'),
  password: ENV.fetch('PGPASSWORD')
)
ActiveRecord::Base.logger = Logger.new(STDOUT)

class CreateMyRelation < ActiveRecord::Migration[5.0]
  def up
    execute "CREATE SCHEMA myschema"

    create_table 'myschema.my_relations' do |t|
      t.string :test_field
    end

    # Syntax error...
    add_length_constraint(
      'myschema.my_relations', 
      :test_field, less_than_or_equal_to: 10
    )
    # Works fine
    # add_length_constraint(
    #   '"myschema"."my_relations"',
    #   :test_field,
    #   less_than_or_equal_to: 10, name: :myschema_my_relations_test_field_length
    # )
  end
end

CreateMyRelation.migrate(:up)

Must be run with PGUSER and PGPASSWORD set in the environment, and the rein_schema_issue DB already existing

owst avatar Apr 09 '19 12:04 owst