SQL炼金术:无效 SQL load_only、order_by 和限制
SQLAlchemy: Invalid SQL with load_only, order_by and limit
当运行下面的例子时,会生成以下无效的SQL查询:
SELECT anon_1.venue_id AS anon_1_venue_id,
St_asbinary(anon_1.venue_location) AS anon_1_venue_location,
St_asbinary(anon_1.anon_2) AS anon_1_anon_2,
label_1.id AS label_1_id
FROM (
SELECT venue.id AS venue_id,
venue.location AS venue_location,
venue.location <-> St_geomfromtext(:ST_GeomFromText_1,
:ST_GeomFromText_2) AS anon_2
FROM venue
ORDER BY venue.location <-> St_geomfromtext(:ST_GeomFromText_1,
:ST_GeomFromText_2)
LIMIT :param_1
) AS anon_1
LEFT OUTER JOIN (
venue_to_label AS venue_to_label_1
JOIN label AS label_1
ON label_1.id = venue_to_label_1.label_id)
ON anon_1.venue_id = venue_to_label_1.venue_id
ORDER BY anon_1.anon_2
问题是 St_asbinary 应用于 anon_1.anon_2。我希望该行不会生成,或者至少没有 "St_asbinary"。我很确定这是 GeoAlchemy2 的错。有人可以评论这个假设吗?
知道如何最好地解决这个问题吗?不幸的是,这似乎很基础。我们正在尝试在一个大项目中使用代码,欢迎任何帮助!
下面的(最小)示例假定安装了 GIS 扩展的本地 PostgreSQL 数据库 "tmp"。
import unittest
from geoalchemy2 import WKTElement, Geometry
from sqlalchemy import Table, Column, Integer, ForeignKey
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import joinedload, relationship, load_only
from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = (
'postgres://postgres:password@localhost:5432/tmp')
db = SQLAlchemy(app)
Base = declarative_base()
# many (venue) <-> many (label) mapping table
venue_to_label = Table(
'venue_to_label', db.metadata,
Column('venue_id', Integer, ForeignKey('venue.id'), primary_key=True),
Column('label_id', Integer, ForeignKey('label.id'), primary_key=True)
)
class Label(db.Model):
__tablename__ = 'label'
id = Column(Integer, primary_key=True, nullable=False)
class Venue(db.Model):
id = Column(Integer, primary_key=True, nullable=False)
labels = relationship(Label, secondary=venue_to_label)
location = Column(Geometry(geometry_type="POINT"), nullable=False)
db.create_all()
class TestGeoAlchemy2Bug(unittest.TestCase):
def test_geo_alchemy2_bug(self):
point = WKTElement("POINT(0 0)")
query = Venue.query
query = query.options(joinedload(*['labels']).load_only(*['id']))
query = query.order_by(Venue.location.distance_centroid(point))
query = query.limit(10)
print query
print query.all()
免责声明:我已经将该问题作为问题发布在 GeoAlchemy2 github 页面上,但还没有得到任何回复 (https://github.com/geoalchemy/geoalchemy2/issues/93)。
非常感谢我应该寻找哪个方向的一些一般性建议!
感谢您的帮助!
更新
现在通过在创建数据库时创建 "missing" 函数解决了这个问题:
CREATE FUNCTION St_asbinary(double precision)
RETURNS double precision
AS 'select ;'
LANGUAGE SQL
IMMUTABLE
RETURNS NULL ON NULL INPUT;
仍然对合适的解决方案很感兴趣!
问题已在最新版本中解决!
https://github.com/geoalchemy/geoalchemy2/issues/93
当运行下面的例子时,会生成以下无效的SQL查询:
SELECT anon_1.venue_id AS anon_1_venue_id,
St_asbinary(anon_1.venue_location) AS anon_1_venue_location,
St_asbinary(anon_1.anon_2) AS anon_1_anon_2,
label_1.id AS label_1_id
FROM (
SELECT venue.id AS venue_id,
venue.location AS venue_location,
venue.location <-> St_geomfromtext(:ST_GeomFromText_1,
:ST_GeomFromText_2) AS anon_2
FROM venue
ORDER BY venue.location <-> St_geomfromtext(:ST_GeomFromText_1,
:ST_GeomFromText_2)
LIMIT :param_1
) AS anon_1
LEFT OUTER JOIN (
venue_to_label AS venue_to_label_1
JOIN label AS label_1
ON label_1.id = venue_to_label_1.label_id)
ON anon_1.venue_id = venue_to_label_1.venue_id
ORDER BY anon_1.anon_2
问题是 St_asbinary 应用于 anon_1.anon_2。我希望该行不会生成,或者至少没有 "St_asbinary"。我很确定这是 GeoAlchemy2 的错。有人可以评论这个假设吗?
知道如何最好地解决这个问题吗?不幸的是,这似乎很基础。我们正在尝试在一个大项目中使用代码,欢迎任何帮助!
下面的(最小)示例假定安装了 GIS 扩展的本地 PostgreSQL 数据库 "tmp"。
import unittest
from geoalchemy2 import WKTElement, Geometry
from sqlalchemy import Table, Column, Integer, ForeignKey
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import joinedload, relationship, load_only
from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = (
'postgres://postgres:password@localhost:5432/tmp')
db = SQLAlchemy(app)
Base = declarative_base()
# many (venue) <-> many (label) mapping table
venue_to_label = Table(
'venue_to_label', db.metadata,
Column('venue_id', Integer, ForeignKey('venue.id'), primary_key=True),
Column('label_id', Integer, ForeignKey('label.id'), primary_key=True)
)
class Label(db.Model):
__tablename__ = 'label'
id = Column(Integer, primary_key=True, nullable=False)
class Venue(db.Model):
id = Column(Integer, primary_key=True, nullable=False)
labels = relationship(Label, secondary=venue_to_label)
location = Column(Geometry(geometry_type="POINT"), nullable=False)
db.create_all()
class TestGeoAlchemy2Bug(unittest.TestCase):
def test_geo_alchemy2_bug(self):
point = WKTElement("POINT(0 0)")
query = Venue.query
query = query.options(joinedload(*['labels']).load_only(*['id']))
query = query.order_by(Venue.location.distance_centroid(point))
query = query.limit(10)
print query
print query.all()
免责声明:我已经将该问题作为问题发布在 GeoAlchemy2 github 页面上,但还没有得到任何回复 (https://github.com/geoalchemy/geoalchemy2/issues/93)。
非常感谢我应该寻找哪个方向的一些一般性建议!
感谢您的帮助!
更新
现在通过在创建数据库时创建 "missing" 函数解决了这个问题:
CREATE FUNCTION St_asbinary(double precision)
RETURNS double precision
AS 'select ;'
LANGUAGE SQL
IMMUTABLE
RETURNS NULL ON NULL INPUT;
仍然对合适的解决方案很感兴趣!
问题已在最新版本中解决! https://github.com/geoalchemy/geoalchemy2/issues/93