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
|
SET
|
||||||
geo_type = COALESCE(sqlc.narg('geo_type'), geo_type),
|
geo_type = COALESCE(sqlc.narg('geo_type'), geo_type),
|
||||||
draw_geometry = COALESCE(sqlc.narg('draw_geometry'), draw_geometry),
|
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_start = COALESCE(sqlc.narg('time_start'), time_start),
|
||||||
time_end = COALESCE(sqlc.narg('time_end'), time_end),
|
time_end = COALESCE(sqlc.narg('time_end'), time_end),
|
||||||
project_id = COALESCE(sqlc.narg('project_id'), project_id),
|
project_id = COALESCE(sqlc.narg('project_id'), project_id),
|
||||||
|
|||||||
@@ -642,35 +642,40 @@ UPDATE geometries
|
|||||||
SET
|
SET
|
||||||
geo_type = COALESCE($1, geo_type),
|
geo_type = COALESCE($1, geo_type),
|
||||||
draw_geometry = COALESCE($2, draw_geometry),
|
draw_geometry = COALESCE($2, draw_geometry),
|
||||||
bound_with = COALESCE($3, bound_with),
|
bound_with = CASE
|
||||||
time_start = COALESCE($4, time_start),
|
WHEN $3::boolean = true THEN
|
||||||
time_end = COALESCE($5, time_end),
|
$4
|
||||||
project_id = COALESCE($6, project_id),
|
ELSE bound_with
|
||||||
|
END,
|
||||||
|
time_start = COALESCE($5, time_start),
|
||||||
|
time_end = COALESCE($6, time_end),
|
||||||
|
project_id = COALESCE($7, project_id),
|
||||||
bbox = CASE
|
bbox = CASE
|
||||||
WHEN $7::boolean = true THEN
|
WHEN $8::boolean = true THEN
|
||||||
ST_MakeEnvelope($8::float8, $9::float8, $10::float8, $11::float8, 4326)
|
ST_MakeEnvelope($9::float8, $10::float8, $11::float8, $12::float8, 4326)
|
||||||
ELSE bbox
|
ELSE bbox
|
||||||
END,
|
END,
|
||||||
updated_at = now()
|
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,
|
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,
|
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
|
is_deleted, created_at, updated_at
|
||||||
`
|
`
|
||||||
|
|
||||||
type UpdateGeometryParams struct {
|
type UpdateGeometryParams struct {
|
||||||
GeoType pgtype.Int2 `json:"geo_type"`
|
GeoType pgtype.Int2 `json:"geo_type"`
|
||||||
DrawGeometry []byte `json:"draw_geometry"`
|
DrawGeometry []byte `json:"draw_geometry"`
|
||||||
BoundWith pgtype.UUID `json:"bound_with"`
|
UpdateBoundWith pgtype.Bool `json:"update_bound_with"`
|
||||||
TimeStart pgtype.Int4 `json:"time_start"`
|
BoundWith pgtype.UUID `json:"bound_with"`
|
||||||
TimeEnd pgtype.Int4 `json:"time_end"`
|
TimeStart pgtype.Int4 `json:"time_start"`
|
||||||
ProjectID pgtype.UUID `json:"project_id"`
|
TimeEnd pgtype.Int4 `json:"time_end"`
|
||||||
UpdateBbox pgtype.Bool `json:"update_bbox"`
|
ProjectID pgtype.UUID `json:"project_id"`
|
||||||
MinLng pgtype.Float8 `json:"min_lng"`
|
UpdateBbox pgtype.Bool `json:"update_bbox"`
|
||||||
MinLat pgtype.Float8 `json:"min_lat"`
|
MinLng pgtype.Float8 `json:"min_lng"`
|
||||||
MaxLng pgtype.Float8 `json:"max_lng"`
|
MinLat pgtype.Float8 `json:"min_lat"`
|
||||||
MaxLat pgtype.Float8 `json:"max_lat"`
|
MaxLng pgtype.Float8 `json:"max_lng"`
|
||||||
ID pgtype.UUID `json:"id"`
|
MaxLat pgtype.Float8 `json:"max_lat"`
|
||||||
|
ID pgtype.UUID `json:"id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type UpdateGeometryRow struct {
|
type UpdateGeometryRow struct {
|
||||||
@@ -694,6 +699,7 @@ func (q *Queries) UpdateGeometry(ctx context.Context, arg UpdateGeometryParams)
|
|||||||
row := q.db.QueryRow(ctx, updateGeometry,
|
row := q.db.QueryRow(ctx, updateGeometry,
|
||||||
arg.GeoType,
|
arg.GeoType,
|
||||||
arg.DrawGeometry,
|
arg.DrawGeometry,
|
||||||
|
arg.UpdateBoundWith,
|
||||||
arg.BoundWith,
|
arg.BoundWith,
|
||||||
arg.TimeStart,
|
arg.TimeStart,
|
||||||
arg.TimeEnd,
|
arg.TimeEnd,
|
||||||
|
|||||||
@@ -705,6 +705,13 @@ func (s *submissionService) applySnapshot(ctx context.Context, tx pgx.Tx, projec
|
|||||||
refGeometryMap[g.ID] = true
|
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))
|
newGeometries := make([]*request.GeometrySnapshot, 0, len(snapshotData.Geometries))
|
||||||
for i, geo := range snapshotData.Geometries {
|
for i, geo := range snapshotData.Geometries {
|
||||||
if geo.Operation == "delete" {
|
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")
|
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)
|
geoTypeCode := int16(0)
|
||||||
if geo.Type != "" {
|
if geo.Type != "" {
|
||||||
if n, err := strconv.ParseInt(geo.Type, 10, 16); err == nil {
|
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 {
|
if _, ok := persistCurrentItemIDs[geo.ID]; ok {
|
||||||
params := sqlc.UpdateGeometryParams{
|
params := sqlc.UpdateGeometryParams{
|
||||||
ID: geometryUUID,
|
ID: geometryUUID,
|
||||||
GeoType: pgtype.Int2{Int16: geoTypeCode, Valid: true},
|
GeoType: pgtype.Int2{Int16: geoTypeCode, Valid: true},
|
||||||
DrawGeometry: geo.DrawGeometry,
|
DrawGeometry: geo.DrawGeometry,
|
||||||
BoundWith: boundWith,
|
UpdateBoundWith: pgtype.Bool{Bool: false, Valid: true},
|
||||||
TimeStart: convert.PtrFloat64ToInt4(geo.TimeStart),
|
TimeStart: convert.PtrFloat64ToInt4(geo.TimeStart),
|
||||||
TimeEnd: convert.PtrFloat64ToInt4(geo.TimeEnd),
|
TimeEnd: convert.PtrFloat64ToInt4(geo.TimeEnd),
|
||||||
ProjectID: projectUUID,
|
ProjectID: projectUUID,
|
||||||
}
|
}
|
||||||
|
|
||||||
if geo.BBox != nil {
|
if geo.BBox != nil {
|
||||||
@@ -762,7 +760,7 @@ func (s *submissionService) applySnapshot(ctx context.Context, tx pgx.Tx, projec
|
|||||||
ID: geometryUUID,
|
ID: geometryUUID,
|
||||||
GeoType: geoTypeCode,
|
GeoType: geoTypeCode,
|
||||||
DrawGeometry: geo.DrawGeometry,
|
DrawGeometry: geo.DrawGeometry,
|
||||||
BoundWith: boundWith,
|
BoundWith: pgtype.UUID{Valid: false},
|
||||||
TimeStart: convert.PtrFloat64ToInt4(geo.TimeStart),
|
TimeStart: convert.PtrFloat64ToInt4(geo.TimeStart),
|
||||||
TimeEnd: convert.PtrFloat64ToInt4(geo.TimeEnd),
|
TimeEnd: convert.PtrFloat64ToInt4(geo.TimeEnd),
|
||||||
ProjectID: projectUUID,
|
ProjectID: projectUUID,
|
||||||
@@ -789,6 +787,41 @@ func (s *submissionService) applySnapshot(ctx context.Context, tx pgx.Tx, projec
|
|||||||
}
|
}
|
||||||
snapshotData.Geometries = newGeometries
|
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{}
|
refWikiIDs := []string{}
|
||||||
for _, w := range snapshotData.Wikis {
|
for _, w := range snapshotData.Wikis {
|
||||||
if w.Source == "ref" {
|
if w.Source == "ref" {
|
||||||
@@ -928,10 +961,6 @@ func (s *submissionService) applySnapshot(ctx context.Context, tx pgx.Tx, projec
|
|||||||
for _, e := range snapshotData.Entities {
|
for _, e := range snapshotData.Entities {
|
||||||
validEntities[e.ID] = true
|
validEntities[e.ID] = true
|
||||||
}
|
}
|
||||||
validGeometries := make(map[string]bool)
|
|
||||||
for _, g := range snapshotData.Geometries {
|
|
||||||
validGeometries[g.ID] = true
|
|
||||||
}
|
|
||||||
validWikis := make(map[string]bool)
|
validWikis := make(map[string]bool)
|
||||||
for _, w := range snapshotData.Wikis {
|
for _, w := range snapshotData.Wikis {
|
||||||
validWikis[w.ID] = true
|
validWikis[w.ID] = true
|
||||||
|
|||||||
Reference in New Issue
Block a user