ogc-cql2
Rust implementation of the Open Geospatial Consortium (OGC) Common Query Language (CQL2) described here.
This library aims to fulfill all the requirements listed under Conformance section of the specs.
So far, users of this library will be able to:
- Parse CQL2 Expressions in either Text- or JSON-encoded forms,
- Implement Evaluators to process collections of Resources (a.k.a features) against valid expressions.
- Make use of a comprehensive set of builtin Functions to use in writing their expressions.
- Implement their own versions of Functions and register them w/ Evaluators.
- Evaluate CQL2 Expressions against records provided by Data Sources through two traits: Iterable and Streamable. So far implementations for CSV and GeoPackage data-sources are also included.
Changes are tracked in ChangeLog.
Parsing Expression Grammar (PEG) + Typify
The text-encoded parser used in this project was generated by rust-peg by manually translating the source into input recognizable by that crate's peg::parser! macro. The reference BNF document is included in the doc folder.
The JSON-encoded one started life from code generated by the cargo-typify tool from the JSON Schema given in the Standard. However some limitations w/ that tool meant that manual intervention was required.
The modified JSON Schema input file is included w/ the source of this crate (cql2.json) as well as a patch file (cql2.json.patch) showing the changes from the original copy.
Change to the BNF Grammar
The BNF grammar specified in the specs limit the WKT representation of multi-point geometries to always enclose point coordinates w/in parenthesis as implied from the following rules...
multipointTaggedText = "MULTIPOINT" ["Z"] multiPointText;
multiPointText = "(" pointText {"," pointText} ")";
pointText = "(" point ")";
point = xCoord yCoord [zCoord];
That meant that text like MULTIPOINT(1 2, 3 4) causes a syntax error forcing the user to write it instead as MULTIPOINT((1 2), (3 4)).
This implementation allows for both forms.
Deviation from the Stadard
The CQL2 specs state that Dates should be considered as local with regard to time zones. This implementation however always assign them the UTC TZ.
Conformance tests
The tests folder contains tests that implement most of the Annex A: Abstract Test Suite (Normative) conformance tests, grouped in folders mirroring the level-1 sections of the specs.
Test data
The folder tests/samples/data contain 3 CSV files created/converted from the same named Layers in the GeoPackage referenced in the Standard, as well as the GeoPackage DB/file itself.
Those CSV files were first created by exporting each Layer to a CSV file using DB Browser for SQLite Version 3.13.1, then converting the geometries to their WKT form and renaming their column geom.
The GeoPackage DB/file is used for testing the GeoPackage Data Source and the Streamable Data Source trait with and without translating the filter expression to SQL.
The other 2 folders next to csv in the same parent folder mirror the same data found here.
Tests not implemented yet
Some tests, which test filter expressions with AND, OR, and NOT including sub-expressions of 4 predicates are not implemented yet. Those are:
- A.6.6. Conformance Test 24:
/conf/accent-insensitive-comparison/logical, - A.7.3. Conformance Test 27:
/conf/basic-spatial-functions/logical, - A.9.10. Conformance Test 39:
/conf/spatial-functions/logical, - A.10.4. Conformance Test 43:
/conf/temporal-functions/logical, - A.11.2. Conformance Test 45:
/conf/array-functions/logical, - A.12.5. Conformance Test 50:
/conf/property-property/logical, - A.14.3. Conformance Test 54:
/conf/arithmetic/logical,
Test result pending request for clarification
The issue here is at the time of this writing still unresolved.
For now, the relevant test (a6/test_23.rs) expected results have been amended according to the findings reported in the issue in question.
How to configure this library
- Make a copy of the file
.env.templateand rename it.env. - Make sure
.envis included in.gitignore. - Edit the contents of
.envto suit your requirements and environment.
For now these are the environment variables that can be configured:
DEFAULT_CRS
Coordinate Reference System (CRS) code to use when validating geometry coordinates. Defaults to EPSG:4326 if/when undefined.
DEFAULT_PRECISION
Precision (number of digits after the decimal point) to keep/use when processing coordinates. Defaults to 7 if/when undefined. For WGS 84 coordinates this translates to approx. 1.11 cm. accuracy when projecting them to Web Mercator.
For now only positive integers in the range 0..32 inclusive are allowed.
RUST_LOG
See https://docs.rs/env_logger/latest/env_logger/#enabling-logging for details.
Required external software
GEOS
This library relies on GEOS by virtue of its dependence on the geos crate. In my case the native installed version shows the following at the time this page was last updated...
)
)
)
SQLite + Spatialite extension
This library now supports GeoPackage database files. This requires an installed version of sqlite and libspatial binaries. The latter will provide the mod_spatialite.so extension usually to be found under /usr/lib64/. Here is the info about my test installation at the time of this page's last update...
TODO
In no particular order...
- Implement more Data Sources such as Shapefiles and PostGIS tables.
- Add an option to the
replcommand line tool to output valid expressions as SQL WHERE clauses. - Investigate implementing basic spatial operators for 2D geometries in pure Rust; i.e. removing ependenceon the
geoscrate. - Implement missing conformance tests preferably after finding an external set of Test Vectors.
- Add more Functions.
- Implement pooling of Evaluators à la DB connections pools.
- Refine the Evaluator trait as the external interface to this library.
- Investigate ways of translating Expressions to PostGIS clauses + views.
- Improve the way we handle user defined closures.
- Reduce allocation.
- Improve performance.
- Reduce code repetition by using more macros.
- Investigate alternative means for external clients to inject functions logic + metadata.
-
The WKT parsing machinery entry-point is private. Make it public.Done 2025-08-31. -
Properly manage + handle global configurable options such as default CRS bearing in mind how it may affect conformance tests.Done 2025-09-02. -
Add an LRU to store commonly used CRSes.Turns out Proj is notSendand hence cannot be cached in an LRU cache safely w/o introducingunsafecode.
License
This product is licensed under the Apache License Version 2.0 —see included copy or online