comparison 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
comparison
equal deleted inserted replaced
3170:5c8ecab9f2d4 3171:c8ded555c2a8
1 // This is Free Software under GNU Affero General Public License v >= 3.0
2 // without warranty, see README.md and license for details.
3 //
4 // SPDX-License-Identifier: AGPL-3.0-or-later
5 // License-Filename: LICENSES/AGPL-3.0.txt
6 //
7 // Copyright (C) 2018 by via donau
8 // – Österreichische Wasserstraßen-Gesellschaft mbH
9 // Software engineering by Intevation GmbH
10 //
11 // Author(s):
12 // * Sascha L. Teichmann <sascha.teichmann@intevation.de>
13
14 package imports
15
16 import (
17 "context"
18 "database/sql"
19 "time"
20
21 "gemma.intevation.de/gemma/pkg/models"
22 )
23
24 type Section struct {
25 Name string `json:"name"`
26 From models.Isrs `json:"from"`
27 To models.Isrs `json:"to"`
28 Tolerance float32 `json:"tolerance"`
29 ObjNam string `json:"objnam"`
30 NObjNam *string `json:"nobjnam"`
31 Source string `json:"source-organization"`
32 Date models.Date `json:"date-info"`
33 }
34
35 const SECJobKind JobKind = "sec"
36
37 type secJobCreator struct{}
38
39 func init() {
40 RegisterJobCreator(SECJobKind, secJobCreator{})
41 }
42
43 func (secJobCreator) Description() string { return "section" }
44
45 func (secJobCreator) AutoAccept() bool { return false }
46
47 func (secJobCreator) Create() Job { return new(Section) }
48
49 func (secJobCreator) Depends() []string {
50 return []string{
51 "sections",
52 }
53 }
54
55 const (
56 secDeleteSQL = `
57 DELETE FROM waterway.sections WHERE
58 staging_done AND name = (
59 SELECT name
60 FROM waterway.sections WHERE
61 id = (
62 SELECT key from import.track_imports
63 WHERE import_id = $1 AND
64 relation = 'waterway.sections'::regclass)
65 AND NOT staging_done
66 )`
67
68 secStageDoneSQL = `
69 UPDATE waterway.sections SET staging_done = true
70 WHERE id IN (
71 SELECT key from import.track_imports
72 WHERE import_id = $1 AND
73 relation = 'waterway.sections'::regclass)`
74
75 secInsertSQL = `
76 WITH r AS (
77 SELECT isrsrange(
78 least(($1::char(2),
79 $2::char(3),
80 $3::char(5),
81 $4::char(5),
82 $5::int)::isrs,
83 ($6::char(2),
84 $7::char(3),
85 $8::char(5),
86 $9::char(5),
87 $10::int)::isrs),
88 greatest(($1::char(2),
89 $2::char(3),
90 $3::char(5),
91 $4::char(5),
92 $5::int)::isrs,
93 ($6::char(2),
94 $7::char(3),
95 $8::char(5),
96 $9::char(5),
97 $10::int)::isrs)
98 ) AS r),
99 axs AS (
100 SELECT ISRSrange_axis((SELECT r FROM r), $16::double precision) AS axs)
101 INSERT INTO waterway.sections (
102 name,
103 stretch,
104 area,
105 objnam,
106 nobjnam,
107 date_info,
108 source_organization
109 ) VALUES (
110 $11,
111 (SELECT r FROM r),
112 ST_Transform(ISRSrange_area(
113 (SELECT axs FROM axs),
114 (SELECT ST_Buffer(axs, 10000) FROM axs)),
115 4326),
116 $12,
117 $13,
118 $14,
119 $15)
120 RETURNING id`
121 )
122
123 // StageDone moves the imported stretch out of the staging area.
124 func (secJobCreator) StageDone(
125 ctx context.Context,
126 tx *sql.Tx,
127 id int64,
128 ) error {
129 if _, err := tx.ExecContext(ctx, secDeleteSQL, id); err != nil {
130 return err
131 }
132 _, err := tx.ExecContext(ctx, secStageDoneSQL, id)
133 return err
134 }
135
136 // CleanUp of a stretch import is a NOP.
137 func (*Section) CleanUp() error { return nil }
138
139 // Do executes the actual stretch import.
140 func (sec *Section) Do(
141 ctx context.Context,
142 importID int64,
143 conn *sql.Conn,
144 feedback Feedback,
145 ) (interface{}, error) {
146
147 start := time.Now()
148
149 if sec.Date.Time.IsZero() {
150 sec.Date = models.Date{Time: start}
151 }
152
153 feedback.Info("Storing section '%s'", sec.Name)
154
155 tx, err := conn.BeginTx(ctx, nil)
156 if err != nil {
157 return nil, err
158 }
159 defer tx.Rollback()
160
161 var nobjnm sql.NullString
162 if sec.NObjNam != nil {
163 nobjnm = sql.NullString{String: *sec.NObjNam, Valid: true}
164 }
165
166 feedback.Info("Section from %s to %s.", sec.From.String(), sec.To.String())
167 feedback.Info("Tolerance used to snap waterway axis: %g", sec.Tolerance)
168
169 var id int64
170 if err := tx.QueryRowContext(
171 ctx,
172 secInsertSQL,
173 sec.From.CountryCode,
174 sec.From.LoCode,
175 sec.From.FairwaySection,
176 sec.From.Orc,
177 sec.From.Hectometre,
178 sec.To.CountryCode,
179 sec.To.LoCode,
180 sec.To.FairwaySection,
181 sec.To.Orc,
182 sec.To.Hectometre,
183 sec.Name,
184 sec.ObjNam,
185 nobjnm,
186 sec.Date.Time,
187 sec.Source,
188 sec.Tolerance,
189 ).Scan(&id); err != nil {
190 return nil, handleError(err)
191 }
192
193 if err := track(ctx, tx, importID, "waterway.sections", id); err != nil {
194 return nil, err
195 }
196
197 feedback.Info("Storing section '%s' took %s", sec.Name, time.Since(start))
198 if err := tx.Commit(); err != nil {
199 return nil, err
200 }
201 feedback.Info("Import of section was successful")
202
203 summary := struct {
204 Section string `json:"section"`
205 }{
206 Section: sec.Name,
207 }
208
209 return &summary, nil
210 }