Commit 68ad9627 authored by Alice Salsé's avatar Alice Salsé
Browse files

evols default values

parents 4727a70d ba66a9d6
......@@ -15,8 +15,9 @@ do
done
echo Creation des tables réseau
psql -h ${host} -d ${dbname} -U ${user} -p ${port} -b -q -v schemaname=${schemaname} -f sql/network/create_table.sql
psql -h ${host} -d ${dbname} -U ${user} -p ${port} -b -q -c "TRUNCATE ${schemaname}.pipe_default_node RESTART IDENTITY;"
psql -h ${host} -d ${dbname} -U ${user} -p ${port} -b -q -c "TRUNCATE ${schemaname}.pipe_default_node RESTART IDENTITY; TRUNCATE ${schemaname}.default_value RESTART IDENTITY;"
psql -h ${host} -d ${dbname} -U ${user} -p ${port} -b -q -c "\copy ${schemaname}.pipe_default_node FROM '../config/csv/${schemaname}/pipe_default_node.csv' WITH DELIMITER ';' ESCAPE'\' CSV HEADER;"
psql -h ${host} -d ${dbname} -U ${user} -p ${port} -b -q -c "\copy ${schemaname}.default_value FROM '../config/csv/${schemaname}/default_value.csv' WITH DELIMITER ';' ESCAPE'\' CSV HEADER;"
echo Creation des tables
python python/create_table.py $schemaname
echo Installation des configurations spécifiques
......
......@@ -2,7 +2,7 @@
# supprimer les macros
import importlib
# lister les schemas contenant à éditer
# lister les schemas contenant les couches à éditer
_schemanames=['<water_events>','<wastewater_events>']
root = iface.layerTreeView().layerTreeModel().rootGroup()
for layer in [l.layer() for l in root.findLayers() if l.layer().type() == QgsMapLayerType.VectorLayer] :
......
......@@ -226,30 +226,24 @@ class NetworkTools:
level, ctrl = QInputDialog.getItem(QInputDialog(), "Level", "Choisir le niveau", levels, 0)
if ctrl :
lvl=lvls[levels.index(level)]
col_names, rcrds = executeQuery(first_lyr.dataProvider(), qconst2.format(_schema))
before_q = []
for r in rcrds :
before_q.append("SET CONSTRAINTS {0}.{1} DEFERRED;".format(*r))
before_q=' '.join(before_q)
result=first_lyr.dataProvider().transaction().executeSql(before_q,False)
result=first_lyr.dataProvider().transaction().executeSql("SET CONSTRAINTS ALL DEFERRED;",False)
if result[0] == False :
self.iface.messageBar().pushMessage("Echec : " + result[1].split('\n')[0], Qgis.Warning)
return
query="UPDATE {0}.{1} SET level = {2} WHERE id in ({3});"
for typ in ['node', 'pipe', 'part', 'lnode', 'lpipe', 'lpart'] :
ids=[]
column_names, records = executeQuery(first_lyr.dataProvider(), qconst.format(_schema, typ))
for rec in records :
for lyr_id in lyrs :
lyr=self.root.findLayer(lyr_id).layer()
l_sch, l_tab = lyr.dataProvider().uri().schema(), lyr.dataProvider().uri().table()
if l_sch == rec[0] and (l_tab[-len(rec[1]):]== rec[1] or l_tab==typ) :
ids=list(set(ids+lyrs[lyr_id]))
result=first_lyr.dataProvider().transaction().executeSql(query.format(l_sch, typ, lvl, ','.join([str(i) for i in ids]) or '0'))
result=first_lyr.dataProvider().transaction().executeSql(query.format(l_sch, l_tab, lvl, ','.join([str(i) for i in lyrs[lyr_id]]) or '0'))
if result[0] == False :
self.iface.messageBar().pushMessage("Echec : " + result[1].split('\n')[0], Qgis.Warning)
return
result=first_lyr.dataProvider().transaction().executeSql(before_q.replace('DEFERRED','IMMEDIATE'),True)
print('debuggg')
result=first_lyr.dataProvider().transaction().executeSql("SET CONSTRAINTS ALL IMMEDIATE;",True)
if result[0] == True :
self.iface.messageBar().pushMessage("Déplacement vers le niveau {0} réussie".format(level), Qgis.Info)
else:
......@@ -325,18 +319,12 @@ class NetworkTools:
self.iface.messageBar().pushMessage("Les couches doivent être en édition", Qgis.Warning)
return
_schema=first_lyr.dataProvider().uri().schema()
col_names, rcrds = executeQuery(first_lyr.dataProvider(), qconst2.format(_schema))
before_q = []
for r in rcrds :
before_q.append("SET CONSTRAINTS {0}.{1} DEFERRED;".format(*r))
before_q=' '.join(before_q)
result=first_lyr.dataProvider().transaction().executeSql(before_q,False)
result=first_lyr.dataProvider().transaction().executeSql("SET CONSTRAINTS ALL DEFERRED;",False)
if result[0] == False :
self.iface.messageBar().pushMessage("Echec : " + result[1].split('\n')[0], Qgis.Warning)
return
query="DELETE FROM {0} WHERE id in ({1});"
for typ in ['lpart', 'lnode', 'lpipe', 'part', 'node', 'pipe'] :
ids=[]
column_names, records = executeQuery(first_lyr.dataProvider(), qconst.format(_schema, typ))
for rec in records :
for lyr_id in lyrs :
......@@ -348,7 +336,7 @@ class NetworkTools:
if result[0] == False :
self.iface.messageBar().pushMessage("Echec : " + result[1].split('\n')[0], Qgis.Warning)
return
result=first_lyr.dataProvider().transaction().executeSql(before_q.replace('DEFERRED','IMMEDIATE'),True)
result=first_lyr.dataProvider().transaction().executeSql("SET CONSTRAINTS ALL IMMEDIATE;",True)
if result[0] == True :
self.iface.messageBar().pushMessage("Suppression réussie", Qgis.Info)
else:
......@@ -407,33 +395,20 @@ class NetworkTools:
self.iface.messageBar().pushMessage("La couche doit être en édition", Qgis.Warning)
return
if layer.geometryType() == QgsWkbTypes.PointGeometry :
leves, ctrl = QInputDialog.getItem(QInputDialog(), "Levés", "Choisir les levés cible", ['Corrige', 'ESRI', 'Chapuis', 'CSV', 'DWG', 'ProxDWG'], 0)
if ctrl :
echecs=[]
l_qtablename=layer.dataProvider().uri().quotedTablename ()
for i in l_ids :
if leves == 'ESRI' :
query="UPDATE "+l_qtablename+" SET geom = ST_SetSRID(st_makepoint(x_reel_esri,y_reel_esri),2154), statut = 'recal auto ESRI' WHERE id = " + str(i)+ ";"
elif leves == 'Chapuis':
query="UPDATE "+l_qtablename+" SET geom = ST_SetSRID(st_makepoint(x_chapuis,y_chapuis),2154), statut = 'recal auto Chapuis' WHERE id = " + str(i)+ ";"
elif leves == 'Corrige':
query="UPDATE "+l_qtablename+" SET geom = ST_SetSRID(st_makepoint(x_corrige,y_corrige),2154), statut = 'recal auto Corrige' WHERE id = " + str(i)+ ";"
elif leves == 'CSV':
query="UPDATE "+l_qtablename+" SET geom = ST_SetSRID(st_makepoint(x_csv,y_csv),2154), statut = 'recal auto CSV' WHERE id = " + str(i)+ ";"
elif leves == 'DWG':
query="UPDATE "+l_qtablename+" SET geom = ST_SetSRID(st_makepoint(x_dwg,y_dwg),2154), statut = 'recal auto DWG' WHERE id = " + str(i)+ ";"
elif leves == 'ProxDWG':
query="UPDATE "+l_qtablename+" SET geom = ST_SetSRID(st_makepoint(x_proxdwg,y_proxdwg),2154), statut = 'recal auto prox DWG' WHERE id = " + str(i)+ ";"
result=layer.dataProvider().transaction().executeSql(query,True)
if result[0] == True :
pass
else :
echecs.append(str(i) + " : " + result[1].split('\n')[0])
if len(echecs) == 0 :
self.iface.messageBar().pushMessage("Recalage réussi pour {} objets".format(len(l_ids)), Qgis.Info)
echecs=[]
l_qtablename=layer.dataProvider().uri().quotedTablename ()
for i in l_ids :
query="UPDATE "+l_qtablename+" SET geom = ST_SetSRID(st_makepoint(x_reel,y_reel), 2154) WHERE id = " + str(i)+ ";"
result=layer.dataProvider().transaction().executeSql(query,True)
if result[0] == True :
pass
else :
self.iface.messageBar().pushMessage("Recalage echoué pour {}/{} : ".format(len(echecs),len(l_ids)) + ','.join(echecs), Qgis.Warning)
# return
echecs.append(str(i) + " : " + result[1].split('\n')[0])
if len(echecs) == 0 :
self.iface.messageBar().pushMessage("Recalage réussi pour {} objets".format(len(l_ids)), Qgis.Info)
else :
self.iface.messageBar().pushMessage("Recalage echoué pour {}/{} : ".format(len(echecs),len(l_ids)) + ','.join(echecs), Qgis.Warning)
# return
else :
self.iface.messageBar().pushMessage("La couche sélectionnée n'est pas de type point", Qgis.Warning)
return
......
......@@ -7,30 +7,13 @@ CREATE OR REPLACE FUNCTION fnc_insert_from_jsonb(
)
RETURNS integer AS $BODY$
DECLARE
_json_keys text;
_json_values text;
_json_match record;
_upd_json jsonb;
BEGIN
i_json := jsonb_strip_nulls(i_json);
_json_match := utils.fnc_json_match_table(i_regclass, i_json);
with matching as (
SELECT key,
case
when udt_name = 'geometry' then ST_SetSRID(St_GeomFromGeoJSON(value), 2154)::text
when data_type = 'ARRAY' then replace(replace(value,'[','{'),']','}')::text
else value
end::text valuee
from jsonb_each_text(i_json)
inner join information_schema.columns
on table_schema=(parse_ident(i_regclass::text))[1]
and table_name=(parse_ident(i_regclass::text))[2]
and column_name=key
)
select string_agg(key::text,','), string_agg(quote_nullable(valuee::text),',')
INTO _json_keys, _json_values
FROM matching;
EXECUTE 'INSERT INTO '|| i_regclass ||' ('|| _json_keys ||')
VALUES ('|| _json_values ||')
EXECUTE 'INSERT INTO '|| i_regclass ||' ('|| _json_match.o_json_keys ||')
VALUES ('|| _json_match.o_json_values ||')
returning id;'
into o_id;
......
\encoding UTF8
set search_path to utils, public;
CREATE OR REPLACE FUNCTION fnc_json_match_table(
IN i_regclass regclass,
IN i_new_json jsonb,
IN i_old_json jsonb DEFAULT jsonb_build_object('emptyjson', Null),
OUT o_json_keys text,
OUT o_json_values text,
OUT o_upd_json jsonb
)
RETURNS record AS $BODY$
with upd_keys as (
select n.key, n.value
from jsonb_each_text(i_new_json) n
left outer join (select * from jsonb_each_text(i_old_json)) o on o.key=n.key
where n.key='id' or n.value IS DISTINCT FROM o.value
)
, matching as (
SELECT key,
case
when udt_name = 'geometry' then ST_SetSRID(St_GeomFromGeoJSON(value), 2154)::text
when data_type = 'ARRAY' then replace(replace(value,'[','{'),']','}')::text
else value
end::text valuee
from upd_keys
inner join information_schema.columns
on table_schema=(parse_ident(i_regclass::text))[1]
and table_name=(parse_ident(i_regclass::text))[2]
and column_name=key
)
select string_agg(key::text,',') o_json_keys
, string_agg(quote_nullable(valuee::text),',') o_json_values
, jsonb_object_agg(key,valuee) o_upd_json
FROM matching;
$BODY$
LANGUAGE sql IMMUTABLE SECURITY DEFINER
COST 100;
\encoding UTF8
set search_path to utils, public;
CREATE OR REPLACE FUNCTION fnc_remove_spikes(
CREATE OR REPLACE FUNCTION fnc_remove_spike(
IN i_geom geometry,
OUT o_geom geometry
)
......@@ -14,8 +14,8 @@ with dump_pipe as (
)
, intsct as (
SELECT *
,ST_DWithin(LEAD(vtx,1) OVER (ORDER by no_vtx), segmt_lag, config.get_tolerance('topo')) intsct_lag
,ST_DWithin(LAG(vtx,1) OVER (ORDER by no_vtx), segmt_lead, config.get_tolerance('topo')) intsct_lead
,ST_DWithin(LEAD(vtx,1) OVER (ORDER by no_vtx), segmt_lag, config.get_tolerance('spike')) intsct_lag
,ST_DWithin(LAG(vtx,1) OVER (ORDER by no_vtx), segmt_lead, config.get_tolerance('spike')) intsct_lead
FROM dump_pipe
)
select st_makeline(array_agg(vtx)) o_geom
......
\encoding UTF8
set search_path to utils, public;
CREATE OR REPLACE FUNCTION fnc_set_default_value(
IN i_regclass regclass,
IN i_new record,
OUT o_new_json jsonb
)
RETURNS jsonb AS $BODY$
DECLARE
_def_value record;
_select_values text;
_calc_values record;
BEGIN
o_new_json := row_to_json(i_new.*)::jsonb;
for _def_value in EXECUTE FORMAT ('SELECT * FROM %1$I.default_value
where (tablename=%2$L or tablename=''_all'')
and (%3$L::jsonb @> objectdef::jsonb or objectdef is null);'
,(parse_ident(i_regclass::text))[1], (parse_ident(i_regclass::text))[2], o_new_json::text) LOOP
if _def_value.defvalue is not null then
o_new_json := o_new_json || _def_value.defvalue;
end if;
if _def_value.calcvalue is not null then
select string_agg(value||' '||key ::text,',') INTO _select_values from jsonb_each_text(_def_value.calcvalue);
EXECUTE FORMAT ('SELECT %1$s FROM (SELECT (a).* FROM (SELECT $1 a) b) c', _select_values) USING i_new INTO _calc_values;
o_new_json := o_new_json || row_to_json(_calc_values.*)::jsonb;
end if;
END LOOP;
RETURN;
END;
$BODY$
LANGUAGE plpgsql VOLATILE SECURITY DEFINER
COST 100;
......@@ -3,44 +3,23 @@ set search_path to utils, public;
CREATE OR REPLACE FUNCTION fnc_update_from_jsonb(
IN i_regclass regclass,
IN i_new_json jsonb,
IN i_old_json jsonb
IN i_old_json jsonb DEFAULT jsonb_build_object('emptyjson', Null)
)
RETURNS void AS $BODY$
DECLARE
_json_keys text;
_json_values text;
_json_match record;
_upd_json jsonb;
_query text;
BEGIN
select json_object_agg(n.key,n.value) INTO i_new_json
from jsonb_each(i_new_json) n
left outer join (select * from jsonb_each(i_old_json)) o on o.key=n.key
where n.key='id' or n.value!=o.value or o.key is null;
_json_match := utils.fnc_json_match_table(i_regclass, i_new_json - 'id', i_old_json);
with matching as (
SELECT key,
case
when udt_name = 'geometry' then ST_SetSRID(St_GeomFromGeoJSON(value), 2154)::text
when data_type = 'ARRAY' then replace(replace(value,'[','{'),']','}')::text
else value
end::text valuee
from jsonb_each_text(i_new_json)
inner join information_schema.columns
on table_schema=(parse_ident(i_regclass::text))[1]
and table_name=(parse_ident(i_regclass::text))[2]
and column_name=key
where key!='id'
)
select string_agg(key::text,','), string_agg(quote_nullable(valuee::text),',')
INTO _json_keys, _json_values
FROM matching;
if _json_keys like '%,%' then
if _json_match.o_json_keys like '%,%' then
_query := 'UPDATE '|| i_regclass ||'
SET ('|| _json_keys ||') = ('|| _json_values ||')
SET ('|| _json_match.o_json_keys ||') = ('|| _json_match.o_json_values ||')
WHERE id = '|| (i_new_json->>'id') ||';';
else
_query := 'UPDATE '|| i_regclass ||'
SET '|| _json_keys ||' = '|| _json_values ||'
SET '|| _json_match.o_json_keys ||' = '|| _json_match.o_json_values ||'
WHERE id = '|| (i_new_json->>'id') ||';';
end if;
......
......@@ -8,8 +8,11 @@ CREATE TABLE IF NOT EXISTS config.tolerance (
type varchar(15) PRIMARY KEY,
distance float
);
INSERT INTO config.tolerance VALUES('topo', 0.01)
ON CONFLICT DO NOTHING;
INSERT INTO config.tolerance VALUES('spike', 0.05)
ON CONFLICT DO NOTHING;
CREATE OR REPLACE FUNCTION config.get_tolerance(i_type varchar(15))
RETURNS double precision AS
......@@ -31,6 +34,13 @@ CREATE TABLE IF NOT EXISTS config.pipe_default_node (
UNIQUE(schemaname,level)
);
CREATE TABLE IF NOT EXISTS default_value (
tablename varchar(20)
, objectdef jsonb
, defvalue jsonb
, calcvalue jsonb
);
INSERT INTO config.pipe_default_node
SELECT :'schemaname', code, True FROM config.vl_level
ON CONFLICT DO NOTHING;
......
......@@ -102,7 +102,7 @@ begin
END ugeom
FROM %1$I.%2$I p
LEFT OUTER JOIN %1$I.lpipe lp ON lp.end_node=p.id
,utils.fnc_get_closest_pipe(coalesce(lp.geom, p.geom), p.level,''%1$I.pipe'') tp
,utils.fnc_get_closest_pipe(p.geom, p.level,''%1$I.pipe'') tp
WHERE p.pipe_id = %4$s
)
UPDATE %1$I.%2$I p
......
......@@ -23,7 +23,7 @@ begin
-- >>> Tolerance for snapping <<<
select config.get_tolerance('topo') into _distance;
new.geom:=ST_RemoveRepeatedPoints(new.geom, _distance);
new.geom:=utils.fnc_remove_spikes(new.geom);
new.geom:=utils.fnc_remove_spike(new.geom);
-- >>> Find start & end nodes <<<
for _node_table_name in select unnest(_node_tables) LOOP
if _start_node is null or _end_node is null THEN
......
......@@ -15,6 +15,9 @@ DECLARE
_def_node record;
_def_node_new jsonb;
_def_node_new_geom geometry;
_def_value record;
_select_values text;
_calc_values record;
begin
--==== INSTEAD OF INSERT ON VIEW ====
-- >>> Get tables <<<
......@@ -35,7 +38,21 @@ begin
,TG_TABLE_SCHEMA, _nw_table, new.geom, _level, _distance)
INTO _geom_id;
-- >>> New row to jsonb <<<
_new:=jsonb_strip_nulls(row_to_json(new.*)::jsonb);
_new := row_to_json(new.*)::jsonb;
-- ++ Calculate defaults values ++
for _def_value in EXECUTE FORMAT ('SELECT * FROM %1$I.default_value
where (tablename=%2$L or tablename=''_all'')
and (%3$L::jsonb @> objectdef::jsonb or objectdef is null);'
,TG_TABLE_SCHEMA, _table, _new::text) LOOP
if _def_value.defvalue is not null then
_new := _new || _def_value.defvalue;
end if;
if _def_value.calcvalue is not null then
select string_agg(value||' '||key ::text,',') INTO _select_values from jsonb_each_text(_def_value.calcvalue);
EXECUTE FORMAT ('SELECT %1$s FROM (SELECT (a).* FROM (SELECT $1 a) b) c', _select_values) USING new INTO _calc_values;
_new := _new || row_to_json(_calc_values.*)::jsonb;
end if;
END LOOP;
_new := _new -'id' || jsonb_build_object('level', _level);
-- >>> Insert geom if not exist <<<
IF _geom_id is null then
......@@ -47,9 +64,8 @@ begin
for _def_node in EXECUTE FORMAT ('SELECT * FROM %1$I.pipe_default_node
where pipetable=%2$L and (%3$L::jsonb @> pipedef::jsonb or pipedef is null);'
,TG_TABLE_SCHEMA, _table, _new::text) LOOP
EXECUTE FORMAT ('SELECT %1$s
FROM (SELECT %2$L geom) b;'
, _def_node.calcgeom, new.geom) INTO _def_node_new_geom;
EXECUTE FORMAT ('SELECT %1$s FROM (SELECT (a).* FROM (SELECT $1 a) b) c'
, _def_node.calcgeom) USING new INTO _def_node_new_geom;
_def_node_new := _new || _def_node.defvalue || jsonb_build_object('geom', _def_node_new_geom);
PERFORM utils.fnc_insert_from_jsonb(TG_TABLE_SCHEMA||'.vw_'||_def_node.nodetable, _def_node_new);
END LOOP;
......@@ -57,7 +73,7 @@ begin
ELSE
-- Update geom attributes
_new := _new - 'geom' || jsonb_build_object('id', _geom_id);
PERFORM utils.fnc_update_from_jsonb(TG_TABLE_SCHEMA||'.'||_nw_table, _new, jsonb_build_object('emptyjson', 'None'));
PERFORM utils.fnc_update_from_jsonb(TG_TABLE_SCHEMA||'.'||_nw_table, _new);
END IF;
-- >>> Control if object exist <<<
EXECUTE FORMAT (
......
......@@ -12,6 +12,9 @@ DECLARE
_level int;
_new jsonb;
_old jsonb;
_def_value record;
_select_values text;
_calc_values record;
begin
--==== INSTEAD OF UPDATE ON VIEW ====
-- >>> Get tables <<<
......@@ -56,6 +59,20 @@ begin
-- >>> Update attributes <<<
_old:=row_to_json(old.*)::jsonb;
_new := row_to_json(new.*)::jsonb;
-- ++ Calculate defaults values ++
for _def_value in EXECUTE FORMAT ('SELECT * FROM %1$I.default_value
where (tablename=%2$L or tablename=''_all'')
and (%3$L::jsonb @> objectdef::jsonb or objectdef is null);'
,TG_TABLE_SCHEMA, _table, _new::text) LOOP
if _def_value.defvalue is not null then
_new := _new || _def_value.defvalue;
end if;
if _def_value.calcvalue is not null then
select string_agg(value||' '||key ::text,',') INTO _select_values from jsonb_each_text(_def_value.calcvalue);
EXECUTE FORMAT ('SELECT %1$s FROM (SELECT (a).* FROM (SELECT $1 a) b) c', _select_values) USING new INTO _calc_values;
_new := _new || row_to_json(_calc_values.*)::jsonb;
end if;
END LOOP;
_new :=_new - 'geom';
_new :=_new || jsonb_build_object('id', coalesce(_geom_id,new.id));
PERFORM utils.fnc_update_from_jsonb(TG_TABLE_SCHEMA||'.'||_nw_table, _new, _old);
......
......@@ -12,13 +12,13 @@ EXECUTE PROCEDURE utils.fnc_tgg_pipe_before('{"node"}');
DROP TRIGGER IF EXISTS tgg_pipe_after ON pipe ;
CREATE TRIGGER tgg_pipe_after
AFTER INSERT OR UPDATE of geom, level OR DELETE
AFTER INSERT OR UPDATE of geom OR DELETE
ON pipe FOR EACH ROW
EXECUTE PROCEDURE utils.fnc_tgg_pipe_after('node', '{"lnode","part"}');
DROP TRIGGER IF EXISTS tgg_pipe_check_geom ON pipe ;
CREATE CONSTRAINT TRIGGER tgg_pipe_check_geom
AFTER INSERT OR UPDATE of geom, level
AFTER INSERT OR UPDATE of geom
ON pipe FOR EACH ROW
EXECUTE PROCEDURE utils.fnc_tgg_pipe_check_geom('lpipe');
......@@ -31,12 +31,12 @@ EXECUTE PROCEDURE utils.fnc_tgg_pipe_before('{"lnode","node"}');
DROP TRIGGER IF EXISTS tgg_lpipe_after ON lpipe ;
CREATE TRIGGER tgg_lpipe_after
AFTER INSERT OR UPDATE of geom, level OR DELETE
AFTER INSERT OR UPDATE of geom OR DELETE
ON lpipe FOR EACH ROW
EXECUTE PROCEDURE utils.fnc_tgg_pipe_after('lnode', '{"lpart"}');
DROP TRIGGER IF EXISTS tgg_lpipe_check_geom ON lpipe ;
CREATE CONSTRAINT TRIGGER tgg_lpipe_check_geom
AFTER INSERT OR UPDATE of geom, level
AFTER INSERT OR UPDATE of geom
ON lpipe FOR EACH ROW
EXECUTE PROCEDURE utils.fnc_tgg_pipe_check_geom('pipe');
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment