rails 为子查询清理
rails sanitize for subquery
我正在尝试使用子查询清理 SQL 查询,但每次我都收到语法错误或无效几何错误。为了进行消毒,我使用了 sanitize_sql_array 函数。
SQL查询
SELECT ST_Distance('SRID=4326;POINT(0 0)'::geometry, subqry.centroid)
FROM
(SELECT ST_AsText(ST_Centroid('SRID=4326;MULTIPOINT ( 0 0, 0 0, 0 0, 0 0 )'))::geography as centroid
) as subqry;
第一种方法
ActiveRecord::Base::sanitize_sql_array(["select ST_Distance('SRID=4326;POINT(? ?)'::geometry, :sub_query", sub_query: "(SELECT ST_Centroid(SRID=4326;'MULTIPOINT ( ? ?, ? ?, ? ?, ? ? )'::geometry) as centroid) as sub_query", min_longitude, min_latitude, min_longitude, min_latitude, min_longitude, max_latitude, max_longitude, min_latitude, max_longitude, max_latitude])
第二种方法
这里我得到“SRID=4326; SE”<-- 几何中位置 13 的解析错误
ActiveRecord::Base::sanitize_sql_array(["ST_Distance('SRID=4326;POINT(? ?)'::geometry, 'SRID=4326; SELECT ST_AsText(ST_Centroid(MULTIPOINT ( ? ?, ? ?, ? ?, ? ? ))) as centroid'::geometry)", min_longitude, min_latitude, min_longitude, min_latitude, min_longitude, max_latitude, max_longitude, min_latitude, max_longitude, max_latitude])
PostGIS 中 st_centroid 和 st_distance 方法的示例
st_centroid
SELECT ST_AsText(ST_Centroid('MULTIPOINT ( -1 0, -1 2, -1 3, -1 4, -1 7, 0 1, 0 3, 1 1, 2 0, 6 0, 7 8, 9 8, 10 6 )'));
st_distance
SELECT ST_Distance(
'SRID=4326;POINT(-72.1235 42.3521)'::geometry,
'SRID=4326;LINESTRING(-72.1260 42.45, -72.123 42.1546)'::geometry
);
您可以使用一些技巧和大量 Arel(它将为您处理卫生)来构建您可能想要的任何查询。
警告:这可能看起来不漂亮,但它可以非常灵活并且应该产生预期的结果。 (这只是生成所需的查询,如 post 所示,我不知道所需的语法是否正确,因为我从未使用过 PostGIS)
class PostGISQuery
def initialize(srid,points,point)
@srid = srid
@points = points
@point = point
end
def build_query
return @query if @query
multi_point = Arel::Nodes::NamedFunction.new("MULTIPOINT",[lat_long(@points)])
centroid = Arel::Nodes::NamedFunction.new('ST_AsText',[
Arel::Nodes::NamedFunction.new('ST_Centroid',[
Arel.sql("SRID=#{@srid};#{multi_point.to_sql}")
])
])
mgr = Arel::SelectManager.new
mgr.project(cast_geometry(centroid).as('centroid'))
table = Arel::Table.new('subqry')
answer= Arel::Nodes::NamedFunction.new('ST_Distance',[
cast_geometry(Arel.sql("SRID=#{@srid};#{Arel::Nodes::NamedFunction.new('POINT',lat_long([@point])).to_sql}")),
table[:centroid]
])
mgr2 = Arel::SelectManager.new(Arel::Nodes::As.new(mgr,Arel.sql(table.name)))
@query = mgr2.project(answer.as('answer'))
end
def execute
ActiveRecord::Base.connection.exec_query(build_query.to_sql)
end
private
def cast_geometry(arel)
Arel::Nodes::NamedFunction.new("CAST",[arel.as('geometry')])
end
def lat_long(arr)
arr.map {|a| Arel.sql(a.join(' '))}
end
end
用法
srid = 4326
points = [[1, 0], [-1, 2], [-1, 3], [-1, 4], [-1, 7], [0, 1], [0, 3], [1, 1], [2, 0], [6, 0], [7, 8], [9, 8], [10, 6]]
point = [-72.1235, 42.3521]
qry = PostGISQuery.new(srid,points,point)
qry.execute
#=> ActiveRecord::Result
SQL 出品:
SELECT
ST_Distance(
CAST('SRID=4326;POINT(-72.1235 42.3521)' AS geometry),
"subqry"."centroid") AS answer
FROM (
SELECT
CAST(ST_AsText(
ST_Centroid(
'SRID=4326;MULTIPOINT(1 0, -1 2, -1 3, -1 4, -1 7, 0 1, 0 3, 1 1, 2 0, 6 0, 7 8, 9 8, 10 6)'
)
) AS geometry) AS centroid
) AS subqry
我正在尝试使用子查询清理 SQL 查询,但每次我都收到语法错误或无效几何错误。为了进行消毒,我使用了 sanitize_sql_array 函数。
SQL查询
SELECT ST_Distance('SRID=4326;POINT(0 0)'::geometry, subqry.centroid)
FROM
(SELECT ST_AsText(ST_Centroid('SRID=4326;MULTIPOINT ( 0 0, 0 0, 0 0, 0 0 )'))::geography as centroid
) as subqry;
第一种方法
ActiveRecord::Base::sanitize_sql_array(["select ST_Distance('SRID=4326;POINT(? ?)'::geometry, :sub_query", sub_query: "(SELECT ST_Centroid(SRID=4326;'MULTIPOINT ( ? ?, ? ?, ? ?, ? ? )'::geometry) as centroid) as sub_query", min_longitude, min_latitude, min_longitude, min_latitude, min_longitude, max_latitude, max_longitude, min_latitude, max_longitude, max_latitude])
第二种方法
这里我得到“SRID=4326; SE”<-- 几何中位置 13 的解析错误
ActiveRecord::Base::sanitize_sql_array(["ST_Distance('SRID=4326;POINT(? ?)'::geometry, 'SRID=4326; SELECT ST_AsText(ST_Centroid(MULTIPOINT ( ? ?, ? ?, ? ?, ? ? ))) as centroid'::geometry)", min_longitude, min_latitude, min_longitude, min_latitude, min_longitude, max_latitude, max_longitude, min_latitude, max_longitude, max_latitude])
PostGIS 中 st_centroid 和 st_distance 方法的示例
st_centroid
SELECT ST_AsText(ST_Centroid('MULTIPOINT ( -1 0, -1 2, -1 3, -1 4, -1 7, 0 1, 0 3, 1 1, 2 0, 6 0, 7 8, 9 8, 10 6 )'));
st_distance
SELECT ST_Distance(
'SRID=4326;POINT(-72.1235 42.3521)'::geometry,
'SRID=4326;LINESTRING(-72.1260 42.45, -72.123 42.1546)'::geometry
);
您可以使用一些技巧和大量 Arel(它将为您处理卫生)来构建您可能想要的任何查询。
警告:这可能看起来不漂亮,但它可以非常灵活并且应该产生预期的结果。 (这只是生成所需的查询,如 post 所示,我不知道所需的语法是否正确,因为我从未使用过 PostGIS)
class PostGISQuery
def initialize(srid,points,point)
@srid = srid
@points = points
@point = point
end
def build_query
return @query if @query
multi_point = Arel::Nodes::NamedFunction.new("MULTIPOINT",[lat_long(@points)])
centroid = Arel::Nodes::NamedFunction.new('ST_AsText',[
Arel::Nodes::NamedFunction.new('ST_Centroid',[
Arel.sql("SRID=#{@srid};#{multi_point.to_sql}")
])
])
mgr = Arel::SelectManager.new
mgr.project(cast_geometry(centroid).as('centroid'))
table = Arel::Table.new('subqry')
answer= Arel::Nodes::NamedFunction.new('ST_Distance',[
cast_geometry(Arel.sql("SRID=#{@srid};#{Arel::Nodes::NamedFunction.new('POINT',lat_long([@point])).to_sql}")),
table[:centroid]
])
mgr2 = Arel::SelectManager.new(Arel::Nodes::As.new(mgr,Arel.sql(table.name)))
@query = mgr2.project(answer.as('answer'))
end
def execute
ActiveRecord::Base.connection.exec_query(build_query.to_sql)
end
private
def cast_geometry(arel)
Arel::Nodes::NamedFunction.new("CAST",[arel.as('geometry')])
end
def lat_long(arr)
arr.map {|a| Arel.sql(a.join(' '))}
end
end
用法
srid = 4326
points = [[1, 0], [-1, 2], [-1, 3], [-1, 4], [-1, 7], [0, 1], [0, 3], [1, 1], [2, 0], [6, 0], [7, 8], [9, 8], [10, 6]]
point = [-72.1235, 42.3521]
qry = PostGISQuery.new(srid,points,point)
qry.execute
#=> ActiveRecord::Result
SQL 出品:
SELECT
ST_Distance(
CAST('SRID=4326;POINT(-72.1235 42.3521)' AS geometry),
"subqry"."centroid") AS answer
FROM (
SELECT
CAST(ST_AsText(
ST_Centroid(
'SRID=4326;MULTIPOINT(1 0, -1 2, -1 3, -1 4, -1 7, 0 1, 0 3, 1 1, 2 0, 6 0, 7 8, 9 8, 10 6)'
)
) AS geometry) AS centroid
) AS subqry