开发者

JRuby on Rails using jdbc postgres (8.4) ignores Default values

开发者 https://www.devze.com 2023-02-09 18:17 出处:网络
I have a table created in a migration (only to simplify the problem) that looks like this: create_table :test_defaults, :force => true do |table|

I have a table created in a migration (only to simplify the problem) that looks like this:

create_table :test_defaults, :force => true do |table|
     table.integer   :failure,       :default => -1, :null => false
end

So, one column named failure. When I execute this rails command:

td = TestDefault.create!

JRuby fails with:

ActiveRecord::StatementInvalid: ActiveRecord::JDBCError: ERROR: null value in column
"failure" violates not-null constraint: INSERT INTO "test_defaults" ("failure")
VALUES(NULL) RETURNING "id"

whereas the ruby version succeeds with a query like this:

INSERT INTO "test_defaults" ("failure") VALUES(-1) RETURNING "id"

I'm running:

ruby 1.8.7, 
rails 2.2.2, 
jruby 1.5.6, 
activerecord-jdbc-adapter (1.1.0)
activerecord-jdbcpostgresql-adapter (1.1.0)
jdbc-postgres (8.4.702)

Suggestions are appreciated. Haven't been able to find anything helpful on google, 开发者_Go百科and don't even know who to report the bug to.

Cheers.

EDIT: Ha. Seems it only happens with negative defaults. Zero and greater is fine.

EDIT2: From my answer below, it's a code problem around brackets on negative default values in postgres 8.4. If someone can suggest a way around this issue without waiting for a gem upgrade (like telling postgres to remove those brackets), it would be much appreciated.


Ok. Found the answer to this one:

activerecord-jdbc-adapter-1.1.0/lib/arjdbc/postgresql/adapter.rb

we have the lines (@59):

def default_value(value)
    # Boolean types
    return "t" if value =~ /true/i
    return "f" if value =~ /false/i

    # Char/String/Bytea type values
    return $1 if value =~ /^'(.*)'::(bpchar|text|character varying|bytea)$/

    # Numeric values
    return value if value =~ /^-?[0-9]+(\.[0-9]*)?/

    # Fixed dates / timestamp
    return $1 if value =~ /^'(.+)'::(date|timestamp)/

    # Anything else is blank, some user type, or some function
    # and we can't know the value of that, so return nil.
    return nil
  end
end

When the negative default value is returned from postgres, it returns, say, "(-1)" inside brackets. However, the above regex for numbers doesn't match on brackets.

Tried to register to log a bug (on http://kenai.com/jira/browse/ACTIVERECORD_JDBC), but the server was failing during registration.

EDIT: Created bug: http://kenai.com/jira/browse/ACTIVERECORD_JDBC-151

EDIT: Also ended up needing this in the same place as the previous code. "(-1)".to_i returns 0, which is usually bad.

    def type_cast(value)
        case type
            when :integer then value = remove_brackets_from_negative(value)
        end
        super
    end
    def remove_brackets_from_negative(value)
        value.gsub!(/[\)\(]/,"") if value.is_a?(String)
        value
    end
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号