NAME

DBIO::PostgreSQL::PostGIS::Storage - Storage class with PostGIS spatial extensions

VERSION

version 0.900001

DESCRIPTION

A storage layer that adds PostGIS-aware helper methods (extension ensure/probe, version, deploy-class selection) to a PostgreSQL storage. It is not a storage subclass: it is a plain method package composed over the resolved driver storage at connection time (see DBIO::Storage::Composed). DBIO::PostgreSQL::PostGIS registers it via "register_storage_layer" in DBIO::Schema, so on $schema->connect the live storage isa both this layer and DBIO::PostgreSQL::Storage, and its methods below are callable on that composed storage.

Layer rules

Per the storage-layer composition model (DBIO core, storage-layer composition): this package does not use base a driver storage, defines no constructor, and calls only the documented public storage surface (dbh_do, throw_exception) -- which resolves through the composed MRO to the driver base at runtime. New methods here (ensure_postgis, postgis_version, _ensure_postgis_extension) do not shadow any base method; dbio_deploy_class below is a deliberate override of the base hook.

dbio_deploy_class is a single-owner base-hook override

"dbio_deploy_class" overrides the base storage's deploy-class hook to route $schema->deploy through the PostGIS-aware deploy class. Under the core composition collision rule, exactly one composed layer may own a given method: if a second deploy-hooking extension (e.g. another spatial/graph layer that also defines its own dbio_deploy_class) is registered alongside this one, composition croaks at compose time naming dbio_deploy_class and every defining package. That is fail-loud by design -- the deploy class cannot be silently decided by registration order. Two deploy-extending extensions on one schema is a new core requirement (deploy-hook chaining), not a workaround here.

No async layer

PostGIS ships no ::Async sibling: its storage surface (extension ensure, version, deploy class) is synchronous, and the spatial codecs / ResultSet helpers are not storage-async-level. Core composition skips silently any registered layer that has no ::Async mirror, so under any async connection mode ({ async => ... }) the composed async backend simply carries no PostGIS async layer, and CRUD on geometry columns flows through the transport unchanged. If async deploy or codec hooks are ever needed, that is a separate ticket.

METHODS

ensure_postgis

$storage->ensure_postgis;

Issues CREATE EXTENSION IF NOT EXISTS postgis against the connected database. Idempotent.

postgis_version

my $v = $storage->postgis_version;

Returns the PostGIS extension version string from PostGIS_Full_Version(), or undef if the extension is not installed.

_ensure_postgis_extension

$storage->_ensure_postgis_extension;

Cheap fail-fast check that the postgis extension is installed on the connected database. Throws a DBIO::Exception with a message naming the missing extension and the database when the extension is not present. A no-op when the extension is installed.

Intended to be wrapped around first-use storage operations by callers that require PostGIS (deploy, schema load, geometry inflation). The core driver does not call this automatically so that storage construction against a non-PostGIS database remains possible for introspection and other PostGIS-agnostic tasks.

dbio_deploy_class

Returns DBIO::PostgreSQL::PostGIS::Deploy to activate PostGIS-aware deploy when $schema->deploy is called on a PostGIS-enabled schema. This overrides the base storage's deploy-class hook; as a single-owner base override it composes cleanly, but a second layer that also defines its own dbio_deploy_class makes composition croak (see "dbio_deploy_class is a single-owner base-hook override").

AUTHOR

DBIO Authors

COPYRIGHT AND LICENSE

Copyright (C) 2026 DBIO Authors

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.