Skip to content

Adequar a função write_geoJSONb_Features aos requisitos stable #1

Description

@ppKrauss

Depois dos resultados dos testes, com diff de coordenadas e diff de propriedades, definir requisitos e efetuar modificações nas funções abaixo. Se aprovado também incluir modificações na lib de origem.

-- originais de https://github.com/AddressForAll/pg_pubLib-v1/blob/main/src/pubLib03-json.sql
CREATE or replace FUNCTION jsonb_pretty(
  jsonb,            -- input
  compact boolean   -- true for compact format
) RETURNS text AS $f$
  SELECT CASE -- warning: incidental behaviour of strip_nulls.
    WHEN $2 THEN  json_strip_nulls($1::json)::text
    ELSE  jsonb_pretty($1)
  END
  -- from https://stackoverflow.com/a/27536804/287948
  -- pg16+ back to https://stackoverflow.com/a/70828187/287948
$f$ LANGUAGE SQL IMMUTABLE;
COMMENT ON FUNCTION jsonb_pretty(jsonb,boolean)
  IS 'Extends jsonb_pretty() to return canonical compact form when true';
-- SELECT jsonb_pretty(  jsonb_build_object('a',1, 'bla','bla bla'), true );

CREATE or replace FUNCTION jsonb_pretty_lines(j_input jsonb, opt int DEFAULT 0) RETURNS text AS $f$
 -- jsonB input
 SELECT CASE opt
   WHEN 0  THEN j_input::text
   WHEN 1  THEN jsonb_pretty(j_input)
   WHEN 2  THEN regexp_replace(regexp_replace(j_input::text, ' ?\{"type": "Feature", "geometry":\n', '{"type": "Feature", "geometry": ', 'g'), ' ?\{"type": "Feature", "geometry":', E'\n{"type": "Feature", "geometry":', 'g') || E'\n'  -- GeoJSON
   WHEN 3  THEN replace(regexp_replace(j_input::text, ' ?\{"type": "Feature", "geometry":\n', '{"type": "Feature", "geometry": ', 'g'), ' ', '') || E'\n'  -- GeoJSON
   WHEN 4  THEN jsonb_pretty(j_input,true)  -- canonical compact form
   END
$f$ language SQL IMMUTABLE;
COMMENT ON FUNCTION jsonb_pretty_lines(jsonB,int)
  IS 'Alternatives for jsonb_pretty() to return one item per line: 0 = to_text with no formating, 1=standard pretty, 2=GeoJSON preserving type, 3=GeoJSON removing type, 4=compact form';


CREATE or replace FUNCTION json_pretty_lines(j_input json, opt int DEFAULT 0) RETURNS text AS $f$
 -- json input (not jsonB!) 
 SELECT CASE opt
   WHEN 0  THEN j_input::text
   WHEN 1  THEN jsonb_pretty(j_input::jsonb)
   WHEN 2  THEN regexp_replace(regexp_replace(j_input::text, ' ?\{"type": "Feature", "geometry":\n', '{"type": "Feature", "geometry": ', 'g'), ' ?\{"type": "Feature", "geometry":', E'\n{"type": "Feature", "geometry":', 'g') || E'\n'  -- GeoJSON
   WHEN 3  THEN replace(regexp_replace(j_input::text, ' ?\{"type": "Feature", "geometry":\n', '{"type": "Feature", "geometry": ', 'g'), ' ', '') || E'\n'  -- GeoJSON
   WHEN 4  THEN json_strip_nulls(j_input)::text -- canonical compact form, same as jsonb_pretty(j,true)
   END
$f$ language SQL IMMUTABLE;
COMMENT ON FUNCTION json_pretty_lines(json,int)
  IS 'Format JSON like jsonB_pretty() to return one item per line: 0 = to_text with no formating, 1=standard Pretty, 2=GeoJSON preserving type, 3=GeoJSON removing type, 4=compact form';



-- original de https://github.com/AddressForAll/pg_pubLib-v1/blob/main/src/pubLib06pgis-geoJSON.sql
CREATE or replace FUNCTION write_geoJSONb_Features(
  sql_tablename text, -- ex. 'vw_grid_ibge_l1' or 'SELECT * FROM t WHERE cond'
  p_file text, -- ex. '/tmp/grid_ibge100km.geojson'
  sql_geom text DEFAULT 't1.geom', -- sql using t1 as alias for geom, eg. ST_Transform(t1.geom,4326)
  p_cols text DEFAULT NULL, -- null or list of p_properties. Ex. 'id_unico,pop,pop_fem_perc,dom_ocu'
  p_cols_orderby text[] DEFAULT NULL,
  col_id text default null, -- p_id, expressed as t1.colName. Ex. 't1.gid::text'
  p_pretty_opt int default 0, -- 0=no, 1=jsonb_pretty, 2=jsonb_pretty_lines(s,1), 3=jsonb_pretty_lines(s,2)
  p_decimals int default 6,
  p_options int default 0,  -- 0=better, 1=(implicit WGS84) tham 5 (explicit)
  p_name text default null,
  p_title text default null,
  p_id_as_int boolean default false
)
RETURNS text LANGUAGE 'plpgsql' AS $f$
  DECLARE
    msg text;
    sql_orderby text;
    sql_pre text;
    sql text;
  BEGIN
      IF position(' ' in trim(sql_tablename))>0 THEN
        sql_tablename := '('||sql_tablename||')';
      END IF;
      sql_orderby := CASE
        WHEN p_cols_orderby IS NULL OR array_length(p_cols_orderby,1) IS NULL THEN ''
        ELSE 'ORDER BY '||stragg_prefix('t1.',p_cols_orderby) END;
      sql_pre := format($$
        ST_AsGeoJSONb( %s, %s, %s, %s, %s, %s, %s, %s) %s
        $$,
        sql_geom, p_decimals::text, p_options::text,
        CASE WHEN col_id is null THEN 'NULL' ELSE 't1.'||col_id||'::text' END,
        CASE WHEN p_cols~'::jsonb?$' THEN regexp_replace(p_cols,'::jsonb?$','')
             WHEN p_cols is null THEN 'NULL'
             ELSE 'to_jsonb(t2)'
        END,
        COALESCE(p_name::text,'NULL'),
        COALESCE(p_title::text,'NULL'),
        COALESCE(p_id_as_int::text,'NULL'),
        sql_orderby
      );
      -- RAISE NOTICE '--- DEBUG sql_pre: %', sql_pre
      -- ex. 'ST_AsGeoJSONb( ST_Transform(t1.geom,4326), 6, 0, t1.gid::text, to_jsonb(t2) ) ORDER BY t1.gid'
      -- EXECUTE
      SELECT pg_catalog.pg_file_unlink(p_file)::text INTO sql;
      sql := format($$
        SELECT volat_file_write(
                %L,
                jsonb_pretty_lines( jsonb_build_object('type','FeatureCollection', 'features', gj), %s)
             )
        FROM (
          SELECT jsonb_agg( %s ) AS gj
          FROM %s t1 %s
        ) t3
       $$,
       p_file,
       p_pretty_opt::text,
       sql_pre, sql_tablename,
       CASE WHEN p_cols IS NULL OR p_cols~'::jsonb?$' THEN ''
            ELSE ', LATERAL (SELECT '||p_cols||') t2'
       END
      );
      -- RAISE NOTICE E'--- DEBUG SQL: ---\n%\n', sql
      EXECUTE sql INTO msg;
      RETURN msg;
  END
$f$;
COMMENT ON FUNCTION write_geojsonb_Features
  IS 'run file_write() dynamically to save specified relation as GeoJSONb FeatureCollection.'
;

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

enhancementNew feature or request

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions