Skip to content

Commit

Permalink
Restore lost code (#199)
Browse files Browse the repository at this point in the history
* Restore lost code

* Remove old line
  • Loading branch information
Teddy-1000 authored Oct 2, 2024
1 parent d943ea7 commit e5e680c
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 64 deletions.
111 changes: 56 additions & 55 deletions datastore/datastore/storagebackend/postgresql/getextents.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,79 +5,80 @@ import (
"datastore/common"
"datastore/datastore"
"fmt"
"time"

_ "github.com/lib/pq"
"google.golang.org/grpc/codes"
"google.golang.org/protobuf/types/known/timestamppb"
)

// createExtQueryVals creates from request values used for querying extensions.
//
// Values to be used for query placeholders are appended to phVals.
//
// Returns:
// - time filter used in a 'WHERE ... AND ...' clause
// - filter for reflectable metadata fields of type int64 ... ditto
// - filter for reflectable metadata fields of type string ... ditto
func createExtQueryVals(request *datastore.GetExtentsRequest, phVals *[]interface{}) (
string, string, string) {
// getTemporalExtent gets the current temporal extent of all observations in the storage.
func getTemporalExtent(db *sql.DB) (*datastore.TimeInterval, error) {
query := "SELECT min(obstime_instant), max(obstime_instant) FROM observation"
row := db.QueryRow(query)

loTime, hiTime := common.GetValidTimeRange()
timeFilter := fmt.Sprintf(`
((obstime_instant >= to_timestamp(%d)) AND (obstime_instant <= to_timestamp(%d)))
`, loTime.Unix(), hiTime.Unix())
var start, end time.Time

err := row.Scan(&start, &end)
if err != nil {
return nil, fmt.Errorf("row.Scan() failed: %v", err)
}

int64MdataFilter := getInt64MdataFilter(request.GetFilter(), phVals)
stringMdataFilter := getStringMdataFilter(request.GetFilter(), phVals)
loTime, hiTime := common.GetValidTimeRange()
if start.Before(loTime) {
start = loTime
}
if end.After(hiTime) {
end = hiTime
}

return timeFilter, int64MdataFilter, stringMdataFilter
return &datastore.TimeInterval{
Start: timestamppb.New(start),
End: timestamppb.New(end),
}, nil
}

// GetExtents ... (see documentation in StorageBackend interface)
func (sbe *PostgreSQL) GetExtents(request *datastore.GetExtentsRequest) (
*datastore.GetExtentsResponse, codes.Code, string) {
// getSpatialExtent gets the current horizontally spatial extent of all observations in the storage.
func getSpatialExtent(db *sql.DB) (*datastore.BoundingBox, error) {
query := `
SELECT ST_XMin(ext), ST_YMin(ext), ST_XMax(ext), ST_YMax(ext)
FROM (SELECT ST_Extent(point::geometry) AS ext FROM geo_point) t
`
row := db.QueryRow(query)

var xmin, ymin, xmax, ymax float64

// get values needed for query
phVals := []interface{}{} // placeholder values
timeFilter, int64MdataFilter, stringMdataFilter := createExtQueryVals(request, &phVals)
err := row.Scan(&xmin, &ymin, &xmax, &ymax)
if err != nil {
return nil, fmt.Errorf("row.Scan() failed: %v", err)
}

query := fmt.Sprintf(`
SELECT temp_min, temp_max,
ST_XMin(spat_ext), ST_YMin(spat_ext), ST_XMax(spat_ext), ST_YMax(spat_ext)
FROM (
SELECT min(obstime_instant) AS temp_min, max(obstime_instant) AS temp_max,
ST_Extent(point::geometry) AS spat_ext
FROM observation
JOIN time_series ON observation.ts_id = time_series.id
JOIN geo_point ON observation.geo_point_id = geo_point.id
WHERE %s AND %s AND %s
) t
`, timeFilter, int64MdataFilter, stringMdataFilter)
return &datastore.BoundingBox{
Left: xmin,
Bottom: ymin,
Right: xmax,
Top: ymax,
}, nil
}

row := sbe.Db.QueryRow(query, phVals...)
// GetExtents ... (see documentation in StorageBackend interface)
func (sbe *PostgreSQL) GetExtents(_ *datastore.GetExtentsRequest) (
*datastore.GetExtentsResponse, codes.Code, string,
) {
var err error

var (
start, end sql.NullTime
xmin, ymin, xmax, ymax float64
)
temporalExtent, err := getTemporalExtent(sbe.Db)
if err != nil {
return nil, codes.Internal, fmt.Sprintf("getTemporalExtent() failed: %v", err)
}

err := row.Scan(&start, &end, &xmin, &ymin, &xmax, &ymax)
if !start.Valid { // indicates no matching rows found!
return nil, codes.NotFound, "no matching data to compute extensions for"
} else if err != nil {
return nil, codes.Internal, fmt.Sprintf("row.Scan() failed: %v", err)
spatialExtent, err := getSpatialExtent(sbe.Db)
if err != nil {
return nil, codes.Internal, fmt.Sprintf("getSpatialExtent() failed: %v", err)
}

return &datastore.GetExtentsResponse{
TemporalExtent: &datastore.TimeInterval{
Start: timestamppb.New(start.Time),
End: timestamppb.New(end.Time),
},
SpatialExtent: &datastore.BoundingBox{
Left: xmin,
Bottom: ymin,
Right: xmax,
Top: ymax,
},
TemporalExtent: temporalExtent,
SpatialExtent: spatialExtent,
}, codes.OK, ""
}
10 changes: 1 addition & 9 deletions protobuf/datastore.proto
Original file line number Diff line number Diff line change
Expand Up @@ -305,15 +305,7 @@ message GetTSAGResponse {
//---------------------------------------------------------------------------

message GetExtentsRequest {
// --- BEGIN filter for reflectable metadata of type int64 or string -------------------------

// general filter
// - map keys must correspond exactly with string field names in TSMetadata or ObsMetadata
// - if map key F is specified (where F is for example 'platform'), only observations that match
// at least one of these values for F may be returned
map<string, Strings> filter = 1;

// --- END filter for reflectable metadata of type int64 or string -------------------------
// No parameters
}

message GetExtentsResponse {
Expand Down

1 comment on commit e5e680c

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

API Unit Test Coverage Report
FileStmtsMissCoverMissing
\_\_init\_\_.py00100% 
datastore_pb2.py614821%34–81
datastore_pb2_grpc.py542750%15–16, 19, 65–80, 121–123, 128–130, 135–137, 142–144, 148–173, 219, 246, 273, 300
export_metrics.py100100% 
grpc_getter.py201145%15–19, 23–26, 30–32, 36–38
locustfile.py15150%1–31
main.py43784%45, 50, 60, 70–71, 81–82
metadata_endpoints.py653152%45–54, 58, 85, 100–219, 223
response_classes.py50100% 
utilities.py1744674%20, 38, 45, 67–70, 78–89, 94–101, 121, 125, 127, 155, 161, 179, 193–194, 198, 214–218, 222–228, 232–234, 264, 268, 290, 295
custom_geo_json
   edr_feature_collection.py60100% 
formatters
   \_\_init\_\_.py110100% 
   covjson.py59198%91
   geojson.py21290%27, 52
openapi
   custom_dimension_examples.py40100% 
   edr_query_parameter_descriptions.py110100% 
   openapi_examples.py130100% 
routers
   \_\_init\_\_.py00100% 
   edr.py101496%348–349, 438–439
   feature.py471960%99–132, 148–153, 159–181
TOTAL72021171% 

API Unit Test Coverage Summary

Tests Skipped Failures Errors Time
30 0 💤 0 ❌ 0 🔥 1.950s ⏱️

Please sign in to comment.