PGconn#quote_ident の有無

昨日 PGconn#quote_ident - Rubyとか Illustratorとか SFとか折紙とか の続き。
大事な事、Debian lenny で libpgsql-ruby を使ってた方は大丈夫だったです、他でも新しめの環境なら大丈夫なのでしょう。

  1. Rails(ActiveRecord) 2.3.3 <- 2.3.2 のヴァージョンアップで、activerecord-2.3.#/lib/active_record/connection_adapters/postgresql_adapter.rb の中の quote_column_name(name)メソッドの実装が変わった
    • 単に「%("#{name}")」としていたものから「PGconn.quote_ident(name.to_s)」へ
  2. Debian の libpgsql-ruby1.8 の提供する Rubyライブラリは lenny では pg.so だが、etch では postgres.so たった
    • postgres.so の提供する PGconnクラスに所要の quote_ident は定義されていない
  3. それはそれとして上記 postgresql_adapter.rb 冒頭ではまずライブラリでかジェムでか知らず 'pg' を requireしようとし、駄目だったら 'postgres' を requireする(そしてメソッド名とかちょこっと調整する)

という訳で、未だに Debian etch を引きずってるのが駄目だった模様。

etchの場合

そういうわけで、ActiveRecord(postgresql_adapter.rb) のライブラリ切換えを利用することにして、site_ruby にちょっと pg.rb とか置いて誤摩化す。これで Railsアプリケーションレベルでの昨日みたいなちょっとなんとかはせずに済むようになる。

/usr/local/lib/site_ruby/pg.rb

require 'postgres'

class PGconn
  unless self.respond_to? :quote_ident then
    def self.quote_ident(name)
      '"' + name + '"'
    end # def self.quote_ident(name)
  end # unless self.respond_to? :quote_ident
end # class PGconn

class PGresult
  alias_method :nfields, :num_fields unless self.method_defined?(:nfields)
  alias_method :ntuples, :num_tuples unless self.method_defined?(:ntuples)
  alias_method :ftype, :type unless self.method_defined?(:ftype)
  alias_method :cmd_tuples, :cmdtuples unless self.method_defined?(:cmd_tuples)
end # class PGresult

site_ruby か site_ruby/1.8 か、或いは vender_ruby以下とかは大変迷う。 PGresult方面は上記 postgresql_adapter.rb 冒頭での調整事項、ここが繰り返しになるのはちょっとやなんだけどね

Windowsの場合

こっちの方ではポスグレのドライバーとしては gem の postgres-pr を使っている (PostgreSQLサーバ自体は近在の Linux機)。そして gem の postgres はコンパイル不能でやっぱりインストール出来ない。「Could not find PostgreSQL build environment (libraries & headers): Makefile not created」

上記 etch での措置と同じやり方でも誤魔化せそうなんだけど折角 postgres-pr というちょっとだけ違う名前が使えるのでなんかやってみる。

C:\Program Files\ruby-1.8\lib\ruby\site_ruby\postgres.rb

require 'rubygems'
require 'postgres-pr/postgres-compat'

class PGconn
  unless self.respond_to? :quote_ident then
    def self.quote_ident(name)
      '"' + name + '"'
    end # def self.quote_ident(name)
  end # unless self.respond_to? :quote_ident
end # class PGconn

postgres-prジェムの入れる postgres.rb は乗っ取ってしまうがその中でやってるのは postgres-pr/postgres-compat の呼び出しなのでそれを代行。rubygems を require しておくべきかどうかは微妙だが、いつもいつも Rails方面からの require だけでもあるまいと考えて。
pg として振舞うわけではだいので etch の時のようなメソッド名調整は無くて良い、そこはちょっとすっきりした。

関係ないけど rake cucumber:all

関係ないけどそんなことしてる間に「rake features」は時代遅れになっていた。「rake cucumber:all」だって、あと「ok」「wip」(work in progress 絶賛開発中)モードとか。