feat: implement geometry CRUD operations and entity association management in SQLC and service layer
All checks were successful
Build and Release / release (push) Successful in 1m32s
All checks were successful
Build and Release / release (push) Successful in 1m32s
This commit is contained in:
@@ -20,7 +20,11 @@ UPDATE geometries
|
||||
SET
|
||||
geo_type = COALESCE(sqlc.narg('geo_type'), geo_type),
|
||||
draw_geometry = COALESCE(sqlc.narg('draw_geometry'), draw_geometry),
|
||||
bound_with = COALESCE(sqlc.narg('bound_with'), bound_with),
|
||||
bound_with = CASE
|
||||
WHEN sqlc.narg('update_bound_with')::boolean = true THEN
|
||||
sqlc.narg('bound_with')
|
||||
ELSE bound_with
|
||||
END,
|
||||
time_start = COALESCE(sqlc.narg('time_start'), time_start),
|
||||
time_end = COALESCE(sqlc.narg('time_end'), time_end),
|
||||
project_id = COALESCE(sqlc.narg('project_id'), project_id),
|
||||
|
||||
@@ -642,35 +642,40 @@ UPDATE geometries
|
||||
SET
|
||||
geo_type = COALESCE($1, geo_type),
|
||||
draw_geometry = COALESCE($2, draw_geometry),
|
||||
bound_with = COALESCE($3, bound_with),
|
||||
time_start = COALESCE($4, time_start),
|
||||
time_end = COALESCE($5, time_end),
|
||||
project_id = COALESCE($6, project_id),
|
||||
bound_with = CASE
|
||||
WHEN $3::boolean = true THEN
|
||||
$4
|
||||
ELSE bound_with
|
||||
END,
|
||||
time_start = COALESCE($5, time_start),
|
||||
time_end = COALESCE($6, time_end),
|
||||
project_id = COALESCE($7, project_id),
|
||||
bbox = CASE
|
||||
WHEN $7::boolean = true THEN
|
||||
ST_MakeEnvelope($8::float8, $9::float8, $10::float8, $11::float8, 4326)
|
||||
WHEN $8::boolean = true THEN
|
||||
ST_MakeEnvelope($9::float8, $10::float8, $11::float8, $12::float8, 4326)
|
||||
ELSE bbox
|
||||
END,
|
||||
updated_at = now()
|
||||
WHERE id = $12 AND is_deleted = false
|
||||
WHERE id = $13 AND is_deleted = false
|
||||
RETURNING id, geo_type, draw_geometry, bound_with, time_start, time_end, project_id,
|
||||
ST_XMin(bbox)::float8 as min_lng, ST_YMin(bbox)::float8 as min_lat, ST_XMax(bbox)::float8 as max_lng, ST_YMax(bbox)::float8 as max_lat,
|
||||
is_deleted, created_at, updated_at
|
||||
`
|
||||
|
||||
type UpdateGeometryParams struct {
|
||||
GeoType pgtype.Int2 `json:"geo_type"`
|
||||
DrawGeometry []byte `json:"draw_geometry"`
|
||||
BoundWith pgtype.UUID `json:"bound_with"`
|
||||
TimeStart pgtype.Int4 `json:"time_start"`
|
||||
TimeEnd pgtype.Int4 `json:"time_end"`
|
||||
ProjectID pgtype.UUID `json:"project_id"`
|
||||
UpdateBbox pgtype.Bool `json:"update_bbox"`
|
||||
MinLng pgtype.Float8 `json:"min_lng"`
|
||||
MinLat pgtype.Float8 `json:"min_lat"`
|
||||
MaxLng pgtype.Float8 `json:"max_lng"`
|
||||
MaxLat pgtype.Float8 `json:"max_lat"`
|
||||
ID pgtype.UUID `json:"id"`
|
||||
GeoType pgtype.Int2 `json:"geo_type"`
|
||||
DrawGeometry []byte `json:"draw_geometry"`
|
||||
UpdateBoundWith pgtype.Bool `json:"update_bound_with"`
|
||||
BoundWith pgtype.UUID `json:"bound_with"`
|
||||
TimeStart pgtype.Int4 `json:"time_start"`
|
||||
TimeEnd pgtype.Int4 `json:"time_end"`
|
||||
ProjectID pgtype.UUID `json:"project_id"`
|
||||
UpdateBbox pgtype.Bool `json:"update_bbox"`
|
||||
MinLng pgtype.Float8 `json:"min_lng"`
|
||||
MinLat pgtype.Float8 `json:"min_lat"`
|
||||
MaxLng pgtype.Float8 `json:"max_lng"`
|
||||
MaxLat pgtype.Float8 `json:"max_lat"`
|
||||
ID pgtype.UUID `json:"id"`
|
||||
}
|
||||
|
||||
type UpdateGeometryRow struct {
|
||||
@@ -694,6 +699,7 @@ func (q *Queries) UpdateGeometry(ctx context.Context, arg UpdateGeometryParams)
|
||||
row := q.db.QueryRow(ctx, updateGeometry,
|
||||
arg.GeoType,
|
||||
arg.DrawGeometry,
|
||||
arg.UpdateBoundWith,
|
||||
arg.BoundWith,
|
||||
arg.TimeStart,
|
||||
arg.TimeEnd,
|
||||
|
||||
@@ -705,6 +705,13 @@ func (s *submissionService) applySnapshot(ctx context.Context, tx pgx.Tx, projec
|
||||
refGeometryMap[g.ID] = true
|
||||
}
|
||||
|
||||
validGeometries := make(map[string]bool)
|
||||
for _, g := range snapshotData.Geometries {
|
||||
if g.Operation != "delete" {
|
||||
validGeometries[g.ID] = true
|
||||
}
|
||||
}
|
||||
|
||||
newGeometries := make([]*request.GeometrySnapshot, 0, len(snapshotData.Geometries))
|
||||
for i, geo := range snapshotData.Geometries {
|
||||
if geo.Operation == "delete" {
|
||||
@@ -716,15 +723,6 @@ func (s *submissionService) applySnapshot(ctx context.Context, tx pgx.Tx, projec
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Invalid geometry ID")
|
||||
}
|
||||
|
||||
var boundWith pgtype.UUID
|
||||
if geo.BoundWith != nil && *geo.BoundWith != "" {
|
||||
var err error
|
||||
boundWith, err = convert.StringToUUID(*geo.BoundWith)
|
||||
if err != nil {
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid bound_with geometry ID")
|
||||
}
|
||||
}
|
||||
|
||||
geoTypeCode := int16(0)
|
||||
if geo.Type != "" {
|
||||
if n, err := strconv.ParseInt(geo.Type, 10, 16); err == nil {
|
||||
@@ -734,13 +732,13 @@ func (s *submissionService) applySnapshot(ctx context.Context, tx pgx.Tx, projec
|
||||
|
||||
if _, ok := persistCurrentItemIDs[geo.ID]; ok {
|
||||
params := sqlc.UpdateGeometryParams{
|
||||
ID: geometryUUID,
|
||||
GeoType: pgtype.Int2{Int16: geoTypeCode, Valid: true},
|
||||
DrawGeometry: geo.DrawGeometry,
|
||||
BoundWith: boundWith,
|
||||
TimeStart: convert.PtrFloat64ToInt4(geo.TimeStart),
|
||||
TimeEnd: convert.PtrFloat64ToInt4(geo.TimeEnd),
|
||||
ProjectID: projectUUID,
|
||||
ID: geometryUUID,
|
||||
GeoType: pgtype.Int2{Int16: geoTypeCode, Valid: true},
|
||||
DrawGeometry: geo.DrawGeometry,
|
||||
UpdateBoundWith: pgtype.Bool{Bool: false, Valid: true},
|
||||
TimeStart: convert.PtrFloat64ToInt4(geo.TimeStart),
|
||||
TimeEnd: convert.PtrFloat64ToInt4(geo.TimeEnd),
|
||||
ProjectID: projectUUID,
|
||||
}
|
||||
|
||||
if geo.BBox != nil {
|
||||
@@ -762,7 +760,7 @@ func (s *submissionService) applySnapshot(ctx context.Context, tx pgx.Tx, projec
|
||||
ID: geometryUUID,
|
||||
GeoType: geoTypeCode,
|
||||
DrawGeometry: geo.DrawGeometry,
|
||||
BoundWith: boundWith,
|
||||
BoundWith: pgtype.UUID{Valid: false},
|
||||
TimeStart: convert.PtrFloat64ToInt4(geo.TimeStart),
|
||||
TimeEnd: convert.PtrFloat64ToInt4(geo.TimeEnd),
|
||||
ProjectID: projectUUID,
|
||||
@@ -789,6 +787,41 @@ func (s *submissionService) applySnapshot(ctx context.Context, tx pgx.Tx, projec
|
||||
}
|
||||
snapshotData.Geometries = newGeometries
|
||||
|
||||
for _, geo := range snapshotData.Geometries {
|
||||
if geo.Operation == "delete" || geo.Source == "ref" {
|
||||
continue
|
||||
}
|
||||
|
||||
geometryUUID, err := convert.StringToUUID(geo.ID)
|
||||
if err != nil {
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Invalid geometry ID")
|
||||
}
|
||||
|
||||
var boundWith pgtype.UUID
|
||||
if geo.BoundWith != nil && *geo.BoundWith != "" {
|
||||
if !validGeometries[*geo.BoundWith] {
|
||||
return fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Geometry %s references a non-existent or deleted geometry %s as bound_with", geo.ID, *geo.BoundWith))
|
||||
}
|
||||
if *geo.BoundWith == geo.ID {
|
||||
return fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Geometry %s cannot be bound to itself", geo.ID))
|
||||
}
|
||||
|
||||
boundWith, err = convert.StringToUUID(*geo.BoundWith)
|
||||
if err != nil {
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid bound_with geometry ID")
|
||||
}
|
||||
}
|
||||
params := sqlc.UpdateGeometryParams{
|
||||
ID: geometryUUID,
|
||||
UpdateBoundWith: pgtype.Bool{Bool: true, Valid: true},
|
||||
BoundWith: boundWith,
|
||||
}
|
||||
_, err = geometryRepo.Update(ctx, params)
|
||||
if err != nil {
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to update geometry bound_with: "+err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
refWikiIDs := []string{}
|
||||
for _, w := range snapshotData.Wikis {
|
||||
if w.Source == "ref" {
|
||||
@@ -928,10 +961,6 @@ func (s *submissionService) applySnapshot(ctx context.Context, tx pgx.Tx, projec
|
||||
for _, e := range snapshotData.Entities {
|
||||
validEntities[e.ID] = true
|
||||
}
|
||||
validGeometries := make(map[string]bool)
|
||||
for _, g := range snapshotData.Geometries {
|
||||
validGeometries[g.ID] = true
|
||||
}
|
||||
validWikis := make(map[string]bool)
|
||||
for _, w := range snapshotData.Wikis {
|
||||
validWikis[w.ID] = true
|
||||
|
||||
Reference in New Issue
Block a user