Skip to content

Operation on mixed SRID geometries with Rails 7.2 & Postgis Adapter 10.x #429

@inkstak

Description

@inkstak

After upgrading to Rails 7.2 & Postgis Adapter 10.x, I've got the following error :

require "bundler/inline"

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

  gem "rails", "~> 7.2"
  # If you want to test against edge Rails replace the previous line with this:
  # gem "rails", github: "rails/rails", branch: "main"

  gem "pg"
  gem "activerecord-postgis-adapter", "~> 10.0"
end

require "active_record"
require "minitest/autorun"
require "logger"

# `createdb postgis_test_db`

# This connection will do for database-independent bug reports.
ActiveRecord::Base.establish_connection(
  "postgis://localhost/postgis_test_db"
)
ActiveRecord::Base.logger = Logger.new(STDOUT)

ActiveRecord::Schema.define do
  enable_extension 'postgis'

  create_table :areas, force: true do |t|
    t.geometry :geometry, srid: 4326
  end
end

class Area < ActiveRecord::Base
end

class BugTest < Minitest::Test
  def test_within
    center  = RGeo::Geos.factory(srid: 4326).point(3.808591, 43.606092)
    polygon = center.buffer(10_000)
    post    = Area.create!(geometry: polygon)

    assert_equal 1, Area.where("ST_Within(?, geometry)", center).count
  end
end
# Running:

D, [2025-04-28T17:44:27.673065 #36412] DEBUG -- :   TRANSACTION (0.1ms)  BEGIN
D, [2025-04-28T17:44:27.675503 #36412] DEBUG -- :   Area Create (2.6ms)  INSERT INTO "areas" ("geometry") VALUES ($1) RETURNING "id"  [["geometry", "0020000003000010e6000000010000000540c389e77fe8ee6c4045cd946c332f01400e77fe8ee6bd93c0c372326b93ccd1c0c38618801711944045cd946c332e55400e77fe8ee6a80840c39dcd946c332f40c389e77fe8ee6c4045cd946c332f01"]]
D, [2025-04-28T17:44:27.675846 #36412] DEBUG -- :   TRANSACTION (0.3ms)  COMMIT
D, [2025-04-28T17:44:27.686418 #36412] DEBUG -- :   Area Count (6.6ms)  SELECT COUNT(*) FROM "areas" WHERE (ST_Within($1, geometry))  [[nil, "POINT (3.808591 43.606092)"]]
E

Finished in 0.023273s, 42.9682 runs/s, 0.0000 assertions/s.

  1) Error:
BugTest#test_within:
ActiveRecord::StatementInvalid: PG::InternalError: ERROR:  contains: Operation on mixed SRID geometries (Polygon, 4326) != (Point, 0)

The same test with Rails 7.1 & Postgis Adapter 9.x won't raise any error, but it will send instead the following query :

SELECT COUNT(*) FROM "areas" WHERE (ST_Within('0020000001000010e6400e77fe8ee6b8304045cd946c332f01', geometry))

It seems to come from #417 (fixing #402) where Quoting#type_cast was introduce by calling to_s on RGeo::Feature::Instance

module ActiveRecord
  module ConnectionAdapters
    module PostGIS
      module Quoting
        def type_cast(value)
          case value
          when RGeo::Feature::Instance
            value.to_s
          else
            super
          end

I can only guess that WKB include the SRID while WKT does not.

The wordaround will be (copied from OID::Spatial#serialize) :

module ActiveRecord
  module ConnectionAdapters
    module PostGIS
      module Quoting
        def type_cast(value)
          case value
          when RGeo::Feature::Instance
            RGeo::WKRep::WKBGenerator
              .new(hex_format: true, type_format: :ewkb, emit_ewkb_srid: true)
              .generate(value)
          else
            super
          end
        end
      end
    end
  end
end

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions