Способы преодоления ActiveRecord::StatementInvalid: PG::AmbiguousFunction в rails или sql. (st_intersects не является уникальным именем функции)

Когда я запускаю эту команду в рельсах:

CensusBlockGroup.where{st_interects(:the_geom, buffer)}

который запускает эту команду в SQL:

SELECT "census_block_groups".* FROM "census_block_groups"  WHERE (st_intersects("census_block_groups"."proj_shape_3361", '002000000300000d2...'))

Я получаю эту ошибку:

ActiveRecord::StatementInvalid: PG::AmbiguousFunction: 
ERROR:  function st_intersects(geometry, unknown) is not unique
LINE 1: ...lock_groups".* FROM "census_block_groups"  WHERE (st_interse...
HINT:  Could not choose a best candidate function. You might need to add explicit type casts.

Я не знаю, как добавить явное приведение типов, и, честно говоря, не совсем понимаю, что это вообще значит. Я вижу, что функция st_intersects выше передается во втором параметре, который является «неизвестным». Возможно, я мог бы «отлить» это и заставить это работать...?

Я думаю, проблема может заключаться в том, что в postgresql существует несколько определений функций st_intersects из-за его функции «перегрузки функций». Я не первый разработчик, установивший postgresql/postgis в эту систему, это сделал мой подрядчик, поэтому я обеспокоен тем, что мы могли дублировать наши усилия.

Я запускаю сервер rails, используя postgresql и postgis на Ubuntu «12.04 LTS» VPS.

Я почти уверен, что мог бы просто переустановить postgis, но это уничтожило бы код моего подрядчика, который делает довольно сложные вещи с pg_routing, которые я не хочу трогать. Если мне нужно, я просто загружу свежий линод и запущу на нем код, но это кажется расточительным и, возможно, даже более значительным, чем своего рода поражение.

Если я не могу правильно решить проблему, удалив двусмысленность (это обычно работает для меня на Mac и Linux-дистрибутивах), я думаю, что другим решением было бы пометить postgresql, чтобы он игнорировал двусмысленность, и просто выбрать первую функцию st_intersects, с которой она сталкивается. .

Другие примечания:

  • Фабрика геометрии, которую я использую в rgeo, называется «Geos».
  • геометрия декартова, а не географическая

Подобные вопросы (которые до сих пор заставляют меня ломать голову как разработчика рельсов, искалеченного ORM):


person boulder_ruby    schedule 25.09.2015    source источник


Ответы (1)


Я никогда не работал с Rails, но действительно, в PostgreSQL функция ST_Intersects имеет переопределение, что означает, что в зависимости от типа аргументов должна вызываться другая функция.

В данном случае это переопределения:

логическое значение ST_Intersects(геометрия geomA, геометрия geomB);

логическое значение ST_Intersects(география geogA, география geogB);

На основе сгенерированного запроса, отображаемого вами, PostgreSQL может быть трудно определить, какую функцию запускать, добавление явного приведения (способ указать тип определенного значения) скажет, какую функцию следует вызывать.

Для этого в PostgreSQL просто используйте «::» после значения, например:

ГЕОМЕТРИЯ:

SELECT ST_Intersects('POINT(0 0)'::geometry, 'LINESTRING ( 0 0, 0 2 )'::geometry);

Поэтому убедитесь, что оба значения :the_geom и buffer соответствуют типу геометрии, и все будет в порядке. Может быть, в ActiveRecord есть способ явного изменения типов? Или вы можете написать запрос прямо в PostgreSQL?

(источник: http://postgis.net/docs/ST_Intersects.html)

person Felippe Rangel    schedule 25.09.2015
comment
Я смог заставить это работать, когда научился делать пару вещей. 1.) Я узнал, что могу создавать области класса AR, а затем запускать для них #to_sql, чтобы модифицировать код SQL 2.) генерировать правильные строки SQL для выполнения с использованием методов (или лямбда-выражений в моем случае). В моем случае я переключил двоичный код на WKT, используя метод #as_text 3. добавление EPSG=4326; в текст WKT, чтобы postgis учитывал правильный SRID. 4.) запуск этого необработанного sql через ActiveRecord::Base.connection.select_rows(sql) - person boulder_ruby; 28.09.2015
comment
Я не в восторге от этой изолированной области серьезной сложности в моей кодовой базе, но, честно говоря, как программиста ГИС на рельсах, меня не слишком беспокоит запутанное решение, видя, что оно работает. - person boulder_ruby; 28.09.2015
comment
Рад, что у вас есть решатель boulder_ruby! Просто будьте осторожны с SQL-инъекциями при выполнении операторов RAW SQL. - person Felippe Rangel; 28.09.2015
comment
Вернулись к этому вопросу снова, забыв, как я его решил. Такой простой код смог решить проблему двусмысленности. where("st_intersects(proj_shape_4326, ST_GeomFromText('#{shp.as_text}',4326))") - person boulder_ruby; 03.01.2017