diff options
-rwxr-xr-x | webmap-cgi | 28 |
1 files changed, 11 insertions, 17 deletions
@@ -23,7 +23,7 @@ import sys from os import path as os_path -from json import load as json_load, JSONDecodeError +from json import load as json_load, dumps as json_dumps, JSONDecodeError import logging from typing import Final, Iterator import atexit @@ -135,7 +135,9 @@ def get_query_map(layernames : set[str]) -> dict[str,bytes]: resp = cur.fetchone() while resp is not None: c = resp[0] + # pylint: disable-next=too-many-boolean-expressions if (c in ('layer_group', 'layer') or + (c == 'ogc_fid' and pkey_col != c) or (d == 2 and c in ('geom_area', 'geom_perimeter')) or (d == 1 and c == 'geom_length')): logging.warning('Duplicate column name "%s"', c) @@ -143,17 +145,14 @@ def get_query_map(layernames : set[str]) -> dict[str,bytes]: column_names.append(c) resp = cur.fetchone() - # TODO[trixie] id_column => 'ogc_fid' (but don't hardcode either) query = 'WITH feature AS (' - query += 'SELECT m.' + common.escape_identifier(pkey_col) + ',' + query += 'SELECT m.' + common.escape_identifier(pkey_col) + ' AS ogc_fid,' for column_name in column_names: query += 'm.' + common.escape_identifier(column_name) + ',' if force2d: geom_col2d_esc = 'ST_Force2D(m.' + common.escape_identifier(geom_cols[0]) + ')' - query += geom_col2d_esc + ' AS ' + common.escape_identifier(geom_cols[0]) + ',' else: geom_col2d_esc = 'm.' + common.escape_identifier(geom_cols[0]) - query += geom_col2d_esc + ',' if d == 2: query += 'ST_Area(' + geom_col2d_esc +') AS geom_area,' query += 'ST_Perimeter(' + geom_col2d_esc +') AS geom_perimeter,' @@ -164,18 +163,13 @@ def get_query_map(layernames : set[str]) -> dict[str,bytes]: query += common.escape_identifier(layername) + ' m ' query += 'WHERE m.' + common.escape_identifier(pkey_col) + ' = %s' query += ') ' - # letting PostgreSQL convert to UTF-8 is likely faster than if we were doing - # it ourselves - query += 'SELECT convert_to(' - query += 'ST_AsGeoJSON(feature.*,' - query += 'geom_column=>' + common.escape_literal_str(geom_cols[0]) + ',' - query += 'pretty_bool=>\'f\'),' - query += '\'UTF8\') AS "GeoJSON" ' - query += 'FROM feature' + # TODO[trixie] use json_serialize() from PostgreSQL 17 to avoid serializing on + # the Python side. (There is also row_to_json() which might be of interest if + # json not jsonb is needed.) + query += 'SELECT to_jsonb(feature) FROM feature' # The query never returns more than one row since we filter on a single FID. - # Don't try to be clever and batch queries in an IN set or ANY as we - # want to preserve the order in the response (so the feature(s) - # exactly under the cursor are returned first). + # TODO: batch queries using ANY[] or an IN set (the # consummer will then need + # to re-order the response) ret[layername] = query.encode('utf-8') return ret @@ -243,7 +237,7 @@ def application(env, start_response) -> Iterator[bytes]: first = False else: yield b',' - yield resp[0] + yield json_dumps(resp[0], ensure_ascii=False, separators=(',', ':')).encode('utf-8') # the query never returns more than one row since we filter on a single FID if first: yield b'[]' # no match, empty response |