Search code examples
postgresqlpostgisplpgsqlalter-tablegenerated-columns

Postgis: create column with srid in procedure


Hello,

I wonder how I could create a spatialized column with an srid retrieved from the db.

-- OK --
ALTER TABLE POI ADD COORDS GEOMETRY(POINT, 26916);

-- KO (invalid input syntax for type integer: "sridval") --
DO $$
DECLARE
    sridval int;
BEGIN
    sridval := (select srid FROM project_options);
    ALTER TABLE POI ADD COORDS GEOMETRY(POINT, sridval);
END$$;

-- OK but verbose --
DO $$
DECLARE
    sridval int;
BEGIN
    ALTER TABLE POI ADD COORDS GEOMETRY(POINT);
    sridval := (select srid FROM project_options);
    PERFORM updategeometrysrid('POI', 'coords', sridval);
END $$;

Last solution doesn't work with generated columns. Ex:

ALTER TABLE POI ADD COORDS GEOMETRY(POINT, /*put srid here?*/) generated always as (ST_MakePoint(longitude, latitude)) stored;
CREATE INDEX COORDS_IDX ON POI USING GIST (COORDS);

Solution

  • You can use format() to create your DDL dynamically.

    DO $$
    DECLARE
        sridval int;
    BEGIN
     sridval := (SELECT srid FROM project_options); 
     EXECUTE FORMAT('ALTER TABLE poi ADD COLUMN coords geometry(point, %s)',sridval);
    END $$;
    

    You can also skip the variable declaration by passing the query itself as parameter:

    DO $$
    BEGIN
      EXECUTE FORMAT('ALTER TABLE poi ADD coords geometry(point, %s)',
                     (SELECT srid FROM project_options));
    END $$;
    

    And

    DO $$
    BEGIN
     EXECUTE FORMAT('ALTER TABLE poi ADD coords geometry(point, %s) 
                     GENERATED ALWAYS AS (ST_MakePoint(longitude, latitude)) STORED;',
                    (SELECT srid FROM project_options));
    END $$;
    
    • This code assumes that project_options has a single row

    Demo: db<>fiddle