Conversation
The wire form of an ISO 19139 quantitative result types the anyType value element via xsi:type (<gco:Record xsi:type="gml:doubleList">) and carries an empty valueUnit sibling. The decoder rejected any xsi:type; inside a value-wrap chain the attribute types the content of a value element rather than substituting a schema type, so it is now tolerated and dropped there. xsi:type on schema-mapped elements (feature, object and property elements) remains rejected. - FeatureTokenDecoderGml: exempt value-wrap chain elements from rejectXsiType via the new isValueWrapChainElement, which also replaces the equivalent inline condition for pushing VALUE_WRAPPER frames - FeatureTokenDecoderGmlSpec: cover the full genauigkeitswert structure including xsi:type and the empty valueUnit element
Some application schemas (e.g. AX_PunktortAU in the German AFIS-ALKIS-ATKIS NAS schema) carry exactly one position per feature, but in one of several CRSs - including realizations that map to the same EPSG code, 1D vertical reference systems, and coordinate forms whose false easting differs from the CRS definition (Gauss-Krueger without the zone prefix). Each variant is stored in its own geometry property with its own storage CRS; the verbatim srsName is stored alongside so encoders can reproduce it. - SchemaBase/FeatureSchema: new `crs` option - the storage CRS of a geometry property, overriding the provider's nativeCrs - features-sql: the storage CRS travels as the WKT/WKB operation parameters (code, axis-order force); geometry writes route by property path, transform from the geometry's CRS to the column's storage CRS and emit the column's SRID (inserts and native updates) - FeatureTokenTransformerCoordinates: geometries with their own storage CRS pass through the request-CRS transformation untouched - geometries: EastingShift coordinates transformation - adds a constant to the easting, rounded to micrometres; converts between coordinate forms that differ only in the false easting - gml decoder: GmlGeometryVariants routing on the input profile - a position is routed by its verbatim srsName to a variant property (with a configured false-easting difference applied) or, for 1D vertical reference systems, captured as a scalar value at a FLOAT property; the verbatim srsName is emitted at a companion property; GeometryDecoderGml exposes the verbatim srsName and consumes 1D positions without building a Geometry
The mutation stats collector fed every geometry token into the spatial extent of the change events, interpreting position variants stored in a different CRS as native coordinates. Only the primary geometry now contributes, mirroring the read side, which computes the extent over the filter/primary geometry column. Also accumulate min/max across geometries instead of keeping only the last one.
- FeatureSchema: a 'variants' declaration on the primary geometry property groups the sibling properties that store the position as recorded (crsProperty, verticalProperty, geometryProperties); the new roles ORIGINAL_GEOMETRY, ORIGINAL_HEIGHT and ORIGINAL_CRS_IDENTIFIER identify the group members (implied when not declared) and make them internal: read from the data source, but excluded from queryables, sortables, public schemas and regular property encoding - variant properties declare the identifiers of their reference systems (originalCrsIdentifiers), the CRS they are stored in (nativeCrs), the CRS of the recorded positions (originalCrs, e.g. the authority axis order of a geographic CRS whose stored coordinates follow the GIS axis order) and a falseEastingDifference for identifiers whose coordinates use a different false easting than the CRS - VariantsResolver validates the declarations and sets the implied roles at provider start - GML decoder: a position is routed by its verbatim srsName to the variant property that lists the identifier, interpreted in originalCrs and shifted to conform to nativeCrs; a 1D vertical position is captured as a scalar at the vertical property; the srsName is stored verbatim at the crsProperty; the routing metadata moved from the decoder input profile into the schema - the read pipeline restores originalCrs so downstream encodings receive the positions as recorded - EpsgCrs: new auxiliary attribute alternativeUri declares an identifier under which a CRS is known in a community, used when rendering and decoding CRS identifiers on the wire - new WithoutInternal visitor for deriving public schemas
…othing
Predicates on properties that require a join are encoded as INNER-join
semi-joins (A.id IN (SELECT ...)). Negations derived from them were
unsatisfiable or wrong:
- not(<predicate>) was pushed into the subquery by string surgery,
negating the inner predicate ("some related row does not match")
instead of the whole predicate ("no related row matches"); features
without any related row were dropped by the INNER join. The whole
semi-join is now negated (NOT (...)), which is exact since the outer
operand is never null. This changes the result of filters like
NOT role = 'x' on multi-valued properties from "has some other value"
to "has no value 'x'", the consistent reading of logical negation.
- isNull(<property>) applied IS NULL to the joined column inside the
subquery, where it can never match. "No value" is now encoded as
NOT (A.id IN (SELECT ... WHERE <column> IS NOT NULL)).
Also return a 400 instead of a 500 for filter coordinates that cannot be
transformed: a failed transform yields a CoordinateTuple with
isNull()=true, not a null reference; CqlCoordinateChecker now checks it
instead of failing with a NullPointerException.
…the native CRS With skipUnusedPipelineSteps enabled, the COORDINATES pipeline step was skipped whenever the requested CRS equals the provider's native CRS. A geometry property that is stored in its own CRS and declares a differing originalCrs relies on that step to restore the recorded axis order of its positions, so such positions were emitted in the stored axis order while keeping the original srsName. The step is now kept for properties that declare a nativeCrs with a differing originalCrs, regardless of the requested CRS.
azahnen
left a comment
There was a problem hiding this comment.
@cportele
In general I would prefer to put this into an extension, but our current design doesn't really allow that. A more modular approach to the ever-growing FeatureSchema is something I will look into before v5. Two points regarding the PR:
-
Since variants are a concept specific to geometries, I think the naming of
getVariants,SchemaVariantsandVariantResolvershould reflect that. -
getNativeCrs(): Only relevant for properties withtype: GEOMETRYin SQL feature providers, when a feature type stores positions in more than one CRS in separate geometry columns.Couldn't this also be used for simpler cases with a single geometry column per type but mixed storage CRSs?
|
Agreed on a modularization of the feature schema (extensions).
|
The variants concept is specific to geometry properties that store the same logical position in several CRSs; the generic names did not reflect that. - configuration key on geometry properties: variants -> crsVariants - SchemaVariants -> CrsVariants - VariantsResolver -> CrsVariantsResolver - FeatureSchema.getVariants() -> getCrsVariants() - validation messages and documentation updated accordingly
|
@azahnen - the renaming is done (in ldproxy, too). |
azahnen
left a comment
There was a problem hiding this comment.
@cportele Thanks!
Regarding 2, but the spec is not the concern of the provider. If I sent a simple query to the provider requesting raw tokens (to circumvent potential encoder limitations), would it work for a type with a deviating nativeCrs?
|
@azahnen - Regarding your question: Partially. The token stream itself would work: a geometry property with its own |
Part of addressing ldproxy/ldproxy#1692
Adds support for feature types that store geometries in one of several CRSs.
FeatureSchema: avariantsdeclaration on the primary geometry property groups the sibling properties that store a position as recorded; new rolesORIGINAL_GEOMETRY,ORIGINAL_HEIGHTandORIGINAL_CRS_IDENTIFIERidentify the group members and make them internal (readable, but not part of any public schema or regular encoding). Variant properties declare the identifiers of their reference systems (originalCrsIdentifiers), the CRS they are stored in (nativeCrs), the CRS of the recorded positions (originalCrs) and, where needed, afalseEastingDifference.srsNameto the matching variant property (1D positions as scalars, the identifier stored verbatim); the read pipeline restoresoriginalCrsso encodings receive the recorded positions.EpsgCrs: new auxiliaryalternativeUrifor community URIs of a CRS.Also extends the GML decoder for ISO 19139 metadata structures on the wire (value-wrapper chains with attributes and empty elements,
xsi:typeon wrapper elements), so documents shaped like the encoder's output can be ingested losslessly.