Skip to content

Commit

Permalink
Merge pull request #186 from VForWaTer/location_nullable
Browse files Browse the repository at this point in the history
entries.location nullable + db revision
  • Loading branch information
AlexDo1 authored Dec 12, 2022
2 parents faf2266 + 96a9c61 commit 5fc68a2
Show file tree
Hide file tree
Showing 7 changed files with 115 additions and 6 deletions.
2 changes: 1 addition & 1 deletion metacatalog/__version__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = '0.6.0'
__version__ = '0.6.1'
9 changes: 8 additions & 1 deletion metacatalog/api/add.py
Original file line number Diff line number Diff line change
Expand Up @@ -508,7 +508,14 @@ def add_entry(session, title, author, location, variable, abstract=None, externa
on id (int) or organisation_name (str).
location : str, tuple
Can be either a WKT of a EPSG:4326 location, or the coordinates as a
tuple. It has to be (X,Y), to (longitude, latitude)
tuple. It has to be (X,Y), to (longitude, latitude).
.. versionchanged:: 0.6.1
A POINT location should be specified here if there is a physical measurement
point that is different from the centroid of the spatial extent (e.g.,
discharge measurement with the extent of the catchment).
Otherwise, ``Datasource.spatial_scale.extent`` should be used to specify the
location of the measured data.
variable : int, str
**Full** variable name (str) or ID (int) of the data described by the Entry.
abstract : str
Expand Down
2 changes: 2 additions & 0 deletions metacatalog/db/revisions/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
rev8,
rev9,
rev10,
rev11,
)

revisions = {
Expand All @@ -24,4 +25,5 @@
8: rev8,
9: rev9,
10: rev10,
11: rev11,
}
46 changes: 46 additions & 0 deletions metacatalog/db/revisions/rev11.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
"""
Metacatalog database revision
-----------------------------
date: 2022-10-05T14:41:32.055433
revision #11
Make column entries.location nullable (raster data do not have a POINT location).
Attention, the downgrade sets everywhere where entries.location == NULL to
(POINT 0 0), which may not correspond to the state of the database before upgrading,
so the revision upgrade cannot be undone.
"""
from sqlalchemy.orm import Session
from metacatalog import api, models

UPGRADE_SQL = """
-- entries.location nullable
ALTER TABLE entries ALTER COLUMN location DROP NOT NULL;
COMMIT;
"""

DOWNGRADE_SQL = """
-- replace eventually existing NULL values with (POINT 0 0)
UPDATE entries SET location = 'SRID=4326; POINT (0 0)' WHERE location IS NULL;
COMMIT;
-- entries.location not nullable
ALTER TABLE entries ALTER COLUMN location SET NOT NULL;
COMMIT;
"""

# define the upgrade function
def upgrade(session: Session):
print('run update')
# make entries.location nullable
with session.bind.connect() as con:
con.execute(UPGRADE_SQL)


# define the downgrade function
def downgrade(session: Session):
print('run downgrade')
# make entries.location not nullable
with session.bind.connect() as con:
con.execute(DOWNGRADE_SQL)

39 changes: 39 additions & 0 deletions metacatalog/db/views/locations.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
--CREATE OR REPLACE VIEW locations_realdata AS
select
st_asewkt(t.point_location),
t.*,
st_area(t.geom::geography) as "area_sqm"
from
(SELECT
entries.id,
case when entries.location is not null then
entries.location
else
case when spatial_scales.extent is not null then
st_centroid(spatial_scales.extent)
else
case when entries.geom is not null then
st_centroid(entries.geom)
else
null::geometry
end
end
end
as point_location
,
case when entries.geom is not null then
entries.geom
else
case when spatial_scales.extent is not null then
spatial_scales.extent
else
entries.location
end
end
as "geom"
FROM entries
LEFT JOIN datasources ON entries.datasource_id = datasources.id
LEFT JOIN spatial_scales ON spatial_scales.id = datasources.spatial_scale_id
) as t

order by t.id asc
14 changes: 11 additions & 3 deletions metacatalog/models/datasource.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

from metacatalog.db.base import Base
from metacatalog.ext import extension
from metacatalog.util.exceptions import MetadataMissingError


class DataSourceType(Base):
Expand Down Expand Up @@ -337,9 +338,12 @@ class SpatialScale(Base):
cell size, which only applies to gridded datasets. Use the
:attr:`resolution_str` property for a string representation
extent : geoalchemy2.Geometry
The spatial extent of the dataset is given as a ``'POLYGON'``. While
metacatalog is capable of storing any kind of valid POLYGON as extent,
it is best practice to allow only Bounding Boxes on upload.
The spatial extent of the dataset is given as a ``'POLYGON'``.
.. versionchanged:: 0.6.1
From this ``POLYGON``, a bounding box and the centroid are internally
calculated.
To specify a point location here, use the same value for easting and
westing and the same value for northing and southing.
support : float
The support gives the spatial validity for a single observation.
It specifies the spatial extent at which an observed value is valid.
Expand Down Expand Up @@ -607,8 +611,12 @@ def create_scale(self, resolution, extent, support, scale_dimension, commit=Fals
# get the correct class
if scale_dimension.lower() == 'temporal':
Cls = TemporalScale
if self.temporal_scale is not None:
raise MetadataMissingError('Temporal scale already exists. You can edit that one.')
elif scale_dimension.lower() == 'spatial':
Cls = SpatialScale
if self.spatial_scale is not None:
raise MetadataMissingError('Spatial scale already exists. You can edit that one.')
else:
raise AttributeError("scale_dimension has to be in ['temporal', 'spatial']")

Expand Down
9 changes: 8 additions & 1 deletion metacatalog/models/entry.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,13 @@ class Entry(Base):
Usually an unque ID field of other data-storage solutions. The
exernal_id is only stored for reference reasons.
location : str, tuple
.. versionchanged:: 0.6.1
A POINT location should be specified here if there is a physical measurement
point that is different from the centroid of the spatial extent (e.g.,
discharge measurement with the extent of the catchment).
Otherwise, ``Datasource.spatial_scale.extent`` should be used to specify the
location of the measured data.
The location as a POINT Geometry in unprojected WGS84 (EPSG: 4326).
The location is primarily used to show all Entry objects on a map, or
perform geo-searches. If the data-source needs to store more complex
Expand Down Expand Up @@ -165,7 +172,7 @@ class Entry(Base):
title = Column(String(512), nullable=False)
abstract = Column(String)
external_id = Column(String)
location = Column(Geometry(geometry_type='POINT', srid=4326), nullable=False)
location = Column(Geometry(geometry_type='POINT', srid=4326), nullable=True)
geom = Column(Geometry)
version = Column(Integer, default=1, nullable=False)
latest_version_id = Column(Integer, ForeignKey('entries.id'), nullable=True)
Expand Down

0 comments on commit 5fc68a2

Please sign in to comment.