1

I have a gis application using the following main technologies:

- OpenLayers 2.13.1;
- Postgresql 9.4.7;
- PostGIS 2.2.1;
- QGIS Server 2.16.1, installed with OSGeo4W - 32 bytes.

I must display some layers on the map and edit the features geometry, using QGIS Server and, for this, I am using OpenLayers - WFS. The layers are displaying well, without any problem. But the problem appears when I am trying to save the edited/new features geometry, using WFS-T (please see: http://www.gistutor.com/openlayers/22-advanced-openlayers-tutorials/47-openlayers-wfs-t-using-a-geoserver-hosted-postgis-layer.html). In order to find a solution, I have made some research and I have discovered that there are some columns in the database table having BOOLEAN or DATE data types, but with empty string instead of TRUE/FALSE or '2017-01-30' values and for this scenario the saving fails. This is because OpenLayers is sending to QGIS server/PostGIS a XML feed that is trying to update also the attributes, but with empty strings for these attributes correpondent to BOOLEAN (ENCLOSED - see below) or DATE (modified_at - see below) data types (In pgAdmin/PostgreSQL I cannot update a BOOLEAN column using an empty string and the system returns an error).

The command posted is:
<wfs:Transaction xmlns:wfs="http://www.opengis.net/wfs" service="WFS" 
    version="1.0.0" xsi:schemaLocation="http://www.opengis.net/wfs 
    http://schemas.opengis.net/wfs/1.0.0/WFS-transaction.xsd 
    http://www.qgis.org/gml http://localhost/qgis_server
    /qgis_mapserv.fcgi.exe?service=WFS&version=1.1.0&map=C:\OSGeo4W  
    \apps\qgis
    \bin/work.qgs&request=DescribeFeatureType&typeName=land" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <wfs:Update typeName="feature:cgxml_Land" 
        xmlns:feature="http://www.qgis.org/gml">
    <wfs:Property>
        <wfs:Name>geometry</wfs:Name>
        <wfs:Value>
            <gml:MultiPolygon xmlns:gml="http://www.opengis.net/gml"  
                srsName="EPSG:3844">
                <gml:polygonMember>
                    <gml:Polygon>
                        <gml:outerBoundaryIs>
                            <gml:LinearRing>
                                <gml:coordinates decimal="." cs="," ts=" ">609087.3816944876,612069.7245524937,0.00010463595390319824 609096.3033944874,612069.2933524915,0.00010464061051607132 609135.1759798289,612372.8172944221,0.0017628660425543785 609126.200094488,612064.265752496,0.00010463595390319824 609151.3419944876,612066.7777524978,0.00010463688522577286 609158.0495944872,612068.4783524954,0.00010463874787092209 609161.1084944872,612065.6449524972,0.00010463874787092209 609199.3978944882,612030.1782524938,0.00010463688522577286 608922.5359944875,611790.103952495,0.00010464340448379517 608922.1085944867,611790.5076524996,0.00010464433580636978 608857.9066944874,611851.091552499,0.00010464154183864594 608846.9590944864,611861.2476524961,0.00010464154183864594 609087.3816944876,612069.7245524937,0.00010463595390319824
                                </gml:coordinates>
                            </gml:LinearRing>
                        </gml:outerBoundaryIs>
                    </gml:Polygon>
                </gml:polygonMember>
            </gml:MultiPolygon>
        </wfs:Value>
    </wfs:Property>
    <wfs:Property>
        <wfs:Name>ID</wfs:Name>
        <wfs:Value>5256</wfs:Value>
    </wfs:Property>
    <wfs:Property>
        <wfs:Name>LANDID</wfs:Name>
        <wfs:Value>0</wfs:Value>
    </wfs:Property>
    <wfs:Property>
        <wfs:Name>ENCLOSED</wfs:Name>
        <wfs:Value></wfs:Value>
    </wfs:Property>
    <wfs:Property>
        <wfs:Name>created_by</wfs:Name>
        <wfs:Value>postgres</wfs:Value>
    </wfs:Property>
    <wfs:Property>
        <wfs:Name>created_at</wfs:Name>
        <wfs:Value>2016-10-12</wfs:Value>
    </wfs:Property>
    <wfs:Property>
        <wfs:Name>modified_by</wfs:Name>
        <wfs:Value>postgres</wfs:Value>
    </wfs:Property>
    <wfs:Property>
        <wfs:Name>modified_at</wfs:Name>
        <wfs:Value></wfs:Value>
    </wfs:Property>
    <ogc:Filter xmlns:ogc="http://www.opengis.net/ogc">
        <ogc:FeatureId fid="land.5256"></ogc:FeatureId>
    </ogc:Filter>
    </wfs:Update>
</wfs:Transaction>
I am selecting only the needed columns for table definition:
CREATE TABLE "land" (
"ID" integer NOT NULL,
"LANDID" integer,
"ENCLOSED" boolean,
created_by character varying(20),
created_at date,
modified_by character varying(20),
modified_at date
);
ALTER SEQUENCE "land_ID_seq" OWNED BY "land"."ID";
ALTER COLUMN "ID" SET DEFAULT nextval('"land_ID_seq"'::regclass);
The response of QGIS Server is something like this:
<WFS_TransactionResponse xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ogc="http://www
.opengis.net/ogc" version="1.0.0" xmlns="http://www.opengis.net/wfs" xsi:schemaLocation="http://www.opengis
.net/wfs http://schemas.opengis.net/wfs/1.0.0/wfs.xsd">
    <TransactionResult>
        <Status>
            <PARTIAL/>
        </Status>
        <Locator>Update</Locator>
        <Message>
            Provider errors: PostGIS error while changing attributes: ERROR:  invalid input syntax for type boolean: ""
            LINE 1: ..."ENCLOSED"='',created_at...                                                           ^
        </Message>
    </TransactionResult>
</WFS_TransactionResponse>
The response of QGIS Server ar DescribeFeatureType request:
<schema elementFormDefault="qualified" targetNamespace="http://www.qgis.org/gml" version="1.0">
    <import namespace="http://www.opengis.net/gml" schemaLocation="http://schemas.opengis.net/gml/2.1.2/feature.xsd"/>
    <element type="qgs:landType" name="land" substitutionGroup="gml:_Feature"/>
    <complexType name="landType">
        <complexContent>
            <extension base="gml:AbstractFeatureType">
                <sequence><element minOccurs="0" maxOccurs="1" type="gml:MultiPolygonPropertyType" name="geometry"/>
                    <element type="integer" name="ID"/>
                    <element type="integer" name="LANDID"/>
                    <element alias="Enclosed?" type="string" name="ENCLOSED"/>
                    <element type="string" name="created_by"/>
                    <element type="date" name="created_at"/>
                    <element type="string" name="modified_by"/>
                    <element type="date" name="modified_at"/>
                </sequence>
            </extension>
        </complexContent>
    </complexType>
</schema>

Sending a valid boolean/date value, returns SUCCESS, but I also have empty attributes because the correspondent columns in the database are also empty (this is the reality). Please help me to find a solution: firstly, I need to know if there is a possibility to send only geometry, without attributes, when I am editing the geometry and I am saving the modifications; secondly, I need to know if/how I can fix this scenario (for BOOLEAN/DATE attributes/columns) using a trigger in postgres, ignoring them in this way.

EDIT 2017-01-31:
The following work around can be used and works for my case:
var save = new OpenLayers.Control.Button({
    title: "Save Changes",
        trigger: function() {
            if(edit.feature) {
                edit.selectControl.unselectAll();
            }
            var modifFeatArr = [];
            for (var ss = 0; ss < vecLayer.features.length; ss++) {
                modifFeat = vecLayer.features[ss];
                if (modifFeat.state != null) {
                    modifFeat.attributes.ENCLOSED = 't';
                    modifFeat.attributes.COAREA = 't';
                    modifFeat.attributes.ISNEW = 't';
                    modifFeat.attributes.modified_at = '2017-01-31';
                    modifFeatArr.push(modifFeat);
                }
            }
            saveStrategy.save(modifFeatArr);
        },
    displayClass: "olControlSaveFeatures"
});
I will create a trigger:
CREATE TRIGGER "06_before_update"
    BEFORE UPDATE ON work.land
    FOR EACH ROW
        EXECUTE PROCEDURE work.before_update_land();

and the correspondent function:
CREATE OR REPLACE FUNCTION work.before_update_land()
    RETURNS trigger AS
$BODY$  
    NEW."ENCLOSED" := OLD."ENCLOSED";
    NEW."COAREA" := OLD."COAREA";
    NEW."ISNEW" := OLD."ISNEW";
    NEW.modified_at := current_date;

    RETURN NEW;

    END;
$BODY$
    LANGUAGE plpgsql VOLATILE
    COST 100;
ALTER FUNCTION work.before_update_land()
    OWNER TO postgres;
  • please add the definition of the table to your question and what the GeoServer error is – Ian Turton Jan 30 '17 at 15:11
  • I have added the definition of the table and QGIS Server error. I am using QGIS server in this case, not GeoServer. The problem does not appear in GeoServer - I have verified. – Mini Jan 30 '17 at 16:14
  • can you do a describeFeature request and add that too please – Ian Turton Jan 30 '17 at 18:05
  • I have also added the response of QGIS Server's DescribeFeatureType and I see there is "string" allocated for ENCLOSED column instead of "boolean". May be here there is a problem, because I can see that Geoserver's response of DescribeFeatureType contain <xsd:element maxOccurs="1" minOccurs="0" name="ENCLOSED" nillable="true" type="xsd:boolean" />. – Mini Jan 30 '17 at 19:12
  • It still remains the question if we can update only geometry / geometry and some specific attributes, when using QGIS Server. – Mini Jan 31 '17 at 14:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.