Более

Проблема со слоем представления PostgreSQL в QGIS

Проблема со слоем представления PostgreSQL в QGIS


У меня есть таблица PostgreSQL и просмотр:

СОЗДАТЬ ТАБЛИЧНЫЕ строки (геометрия геометрии (MultiLineString, 4326), переменный тип символа (254), текст входа в систему, серийный номер gid NOT NULL, CONSTRAINT lines_pkey PRIMARY KEY (gid)) СОЗДАТЬ ИЛИ ЗАМЕНИТЬ ВИД lines_view КАК ВЫБРАТЬ lines.geom, lines.type, lines.gid FROM lines; СОЗДАТЬ ИЛИ ЗАМЕНИТЬ ПРАВИЛО добавить КАК ON INSERT TO lines_view DO INSTEAD INSERT INTO lines (geom, type, login) VALUES (new.geom, new.type, "current_user" ()); СОЗДАТЬ ИЛИ ЗАМЕНИТЬ ПРАВИЛО del AS НА УДАЛЕНИЕ В lines_view ВСТАВИТЬ УДАЛЕНИЕ ИЗ строк, ГДЕ lines.login = "current_user" () :: text AND lines.gid = old.gid; СОЗДАТЬ ИЛИ ЗАМЕНИТЬ ПРАВИЛО upd КАК НА ОБНОВЛЕНИЕ В lines_view УСТАНОВИТЬ ОБНОВЛЕНИЕ строк SET geom = new.geom, type = new.type, login = "current_user" () ГДЕ lines.login = "current_user" () :: text И строки. gid = new.gid;

Итак, проблема в том, что когда я загружаю этот lines_view в QGIS как слой и добавляю строки, после сохранения я не могу использовать "инструмент узла" для новый линии («Инструмент узла: не удалось выполнить привязку к сегменту на текущем слое»). Но когда я использую для них инструмент перемещения (просто нажмите кнопку «Переместить объект (ы)») и нажмите новый line) "инструмент узла" начинает работать в обычном режиме. Может кто-то помочь мне с этим?


Предполагая, что единственная причина, по которой вам нужны эти представления, - это управлениеавторизоватьсязначение столбца и кто может обновлять какие строки, тогда вам на самом деле не нужно представление здесь.

Начните с созданияВСТАВЛЯТЬтриггер, чтобы всегда устанавливатьавторизоватьсястолбец:

СОЗДАТЬ ИЛИ ЗАМЕНИТЬ ФУНКЦИЮ set_login_to_current_user () ВОЗВРАЩАЕТ ЯЗЫК ТРИГГЕРА plpgsql КАК $$ НАЧАТЬ NEW.login = current_user; ВОЗВРАТ НОВЫЙ; END $$; СОЗДАТЬ ТРИГГЕР insert_on_lines ПЕРЕД ВСТАВКОЙ В СТРОКИ ДЛЯ КАЖДОЙ СТРОКИ ВЫПОЛНИТЬ ПРОЦЕДУРУ set_login_to_current_user ();

(Обратите внимание, что это немного отличается отДЕФОЛТстоимость. АДЕФОЛТсработает только в том случае, если значение не будет предоставлено. Этот триггер переопределяет значение, даже если пользователь пытался его указать.)

Теперь добавьте триггер обновления, который предотвращает изменение строк, не принадлежащих текущему пользователю:

СОЗДАТЬ ИЛИ ЗАМЕНИТЬ ФУНКЦИЮ prevent_update_for_other_user () ВОЗВРАЩАЕТ ЯЗЫК ТРИГГЕРА plpgsql AS $$ BEGIN IF OLD.login! = Current_user THEN RAISE EXCEPTION 'Попытка изменить строку, принадлежащую другому пользователю'; ИНАЧЕ NEW.login = current_user; ВОЗВРАТ НОВЫЙ; КОНЕЦ ЕСЛИ; END $$; СОЗДАТЬ ТРИГГЕР update_on_lines ПЕРЕД ОБНОВЛЕНИЕМ СТРОК ДЛЯ КАЖДОЙ СТРОКИ ВЫПОЛНИТЬ ПРОЦЕДУРУ prevent_update_for_other_user ();

И наконец, добавьте триггер, предотвращающий удаление:

СОЗДАТЬ ИЛИ ЗАМЕНИТЬ ФУНКЦИЮ prevent_delete_for_other_users () ВОЗВРАЩАЕТ ЯЗЫК ТРИГГЕРА plpgsql AS $$ BEGIN IF OLD.login! = Current_user THEN RAISE EXCEPTION 'Попытка удалить строку, принадлежащую другому пользователю'; ЕЩЕ ВОЗВРАТ СТАРЫЙ; КОНЕЦ ЕСЛИ; END $$; СОЗДАТЬ ТРИГГЕР delete_on_lines ПЕРЕД УДАЛЕНИЕМ СТРОК ДЛЯ КАЖДОЙ СТРОКИ ВЫПОЛНИТЬ ПРОЦЕДУРУ prevent_delete_for_other_users ();

Я проверил, что это правильно работает с PostgreSQL 9.3 / PostGIS 2.1.4 и QGIS 2.8.1, но, поскольку он использует только базовые функции PostgreSQL, я ожидаю, что это будет работать в более высоких версиях всего.

Обратите внимание, что в случаях обновления и удаления я выдаю ошибку, если пользователь пытается изменить строку, принадлежащую другому пользователю. Это немного отличается от того, что вы разместили, где вы просто молча ничего не делаете. Я этого не советую. При молчаливом отклонении команды пользователь может подумать, что его изменения были применены, хотя они этого не сделали, и пользователь может быть очень сбит с толку, когда позже обнаружит, что их изменения «отсутствуют». Вызывая ошибку, пользователь сразу узнает, что внесенное изменение было отклонено, и может соответственно отменить изменения. если ты В самом деле нужно продолжить, вы можете заменитьПОДНИМАТЬкоманды с

RETURN NULL;

чтобы молча предотвратить редактирование или удаление.

Я также хочу отметить, что это не означает «безопасность» само по себе, но это может быть частью решения в сочетании с другими вещами. Вам необходимо объединить это с соответствующими разрешениями, чтобы пользователи не могли изменять триггеры или функции триггеров. Важно отметить, что вы не можете фильтровать, какие строки может использовать конкретный пользователь. Посмотреть (но ваш вопрос все равно этого не делает). Также стоит отметить, что PG 9.5 будет иметь "защиту на уровне строк" из коробки, что было бы даже лучшим способом решения этой проблемы.


Вы не упомянули ни версию qgis, ни версию postgis, qgis 2.10 не позволяет редактировать таблицу без первичного ключа - что было бы в случае вашего представления.