Hi Pierre,
having proper support for multiple schemas is something that has been on
the TODO list for a while.
Now, a simple, although incomplete, solution would be to track for each
feature type the origin schema,
and use it to build queries, when the schema has not been provided to the
store factory.

That however has a downside, that one cannot handle two same named tables
in different namespaces.
And no, we cannot use namespace as a way to track the schema, because
that's a parameter provided
from the outside, again to the store factory. Once provided, it must be
honored, failing to do so
would break backwards compatibility (and generally speaking, break a lot of
existing GeoServer installations,
where the namespace URI is always provided, and comes from the workspace
configuration in which the store is found).

Given that a Name is made of namespace URI and simple name only, there is
no place where the schema can be put
in a clean way. In a less clean way, the schema may become a prefix in the
name only, with all the limits of
a simple name built as "prefix:tableName" (potential conflicts if one
starts using your separator of choice in the
schema or table names). If not clean, this should at least be livable.
If you go this way, the prefixing should be enabled with a new optional
store parameter (w.g., schemaPrefix=true/false),
again for backwards compatibility.

A separate store is also an option, but everything in JDBCDataStore is
final, to avoid the temptation to write
custom database classes, so you'd be stuck having to replicate all the
code...

Anyone have any better ideas?

Regards,

Andrea Aime


==
GeoServer Professional Services from the experts!

Visit http://bit.ly/gs-services-us for more information.
==

Ing. Andrea Aime
@geowolf
Technical Lead

GeoSolutions Group
phone: +39 0584 962313

fax:     +39 0584 1660272

mob:   +39  339 8844549

https://www.geosolutionsgroup.com/

http://twitter.com/geosolutions_it

-------------------------------------------------------

Con riferimento alla normativa sul trattamento dei dati personali (Reg. UE
2016/679 - Regolamento generale sulla protezione dei dati “GDPR”), si
precisa che ogni circostanza inerente alla presente email (il suo
contenuto, gli eventuali allegati, etc.) è un dato la cui conoscenza è
riservata al/i solo/i destinatario/i indicati dallo scrivente. Se il
messaggio Le è giunto per errore, è tenuta/o a cancellarlo, ogni altra
operazione è illecita. Le sarei comunque grato se potesse darmene notizia.

This email is intended only for the person or entity to which it is
addressed and may contain information that is privileged, confidential or
otherwise protected from disclosure. We remind that - as provided by
European Regulation 2016/679 “GDPR” - copying, dissemination or use of this
e-mail or the information herein by anyone other than the intended
recipient is prohibited. If you have received this email by mistake, please
notify us immediately by telephone or e-mail


On Wed, Mar 6, 2024 at 10:34 AM Pierre Mauduit <
pierre.maud...@camptocamp.com> wrote:

> Hello,
>
> I was willing to use the gt-postgis module to query a postgresql database
> where the data are stored inside different schema, and was surprised by the
> behaviour of the library in its current state.
>
> First, the module is able to find every relevant tables no matter the
> (database) schema it is stored into, but then trying to access the returned
> typenames lead to SQL query errors as it generally does not explicitely
> target the expected database schema.
>
> Considering a database with the following structure (schema.table):
>
> * nongeo.flup
> * fo.armoires
> * "savoie"."73-Savoie"
>
> And the following pseudocode (it is actually valid groovy code):
>
> import org.geotools.api.data.DataStoreFinder
> import org.geotools.api.data.Query
> import org.geotools.feature.NameImpl
>
> def ds = DataStoreFinder.getDataStore([
>         "dbtype": "postgis",
>         "host": "localhost",
>         "port": 5432,
>         "database": "mel",
>         "user": "pmauduit",
>         "passwd": "secret",
> ])
>
>
> println ds.getTypeNames()
>
> ds.getTypeNames().each {
> def fs = ds.getFeatureSource(it)
> println "${fs.getCount(Query.ALL)} features in ${it}"
> }
>
>
> The call to getTypeNames() will return [armoires, flup, 73-savoie] which I
> was expecting, meaning that the module was able to discover all the tables
> of interest from my database, no matter the schema they are nested in.
>
> But then the call to getFeatureSource() in the loop will fail, because the
> table is not in the search_path of my user, leading to the following
> warnings/errors:
>
> WARNING: Failure occurred while looking up the primary key with finder:
> org.geotools.jdbc.HeuristicPrimaryKeyFinder@4996c99
> org.postgresql.util.PSQLException: ERROR: relation "armoires" does not
> exist
> WARNING: Error occured determing srid for armoires.geom
> [...]
> org.postgresql.util.PSQLException: ERROR: relation "public.armoires" does
> not exist
> WARNING: Failed to retrieve information about public.armoires.geom by
> examining the first sample geometry
> org.postgresql.util.PSQLException: ERROR: relation "public.armoires" does
> not exist
> [...]
>
> I then skimmed into the codebase, looking for a way to have versions of
> the classes that would be "schema-agnostic". I stumbled upon the
> PostGisDialect class which looked as a good start, but was not sufficient
> to circumvent my issue. So I began to relax some code enforcement (removing
> final modifier on the JDBCDataStore class, copy/pasting code to get more
> familiar with the codebase and how objects interact each other, ...), and
> created a version of the objects (e.g. SchemaAwareJDBCDataStore,
> SchemaAwareJDBCFeatureSource). I also stumbled upon the class being used to
> represent typenames (NameImpl), and figured out it was mainly composed of a
> namespaceURI, a separator and a localName, each being a String. So I
> wondered why not considering the namespaceURI could be in our case the name
> of the postgresql schema the table belongs to, even if it is not a "URI"
> per se ?
>
> At this point, my current modifications are more of a PoC, but using a
> custom parameter (schemaAware set to true in the params list), I could
> switch to my custom version of the classes. As a result, using the
> following pseudocode:
>
> def ds = DataStoreFinder.getDataStore([
>         "dbtype": "postgis",
>         "host": "localhost",
>         "port": 5432,
>         "database": "mel",
>         "user": "pmauduit",
>         "passwd": "secret",
>         "schemaAware": true
> ])
>
> ds.getTypeNames().each {
>     def fs = ds.getFeatureSource(it)
>     println "${fs.getCount(Query.ALL)} features in ${it}"
>
> }
>
> will produce the following output:
>
> 56 features in fo.armoires
> 4 features in nongeo.flup
> 305 features in savoie.73-savoie
>
> But the getCount() is almost the only call working for now.
>
> To summarize, before getting further, here are some questions I am asking
> myself and would have liked to share with you / have your inputs on it:
>
> * Is there any reason that I may have missed for the existing
> implementation to react this way ?
> * Am I on the right track with my approach and/or do you think I missed
> some understandings on how the library is designed and works ?
> * Would a custom JDBC datastore being able to be schema-agnostic of
> interest for the project ?
>
> Thanks in advance for your inputs,
>
> Regards,
>
> --
>
> Pierre Mauduit
>
> Ingénieur développement
>
>
> Camptocamp France SAS 18 rue du Lac Saint André Savoie Technolac -
> Bâtiment Le Dauphin F-73370 Le Bourget du Lac Tel. +33 (0)4 58 48 20 24 Fax
> +33(0)4 58 48 20 10 www.camptocamp.com
> _______________________________________________
> GeoTools-Devel mailing list
> GeoTools-Devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/geotools-devel
>
_______________________________________________
GeoTools-Devel mailing list
GeoTools-Devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/geotools-devel

Reply via email to