1

So basically I've got this static table that people update information

Then I need it to give it some geometry from a view table. This geometry is dynamic, that's why can't just make a new geom column on the static table

Both layers have matching ids, but different info. I'd like to give the geometry from the view to the table, but when doing a join on QGIS, it doesn't offer the option of adding the geometry column.

Is there a way to join the geometry?

10
  • Possible duplicate of Joining non-spatial CSV file to spatial data (shapefile) using QGIS?
    – Andy
    Jan 8, 2019 at 16:34
  • @andy thats a very old answer, and I'm not using any CSVs whatsoever
    – Luffydude
    Jan 8, 2019 at 17:29
  • 1
    what kind of table is it?
    – MrXsquared
    Jan 8, 2019 at 17:45
  • Will the Join be temporary or permanent? What format do you want the Joined data to be?
    – klewis
    Jan 8, 2019 at 18:16
  • 1
    couldn't you just add a virtual layer (or query result as layer) with a PG join on that id? any QGIS canvas update will refresh the layers underlying SQL.
    – geozelot
    Jan 8, 2019 at 22:01

1 Answer 1

4

I'll add a simple example of what I think you need; I assume that

  • a first set of users will update the 'static table' (attributes only) in QGIS and save back to DB
  • a second set of users updates the 'dynamic view's base layers and its geometry independently
  • the edits of the first user group must not not affect the geometry; edits to it will be ignored

If so, INSERT & DELETE statements need to be treated with care; you'd have to decide what to do with non-matching ids in the 'dynamic view'...and work out a similar approach with it if you want to be able to alter that views underlying data.

If you are not interested in the ability to update attributes and save changes to the DB by the first group of users, this is overkill...instead, simply create the view below without any triggers and load that into QGIS.


First off, let's set up a (very limited) log table to keep track of changes made to the 'static table':

CREATE TABLE _composite_log(
    _uid    SERIAL PRIMARY KEY,
    op_user TEXT,
    op_type TEXT,
    op_time TIMESTAMP,
    id_ref  INTEGER
);

Then set up the actual view that will be the working layer for the first user group (I'll call it and prefix all related items with composite):

CREATE OR REPLACE VIEW composite AS
    SELECT  a.*,
            b.geom
    FROM    <static_table> AS a
    JOIN    <dynamic_view> AS b
      ON    a.id = b.id
    ORDER BY
            a.id
;

Then create the trigger procedure...:

CREATE OR REPLACE FUNCTION composite_delupsert_row()
    RETURNS TRIGGER AS

    $$
    BEGIN

        IF (TG_OP = 'UPDATE') THEN

            UPDATE <static_table>
                SET (<col1>, <col2>, ...) = (NEW.<col1>, NEW.<col2>, ...)
                WHERE id = OLD.id;

            INSERT INTO _composite_log(op_user, op_type, op_time, id_ref)
                VALUES (USER, 'UPDATE', NOW(), OLD.id);

            RETURN NEW;

        ELSIF (TG_OP = 'INSERT') THEN

            RETURN NULL;

        ELSIF (TG_OP = 'DELETE') THEN

            RETURN NULL;

        END IF;

    END;
    $$

    LANGUAGE plpgsql
;

...and the trigger on composite:

CREATE TRIGGER composite_delupsert
    INSTEAD OF UPDATE OR INSERT OR DELETE
    ON  composite
    FOR EACH ROW
    EXECUTE PROCEDURE composite_delupsert_row()
;

Done.

Note: The role that owns the trigger needs all relevant privileges on the 'static table'!

The trigger will catch any UPDATE (and INSERT & DELETE, but will currently simply ignore them; add the respective functionality yourself if you need) statements on thecomposite view and redirects the data to <static_table> only; you need to refer each relevant column in the SET command, all not mentioned columns will stay as they were, and the NEW.geom value, even if changed, will be dropped silently if not handled elsewhere.

Additionally, the name of the operating user, the operation type, the timestamp and the (old) id of the changed row will be added to the _composite_log table.

Now you can add composite as your first groups working layer, and they can alter any attribute that is present in the 'static table' (and is mentioned in the SET column list) via QGIS Edit functionality. The geometry is 'permanently' joined, cannot be updated by the first group (edits to it will be ignored), but will reflect all changes made to it by the second group (in QGIS as soon as the canvas is updated, e.g. via zoom, pan, ...).


This is a very basic implementation, and if you are new to this the whole thing gets very large pretty soon. Take your time with it to see what's happening before implementing it in production. You can find some more basic examples (including views) in the docs, starting with 'Example 43.5'.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.