diff pkg/imports/sec.go @ 3171:c8ded555c2a8

Sections import: Added a sections import. Derived from the stretches import w/o the countries.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Mon, 06 May 2019 16:36:03 +0200
parents
children 4acbee65275d
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pkg/imports/sec.go	Mon May 06 16:36:03 2019 +0200
@@ -0,0 +1,210 @@
+// This is Free Software under GNU Affero General Public License v >= 3.0
+// without warranty, see README.md and license for details.
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+// License-Filename: LICENSES/AGPL-3.0.txt
+//
+// Copyright (C) 2018 by via donau
+//   – Österreichische Wasserstraßen-Gesellschaft mbH
+// Software engineering by Intevation GmbH
+//
+// Author(s):
+//  * Sascha L. Teichmann <sascha.teichmann@intevation.de>
+
+package imports
+
+import (
+	"context"
+	"database/sql"
+	"time"
+
+	"gemma.intevation.de/gemma/pkg/models"
+)
+
+type Section struct {
+	Name      string      `json:"name"`
+	From      models.Isrs `json:"from"`
+	To        models.Isrs `json:"to"`
+	Tolerance float32     `json:"tolerance"`
+	ObjNam    string      `json:"objnam"`
+	NObjNam   *string     `json:"nobjnam"`
+	Source    string      `json:"source-organization"`
+	Date      models.Date `json:"date-info"`
+}
+
+const SECJobKind JobKind = "sec"
+
+type secJobCreator struct{}
+
+func init() {
+	RegisterJobCreator(SECJobKind, secJobCreator{})
+}
+
+func (secJobCreator) Description() string { return "section" }
+
+func (secJobCreator) AutoAccept() bool { return false }
+
+func (secJobCreator) Create() Job { return new(Section) }
+
+func (secJobCreator) Depends() []string {
+	return []string{
+		"sections",
+	}
+}
+
+const (
+	secDeleteSQL = `
+DELETE FROM waterway.sections WHERE
+staging_done AND name = (
+  SELECT name
+  FROM waterway.sections WHERE
+  id = (
+    SELECT key from import.track_imports
+    WHERE import_id = $1 AND
+      relation = 'waterway.sections'::regclass)
+  AND NOT staging_done
+)`
+
+	secStageDoneSQL = `
+UPDATE waterway.sections SET staging_done = true
+WHERE id IN (
+  SELECT key from import.track_imports
+  WHERE import_id = $1 AND
+        relation = 'waterway.sections'::regclass)`
+
+	secInsertSQL = `
+WITH r AS (
+  SELECT isrsrange(
+    least(($1::char(2),
+           $2::char(3),
+           $3::char(5),
+           $4::char(5),
+           $5::int)::isrs,
+          ($6::char(2),
+           $7::char(3),
+           $8::char(5),
+           $9::char(5),
+           $10::int)::isrs),
+    greatest(($1::char(2),
+              $2::char(3),
+              $3::char(5),
+              $4::char(5),
+              $5::int)::isrs,
+             ($6::char(2),
+              $7::char(3),
+              $8::char(5),
+              $9::char(5),
+              $10::int)::isrs)
+    ) AS r),
+axs AS (
+  SELECT ISRSrange_axis((SELECT r FROM r), $16::double precision) AS axs)
+INSERT INTO waterway.sections (
+  name,
+  stretch,
+  area,
+  objnam,
+  nobjnam,
+  date_info,
+  source_organization
+) VALUES (
+  $11,
+  (SELECT r FROM r),
+  ST_Transform(ISRSrange_area(
+      (SELECT axs FROM axs),
+      (SELECT ST_Buffer(axs, 10000) FROM axs)),
+    4326),
+  $12,
+  $13,
+  $14,
+  $15)
+RETURNING id`
+)
+
+// StageDone moves the imported stretch out of the staging area.
+func (secJobCreator) StageDone(
+	ctx context.Context,
+	tx *sql.Tx,
+	id int64,
+) error {
+	if _, err := tx.ExecContext(ctx, secDeleteSQL, id); err != nil {
+		return err
+	}
+	_, err := tx.ExecContext(ctx, secStageDoneSQL, id)
+	return err
+}
+
+// CleanUp of a stretch import is a NOP.
+func (*Section) CleanUp() error { return nil }
+
+// Do executes the actual stretch import.
+func (sec *Section) Do(
+	ctx context.Context,
+	importID int64,
+	conn *sql.Conn,
+	feedback Feedback,
+) (interface{}, error) {
+
+	start := time.Now()
+
+	if sec.Date.Time.IsZero() {
+		sec.Date = models.Date{Time: start}
+	}
+
+	feedback.Info("Storing section '%s'", sec.Name)
+
+	tx, err := conn.BeginTx(ctx, nil)
+	if err != nil {
+		return nil, err
+	}
+	defer tx.Rollback()
+
+	var nobjnm sql.NullString
+	if sec.NObjNam != nil {
+		nobjnm = sql.NullString{String: *sec.NObjNam, Valid: true}
+	}
+
+	feedback.Info("Section from %s to %s.", sec.From.String(), sec.To.String())
+	feedback.Info("Tolerance used to snap waterway axis: %g", sec.Tolerance)
+
+	var id int64
+	if err := tx.QueryRowContext(
+		ctx,
+		secInsertSQL,
+		sec.From.CountryCode,
+		sec.From.LoCode,
+		sec.From.FairwaySection,
+		sec.From.Orc,
+		sec.From.Hectometre,
+		sec.To.CountryCode,
+		sec.To.LoCode,
+		sec.To.FairwaySection,
+		sec.To.Orc,
+		sec.To.Hectometre,
+		sec.Name,
+		sec.ObjNam,
+		nobjnm,
+		sec.Date.Time,
+		sec.Source,
+		sec.Tolerance,
+	).Scan(&id); err != nil {
+		return nil, handleError(err)
+	}
+
+	if err := track(ctx, tx, importID, "waterway.sections", id); err != nil {
+		return nil, err
+	}
+
+	feedback.Info("Storing section '%s' took %s", sec.Name, time.Since(start))
+	if err := tx.Commit(); err != nil {
+		return nil, err
+	}
+	feedback.Info("Import of section was successful")
+
+	summary := struct {
+		Section string `json:"section"`
+	}{
+		Section: sec.Name,
+	}
+
+	return &summary, nil
+}