Object <class 'models.Foo'> is not legal as a SQL literal value
--SQLAlchemy -The Python SQL Toolkit and Object Relational MapperTo post example code, please provide an MCVE: Minimal, Complete, and Verifiable Example. See http://stackoverflow.com/help/mcve for a full description.---You received this message because you are subscribed to the Google Groups "sqlalchemy" group.To unsubscribe from this group and stop receiving emails from it, send an email to sqlalchemy+...@googlegroups.com.To view this discussion on the web visit https://groups.google.com/d/msgid/sqlalchemy/f3718ff7-a252-41a9-8ac4-1ee2ee1e7f9f%40googlegroups.com.
On Sun, Jan 19, 2020, at 10:54 AM, Stephan Hügel wrote:I'm trying to define a GenericFunction that calls a PostGIS 3.0 function (ST_AsGeoJson). The latest version can be called in two different ways:SELECT ST_AsGeoJSON(t.geom) FROM foo as t WHERE t.id = 1;SELECT ST_AsGeoJSON(t.*) FROM foo as t WHERE t.id = 1;where the first example returns a GeoJSON Geometry, and the second returns a GeoJSON Feature. I'm only interested in making use of the second type / am happy to define the two variants separately.I should be able to subclass GenericFunction in order to do this, but I'm missing two details:1. What should the return type of my subclass be?2. How can I specify that I want to pass the record / row / all columns, as opposed to just the geom column to the underlying function? Ordinarily, attempting something likesess.query(func.MyGeojson(Foo)).all()Will give me an error:Object <class 'models.Foo'> is not legal as a SQL literal value
by "return type" I think you're referring to the "type" attribute, so in SQL if you were to make a database column that stores the result of the ST_AsGeoJSON function, a quick google shows it as "text", so for SQLAlchemy you could make the return type String, VARCHAR, TEXT, etc.
To unsubscribe from this group and stop receiving emails from it, send an email to sqlal...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/sqlalchemy/f3718ff7-a252-41a9-8ac4-1ee2ee1e7f9f%40googlegroups.com.
Object <class '__main__.Hardinfra'> is not legal as a SQL literal value
error though. I don't follow your suggestion about
"if this_looks_like_a_row(args): self.type = Feature else: self.type=Geometry"
possibly because I'm not well-versed in SQLA's internals – is there an easy way to distinguish between a row and a column? That still leaves the issue of the "Geometry" vs "Feature" distinction in self.types: Geoalchemy2 defines a "Geometry" type, but not a "Feature" type, because "Feature" is only a part of the GeoJSON spec, but I doubt that either of these things are causing the problem. I've also tried executing the SQL query on my db to make sure it's working and both
SELECT ST_AsGeoJSON(t.*) FROM hardinfra as t WHERE t.id = 1;
SELECT ST_AsGeoJSON(t.geom) FROM hardinfra as t WHERE t.id = 1;
work, returning a GeoJSON Feature and Geometry respectively.
I didn't open the issue about SQL Server, but I use GeoAlchemy regularly, so if there are intro issues available I'm happy to help out when I can.
possibly because I'm not well-versed in SQLA's internals – is there an easy way to distinguish between a row and a column? That still leaves the issue of the "Geometry" vs "Feature" distinction in self.types: Geoalchemy2 defines a "Geometry" type, but not a "Feature" type, because "Feature" is only a part of the GeoJSON spec, but I doubt that either of these things are causing the problem. I've also tried executing the SQL query on my db to make sure it's working and both
SELECT ST_AsGeoJSON(t.*) FROM hardinfra as t WHERE t.id = 1;
SELECT ST_AsGeoJSON(t.geom) FROM hardinfra as t WHERE t.id = 1;
work, returning a GeoJSON Feature and Geometry respectively.
I didn't open the issue about SQL Server, but I use GeoAlchemy regularly, so if there are intro issues available I'm happy to help out when I can.
--SQLAlchemy -The Python SQL Toolkit and Object Relational MapperTo post example code, please provide an MCVE: Minimal, Complete, and Verifiable Example. See http://stackoverflow.com/help/mcve for a full description.---You received this message because you are subscribed to the Google Groups "sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sqlalchemy+...@googlegroups.com.To view this discussion on the web visit https://groups.google.com/d/msgid/sqlalchemy/795a8d14-17da-4c47-a917-78f355e88951%40googlegroups.com.
SELECT ST_AsGeoJSON(t.*) FROM t;
SELECT ST_AsGeoJSON(t.id, t.geom) FROM t;
SELECT ST_AsGeoJSON(ROW(t.id, t.geom)) FROM t;
{"type": "Feature", "geometry": {"type":"Point","coordinates":[1,1]}, "properties": {"f1": 1}} => "f1" property should be name "id"
{"type": "Feature", "geometry": {"type":"Point","coordinates":[1,1]}, "properties": {"id": 1}}
To view this discussion on the web visit https://groups.google.com/d/msgid/sqlalchemy/795a8d14-17da-4c47-a917-78f355e88951%40googlegroups.com.
Hello thereI tried to integrate your POC in GeoAlchemy2 in the following PR:It is almost working but the ST_AsGeoJSON() function needs a record, not a list of columns. So the query should be like:SELECT ST_AsGeoJSON(t.*) FROM t;while the example you provided gives:SELECT ST_AsGeoJSON(t.id, t.geom) FROM t;which is not accepted by PostGIS (Error: the function st_asgeojson(integer, geometry) does not exist).I was able to make it work in the PR by adding a call to the ROW() function, which leads to the following query:SELECT ST_AsGeoJSON(ROW(t.id, t.geom)) FROM t;This query is properly executed by PostGIS but the column names are lost. For example I will get the following result:{"type": "Feature", "geometry": {"type":"Point","coordinates":[1,1]}, "properties": {"f1": 1}} => "f1" property should be name "id"instead of:{"type": "Feature", "geometry": {"type":"Point","coordinates":[1,1]}, "properties": {"id": 1}}Do you have any idea to overcome this issue? I did not find how to produce a "t.*" with SQLAlchemy...
To unsubscribe from this group and stop receiving emails from it, send an email to sqlalchemy+...@googlegroups.com.To view this discussion on the web visit https://groups.google.com/d/msgid/sqlalchemy/fedacdfa-5bd6-4f6c-9c0a-e2f8287585b7%40googlegroups.com.
SELECT ROW(t.id, t.geom)
FROM (SELECT 1 AS id, ST_GeomFromText('POINT( 1 1)') AS geom) AS t;
row
------------------------------------------------
(1,0101000000000000000000F03F000000000000F03F)
To view this discussion on the web visit https://groups.google.com/d/msgid/sqlalchemy/fedacdfa-5bd6-4f6c-9c0a-e2f8287585b7%40googlegroups.com.
To unsubscribe from this group and stop receiving emails from it, send an email to sqlalchemy+...@googlegroups.com.To view this discussion on the web visit https://groups.google.com/d/msgid/sqlalchemy/8410c4e7-bf98-45b7-9b43-ae9157152aef%40googlegroups.com.
SELECT ST_AsGeoJSON(t)FROM t;
You received this message because you are subscribed to a topic in the Google Groups "sqlalchemy" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/sqlalchemy/owT52zKYNVw/unsubscribe.
To unsubscribe from this group and all its topics, send an email to sqlalchemy+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/sqlalchemy/0d878447-57c6-414b-9785-a41ebb9486e4%40www.fastmail.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/sqlalchemy/CAKuTeydbAbY9VLJFAbK42gLPO6maeugyX0ciJjrwotArabtASQ%40mail.gmail.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/sqlalchemy/ef6eae5a-4c1e-4b43-82ab-854c89924938%40www.fastmail.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/sqlalchemy/CAKuTeydSZwR-aUt0k9sXVtkGPhwd3uidbLc97SNKF1cw%2BJiAsA%40mail.gmail.com.
Ok, thank you for your advice, following it I tried the following (in geoalchemy2.functions.py).
class ST_AsGeoJSON(functions.GenericFunction): def __init__(self, *args, **kwargs): args = list(args) self.feature_mode = False for idx, elem in enumerate(args): try: insp = inspect(elem) if hasattr(insp, "selectable"): args[idx] = insp.selectable self.feature_mode = True except Exception: continue functions.GenericFunction.__init__(self, *args, **kwargs) def _compile_ST_AsGeoJSON(cls): def _compile_geojson_feature(cls_name, element, compiler, **kw): if not element.feature_mode: return "{}({})".format(cls_name, compiler.process(element.clauses, **kw)) else: clauses = list(element.clauses) table = compiler.process(clauses[0], asfrom=True, **kw).split(".")[-1] # This is quite dirty args = [] if len(clauses) > 1: args = ", ".join([compiler.process(i, **kw) for i in clauses[1:]]) return "{}({})".format(cls_name, ", ".join([table, args])) def _compile_geojson_default(element, compiler, **kw): return _compile_geojson_feature(cls, element, compiler, **kw) def _compile_geojson_sqlite(element, compiler, **kw): return _compile_geojson_feature(cls[3:], element, compiler, **kw) compiles(globals()[cls])(_compile_geojson_default) compiles(globals()[cls], "sqlite")(_compile_geojson_sqlite) _compile_ST_AsGeoJSON("ST_AsGeoJSON")
I am not sure it is the right way to do it but using this it is possible to write the following queries:
But it does not work for subqueries:
sq = select([Lake, bindparam('dummy_val', 10).label('dummy_attr')]).alias()
select([func.ST_AsGeoJSON(sq, 'geom')])
because the generated query is:
[SELECT ST_AsGeoJSON(lake) AS anon_1, %(ST_AsGeoJSON_2)s) AS "ST_AsGeoJSON_1"
FROM (SELECT gis.lake.id AS id, gis.lake.geom AS geom, %(dummy_val)s AS dummy_attr
FROM gis.lake) AS anon_1]
[parameters: {'dummy_val': 10, 'ST_AsGeoJSON_2': 'geom'}]
How can I get the alias of an aliased selectable?
To view this discussion on the web visit https://groups.google.com/d/msgid/sqlalchemy/7067863f-c502-4d9d-91e7-3e58e9122339%40www.fastmail.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/sqlalchemy/CAKuTeyf%2B1r0i8ZCGJBOqRgNEmprC0J4pmo4O9HzwYa471j6CyQ%40mail.gmail.com.
select([func.ST_AsGeoJSON(Lake.__table__.c.geom)])
select([func.ST_AsGeoJSON(Lake, 'geom')])
To view this discussion on the web visit https://groups.google.com/d/msgid/sqlalchemy/84dde841-8b7c-4e2b-b47c-776048e231a1%40www.fastmail.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/sqlalchemy/CAKuTeycWi2KEKOJSd1YX_OxOp0ZJtSg8WBYkgJftqeXzVbX%3D_w%40mail.gmail.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/sqlalchemy/d426e4ab-cb61-4f5a-a27e-6f6932663bf0%40www.fastmail.com.