# HG changeset patch # User Thomas Junk # Date 1582013427 -3600 # Node ID 4c57d80ad7a7bd545c0a43ee6f4e3d0327ae8008 # Parent c4d84be3a476e29c1281d4349bf60bbe0f05af94# Parent df6c8a48597996a63097479b3c99b8b492970e1c merge diff -r c4d84be3a476 -r 4c57d80ad7a7 pkg/controllers/routes.go --- a/pkg/controllers/routes.go Tue Feb 18 09:10:05 2020 +0100 +++ b/pkg/controllers/routes.go Tue Feb 18 09:10:27 2020 +0100 @@ -246,6 +246,13 @@ "fm_bcnlat", "fm_boycar", "fm_boylat", + "fm_boysaw", + "fm_boyspp", + "fm_daymar", + "fm_lights", + "fm_rtpbcn", + "fm_topmar", + "fm_notmrk", }, "|") api.Handle("/imports/{kind:"+kinds+"}", waterwayAdmin(&mw.JSONHandler{ diff -r c4d84be3a476 -r 4c57d80ad7a7 pkg/imports/fm.go --- a/pkg/imports/fm.go Tue Feb 18 09:10:05 2020 +0100 +++ b/pkg/imports/fm.go Tue Feb 18 09:10:27 2020 +0100 @@ -101,7 +101,7 @@ ) // Create INSERT statement for specific fairway marks type -func getFMInsertSQL(fmType string, attributes []string) string { +func getFMInsertSQL(fmType string, attributes ...string) string { attNums := "$16" for i := 1; i < len(attributes); i++ { attNums += fmt.Sprintf(",$%d", 16+i) diff -r c4d84be3a476 -r 4c57d80ad7a7 pkg/imports/fm_bcnlat.go --- a/pkg/imports/fm_bcnlat.go Tue Feb 18 09:10:05 2020 +0100 +++ b/pkg/imports/fm_bcnlat.go Tue Feb 18 09:10:27 2020 +0100 @@ -80,7 +80,7 @@ } const ( - insertDirimpSQL = ` + insertBcnlatDirimpSQL = ` INSERT INTO waterway.fairway_marks_bcnlat_dirimps (fm_bcnlat_id, dirimp) VALUES ($1, $2) ` @@ -111,19 +111,20 @@ insertStmt, err := tx.PrepareContext( ctx, - getFMInsertSQL("bcnlat", []string{ - "colour", "colpat", "condtn", "bcnshp", "catlam"}), + getFMInsertSQL("bcnlat", + "colour", "colpat", "condtn", "bcnshp", "catlam"), ) if err != nil { return } defer insertStmt.Close() - insertDirimpStmt, err := tx.PrepareContext(ctx, insertDirimpSQL) + insertBcnlatDirimpStmt, err := tx.PrepareContext( + ctx, insertBcnlatDirimpSQL) if err != nil { return } - defer insertDirimpStmt.Close() + defer insertBcnlatDirimpStmt.Close() savepoint := Savepoint(ctx, tx, "feature") @@ -181,12 +182,15 @@ dirimps := strings.Split(*f.props.Dirimp, ",") for _, dirimp := range dirimps { if err := savepoint(func() error { - _, err := insertDirimpStmt.ExecContext( + _, err := insertBcnlatDirimpStmt.ExecContext( ctx, fmid, dirimp) return err }); err != nil { feedback.Warn( pgxutils.ReadableError{Err: err}.Error()) + feedback.Info( + "Tried to import '%s' as dirimp value", + dirimp) } } } diff -r c4d84be3a476 -r 4c57d80ad7a7 pkg/imports/fm_boycar.go --- a/pkg/imports/fm_boycar.go Tue Feb 18 09:10:05 2020 +0100 +++ b/pkg/imports/fm_boycar.go Tue Feb 18 09:10:27 2020 +0100 @@ -102,9 +102,9 @@ insertStmt, err := tx.PrepareContext( ctx, - getFMInsertSQL("boycar", []string{ + getFMInsertSQL("boycar", "colour", "colpat", "conrad", - "marsys", "boyshp", "catcam"}), + "marsys", "boyshp", "catcam"), ) if err != nil { return diff -r c4d84be3a476 -r 4c57d80ad7a7 pkg/imports/fm_boylat.go --- a/pkg/imports/fm_boylat.go Tue Feb 18 09:10:05 2020 +0100 +++ b/pkg/imports/fm_boylat.go Tue Feb 18 09:10:27 2020 +0100 @@ -104,9 +104,9 @@ insertStmt, err := tx.PrepareContext( ctx, - getFMInsertSQL("boylat", []string{ + getFMInsertSQL("boylat", "colour", "colpat", "conrad", - "marsys", "boyshp", "catlam"}), + "marsys", "boyshp", "catlam"), ) if err != nil { return diff -r c4d84be3a476 -r 4c57d80ad7a7 pkg/imports/fm_boysaw.go --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pkg/imports/fm_boysaw.go Tue Feb 18 09:10:27 2020 +0100 @@ -0,0 +1,159 @@ +// 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) 2020 by via donau +// – Österreichische Wasserstraßen-Gesellschaft mbH +// Software engineering by Intevation GmbH +// +// Author(s): +// * Tom Gottfried + +package imports + +import ( + "context" + "database/sql" + + "gemma.intevation.de/gemma/pkg/pgxutils" +) + +// Boysaw is an import job to import +// fairway marks of type BOYSAW in form of point geometries +// and attribute data from a WFS service. +type Boysaw struct { + FairwayMarks +} + +// Description gives a short info about relevant facts of this import. +func (boysaw *Boysaw) Description() (string, error) { + return boysaw.URL + "|" + boysaw.FeatureType, nil +} + +// BOYSAWJobKind is the import queue type identifier. +const BOYSAWJobKind JobKind = "fm_boysaw" + +type boysawJobCreator struct{} + +func init() { + RegisterJobCreator(BOYSAWJobKind, boysawJobCreator{}) +} + +func (boysawJobCreator) Description() string { return "fairway marks boysaw" } + +func (boysawJobCreator) AutoAccept() bool { return true } + +func (boysawJobCreator) Create() Job { return new(Boysaw) } + +func (boysawJobCreator) Depends() [2][]string { + return [2][]string{ + {"fairway_marks_boysaw"}, + {}, + } +} + +// StageDone is a NOP for fairway marks imports. +func (boysawJobCreator) StageDone(context.Context, *sql.Tx, int64) error { + return nil +} + +// CleanUp for fairway marks imports is a NOP. +func (*Boysaw) CleanUp() error { return nil } + +type boysawProperties struct { + fairwayMarksProperties + Colour *string `json:"hydro_colour"` + Colpat *string `json:"hydro_colpat"` + Conrad *int `json:"hydro_conrad"` + Marsys *int64 `json:"hydro_marsys"` + Boyshp *int `json:"hydro_boyshp"` +} + +type boysawFeaturetype struct { + geom pointSlice + props *boysawProperties +} + +// Do executes the actual import. +func (fm *Boysaw) Do( + ctx context.Context, + importID int64, + conn *sql.Conn, + feedback Feedback, +) (interface{}, error) { + + err := getFMFeatures( + ctx, + conn, + feedback, + fm.FairwayMarks, + func() interface{} { return new(boysawProperties) }, + func(p pointSlice, props interface{}) interface{} { + return &boysawFeaturetype{p, props.(*boysawProperties)} + }, + func( + tx *sql.Tx, epsg int, fms []interface{}, + ) (outsideOrDup int, features int, err error) { + + feedback.Info("Store fairway marks of type BOYSAW") + + insertStmt, err := tx.PrepareContext( + ctx, + getFMInsertSQL("boysaw", + "colour", "colpat", "conrad", "marsys", "boyshp"), + ) + if err != nil { + return + } + defer insertStmt.Close() + + savepoint := Savepoint(ctx, tx, "feature") + + for _, fm := range fms { + + f := fm.(*boysawFeaturetype) + + var fmid int64 + err := savepoint(func() error { + err := insertStmt.QueryRowContext( + ctx, + f.geom.asWKB(), + epsg, + f.props.Datsta, + f.props.Datend, + f.props.Persta, + f.props.Perend, + f.props.Objnam, + f.props.Nobjnm, + f.props.Inform, + f.props.Ninfom, + f.props.Scamin, + f.props.Picrep, + f.props.Txtdsc, + f.props.Sordat, + f.props.Sorind, + f.props.Colour, + f.props.Colpat, + f.props.Conrad, + f.props.Marsys, + f.props.Boyshp, + ).Scan(&fmid) + return err + }) + switch { + case err == sql.ErrNoRows: + outsideOrDup++ + // ignore -> filtered by responsibility_areas + case err != nil: + feedback.Error(pgxutils.ReadableError{Err: err}.Error()) + default: + features++ + } + } + return + }) + + return nil, err +} diff -r c4d84be3a476 -r 4c57d80ad7a7 pkg/imports/fm_boyspp.go --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pkg/imports/fm_boyspp.go Tue Feb 18 09:10:27 2020 +0100 @@ -0,0 +1,162 @@ +// 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) 2020 by via donau +// – Österreichische Wasserstraßen-Gesellschaft mbH +// Software engineering by Intevation GmbH +// +// Author(s): +// * Tom Gottfried + +package imports + +import ( + "context" + "database/sql" + + "gemma.intevation.de/gemma/pkg/pgxutils" +) + +// Boyspp is an import job to import +// fairway marks of type BOYSPP in form of point geometries +// and attribute data from a WFS service. +type Boyspp struct { + FairwayMarks +} + +// Description gives a short info about relevant facts of this import. +func (boyspp *Boyspp) Description() (string, error) { + return boyspp.URL + "|" + boyspp.FeatureType, nil +} + +// BOYSPPJobKind is the import queue type identifier. +const BOYSPPJobKind JobKind = "fm_boyspp" + +type boysppJobCreator struct{} + +func init() { + RegisterJobCreator(BOYSPPJobKind, boysppJobCreator{}) +} + +func (boysppJobCreator) Description() string { return "fairway marks boyspp" } + +func (boysppJobCreator) AutoAccept() bool { return true } + +func (boysppJobCreator) Create() Job { return new(Boyspp) } + +func (boysppJobCreator) Depends() [2][]string { + return [2][]string{ + {"fairway_marks_boyspp"}, + {}, + } +} + +// StageDone is a NOP for fairway marks imports. +func (boysppJobCreator) StageDone(context.Context, *sql.Tx, int64) error { + return nil +} + +// CleanUp for fairway marks imports is a NOP. +func (*Boyspp) CleanUp() error { return nil } + +type boysppProperties struct { + fairwayMarksProperties + Colour *string `json:"hydro_colour"` + Colpat *string `json:"hydro_colpat"` + Conrad *int `json:"hydro_conrad"` + Marsys *int64 `json:"hydro_marsys"` + Boyshp *int `json:"hydro_boyshp"` + Catspm *string `json:"hydro_catspm"` +} + +type boysppFeaturetype struct { + geom pointSlice + props *boysppProperties +} + +// Do executes the actual import. +func (fm *Boyspp) Do( + ctx context.Context, + importID int64, + conn *sql.Conn, + feedback Feedback, +) (interface{}, error) { + + err := getFMFeatures( + ctx, + conn, + feedback, + fm.FairwayMarks, + func() interface{} { return new(boysppProperties) }, + func(p pointSlice, props interface{}) interface{} { + return &boysppFeaturetype{p, props.(*boysppProperties)} + }, + func( + tx *sql.Tx, epsg int, fms []interface{}, + ) (outsideOrDup int, features int, err error) { + + feedback.Info("Store fairway marks of type BOYSPP") + + insertStmt, err := tx.PrepareContext( + ctx, + getFMInsertSQL("boyspp", + "colour", "colpat", "conrad", + "marsys", "boyshp", "catspm"), + ) + if err != nil { + return + } + defer insertStmt.Close() + + savepoint := Savepoint(ctx, tx, "feature") + + for _, fm := range fms { + + f := fm.(*boysppFeaturetype) + + var fmid int64 + err := savepoint(func() error { + err := insertStmt.QueryRowContext( + ctx, + f.geom.asWKB(), + epsg, + f.props.Datsta, + f.props.Datend, + f.props.Persta, + f.props.Perend, + f.props.Objnam, + f.props.Nobjnm, + f.props.Inform, + f.props.Ninfom, + f.props.Scamin, + f.props.Picrep, + f.props.Txtdsc, + f.props.Sordat, + f.props.Sorind, + f.props.Colour, + f.props.Colpat, + f.props.Conrad, + f.props.Marsys, + f.props.Boyshp, + f.props.Catspm, + ).Scan(&fmid) + return err + }) + switch { + case err == sql.ErrNoRows: + outsideOrDup++ + // ignore -> filtered by responsibility_areas + case err != nil: + feedback.Error(pgxutils.ReadableError{Err: err}.Error()) + default: + features++ + } + } + return + }) + + return nil, err +} diff -r c4d84be3a476 -r 4c57d80ad7a7 pkg/imports/fm_daymar.go --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pkg/imports/fm_daymar.go Tue Feb 18 09:10:27 2020 +0100 @@ -0,0 +1,193 @@ +// 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) 2020 by via donau +// – Österreichische Wasserstraßen-Gesellschaft mbH +// Software engineering by Intevation GmbH +// +// Author(s): +// * Tom Gottfried + +package imports + +import ( + "context" + "database/sql" + "strings" + + "gemma.intevation.de/gemma/pkg/pgxutils" +) + +// Daymar is an import job to import +// fairway marks of type DAYMAR in form of point geometries +// and attribute data from a WFS service. +type Daymar struct { + FairwayMarks +} + +// Description gives a short info about relevant facts of this import. +func (daymar *Daymar) Description() (string, error) { + return daymar.URL + "|" + daymar.FeatureType, nil +} + +// DAYMARJobKind is the import queue type identifier. +const DAYMARJobKind JobKind = "fm_daymar" + +type daymarJobCreator struct{} + +func init() { + RegisterJobCreator(DAYMARJobKind, daymarJobCreator{}) +} + +func (daymarJobCreator) Description() string { return "fairway marks daymar" } + +func (daymarJobCreator) AutoAccept() bool { return true } + +func (daymarJobCreator) Create() Job { return new(Daymar) } + +func (daymarJobCreator) Depends() [2][]string { + return [2][]string{ + {"fairway_marks_daymar"}, + {}, + } +} + +// StageDone is a NOP for fairway marks imports. +func (daymarJobCreator) StageDone(context.Context, *sql.Tx, int64) error { + return nil +} + +// CleanUp for fairway marks imports is a NOP. +func (*Daymar) CleanUp() error { return nil } + +type daymarProperties struct { + fairwayMarksProperties + Colour *string `json:"hydro_colour"` + Colpat *string `json:"hydro_colpat"` + Condtn *int `json:"hydro_condtn"` + Dirimp *string `json:"ienc_dirimp,omitempty"` + Topshp *int `json:"hydro_topshp"` + Orient *float64 `json:"hydro_orient,omitempty"` +} + +type daymarFeaturetype struct { + geom pointSlice + props *daymarProperties +} + +const ( + insertDaymarDirimpSQL = ` +INSERT INTO waterway.fairway_marks_daymar_dirimps (fm_daymar_id, dirimp) + VALUES ($1, $2) +` +) + +// Do executes the actual import. +func (fm *Daymar) Do( + ctx context.Context, + importID int64, + conn *sql.Conn, + feedback Feedback, +) (interface{}, error) { + + err := getFMFeatures( + ctx, + conn, + feedback, + fm.FairwayMarks, + func() interface{} { return new(daymarProperties) }, + func(p pointSlice, props interface{}) interface{} { + return &daymarFeaturetype{p, props.(*daymarProperties)} + }, + func( + tx *sql.Tx, epsg int, fms []interface{}, + ) (outsideOrDup int, features int, err error) { + + feedback.Info("Store fairway marks of type DAYMAR/daymar") + + insertStmt, err := tx.PrepareContext( + ctx, + getFMInsertSQL("daymar", + "colour", "colpat", "condtn", "topshp", "orient"), + ) + if err != nil { + return + } + defer insertStmt.Close() + + insertDaymarDirimpStmt, err := tx.PrepareContext( + ctx, insertDaymarDirimpSQL) + if err != nil { + return + } + defer insertDaymarDirimpStmt.Close() + + savepoint := Savepoint(ctx, tx, "feature") + + for _, fm := range fms { + + f := fm.(*daymarFeaturetype) + + var fmid int64 + err := savepoint(func() error { + err := insertStmt.QueryRowContext( + ctx, + f.geom.asWKB(), + epsg, + f.props.Datsta, + f.props.Datend, + f.props.Persta, + f.props.Perend, + f.props.Objnam, + f.props.Nobjnm, + f.props.Inform, + f.props.Ninfom, + f.props.Scamin, + f.props.Picrep, + f.props.Txtdsc, + f.props.Sordat, + f.props.Sorind, + f.props.Colour, + f.props.Colpat, + f.props.Condtn, + f.props.Topshp, + f.props.Orient, + ).Scan(&fmid) + return err + }) + switch { + case err == sql.ErrNoRows: + outsideOrDup++ + // ignore -> filtered by responsibility area or a duplicate + // TODO: handle eventual changes to dirimp + case err != nil: + feedback.Error(pgxutils.ReadableError{Err: err}.Error()) + default: + features++ + + if f.props.Dirimp != nil && *f.props.Dirimp != "" { + dirimps := strings.Split(*f.props.Dirimp, ",") + for _, dirimp := range dirimps { + if err := savepoint(func() error { + _, err := insertDaymarDirimpStmt.ExecContext( + ctx, fmid, dirimp) + return err + }); err != nil { + feedback.Warn( + pgxutils.ReadableError{Err: err}.Error()) + feedback.Info( + "Tried to import '%s' as dirimp value", + dirimp) + } + } + } + } + } + return + }) + + return nil, err +} diff -r c4d84be3a476 -r 4c57d80ad7a7 pkg/imports/fm_lights.go --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pkg/imports/fm_lights.go Tue Feb 18 09:10:27 2020 +0100 @@ -0,0 +1,181 @@ +// 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) 2020 by via donau +// – Österreichische Wasserstraßen-Gesellschaft mbH +// Software engineering by Intevation GmbH +// +// Author(s): +// * Tom Gottfried + +package imports + +import ( + "context" + "database/sql" + + "gemma.intevation.de/gemma/pkg/pgxutils" +) + +// Lights is an import job to import +// fairway marks of type LIGHTS in form of point geometries +// and attribute data from a WFS service. +type Lights struct { + FairwayMarks +} + +// Description gives a short info about relevant facts of this import. +func (lights *Lights) Description() (string, error) { + return lights.URL + "|" + lights.FeatureType, nil +} + +// LIGHTSJobKind is the import queue type identifier. +const LIGHTSJobKind JobKind = "fm_lights" + +type lightsJobCreator struct{} + +func init() { + RegisterJobCreator(LIGHTSJobKind, lightsJobCreator{}) +} + +func (lightsJobCreator) Description() string { return "fairway marks lights" } + +func (lightsJobCreator) AutoAccept() bool { return true } + +func (lightsJobCreator) Create() Job { return new(Lights) } + +func (lightsJobCreator) Depends() [2][]string { + return [2][]string{ + {"fairway_marks_lights"}, + {}, + } +} + +// StageDone is a NOP for fairway marks imports. +func (lightsJobCreator) StageDone(context.Context, *sql.Tx, int64) error { + return nil +} + +// CleanUp for fairway marks imports is a NOP. +func (*Lights) CleanUp() error { return nil } + +type lightsProperties struct { + fairwayMarksProperties + Colour *string `json:"hydro_colour"` + Condtn *int `json:"hydro_condtn"` + Orient *float64 `json:"hydro_orient"` + Catlit *string `json:"hydro_catlit"` + Exclit *int `json:"hydro_exclit"` + Litchr *int `json:"hydro_litchr"` + Litvis *string `json:"hydro_litvis"` + Mltylt *int `json:"hydro_mltylt"` + Sectr1 *float64 `json:"hydro_sectr1"` + Sectr2 *float64 `json:"hydro_sectr2"` + Siggrp *string `json:"hydro_siggrp"` + Sigper *float64 `json:"hydro_sigper"` + Sigseq *string `json:"hydro_sigseq"` + Status *string `json:"hydro_status"` +} + +type lightsFeaturetype struct { + geom pointSlice + props *lightsProperties +} + +// Do executes the actual import. +func (fm *Lights) Do( + ctx context.Context, + importID int64, + conn *sql.Conn, + feedback Feedback, +) (interface{}, error) { + + err := getFMFeatures( + ctx, + conn, + feedback, + fm.FairwayMarks, + func() interface{} { return new(lightsProperties) }, + func(p pointSlice, props interface{}) interface{} { + return &lightsFeaturetype{p, props.(*lightsProperties)} + }, + func( + tx *sql.Tx, epsg int, fms []interface{}, + ) (outsideOrDup int, features int, err error) { + + feedback.Info("Store fairway marks of type LIGHTS") + + insertStmt, err := tx.PrepareContext( + ctx, + getFMInsertSQL("lights", + "colour", "condtn", "orient", + "catlit", "exclit", "litchr", + "litvis", "mltylt", "sectr1", + "sectr2", "siggrp", "sigper", + "sigseq", "status"), + ) + if err != nil { + return + } + defer insertStmt.Close() + + savepoint := Savepoint(ctx, tx, "feature") + + for _, fm := range fms { + + f := fm.(*lightsFeaturetype) + + var fmid int64 + err := savepoint(func() error { + err := insertStmt.QueryRowContext( + ctx, + f.geom.asWKB(), + epsg, + f.props.Datsta, + f.props.Datend, + f.props.Persta, + f.props.Perend, + f.props.Objnam, + f.props.Nobjnm, + f.props.Inform, + f.props.Ninfom, + f.props.Scamin, + f.props.Picrep, + f.props.Txtdsc, + f.props.Sordat, + f.props.Sorind, + f.props.Colour, + f.props.Condtn, + f.props.Orient, + f.props.Catlit, + f.props.Exclit, + f.props.Litchr, + f.props.Litvis, + f.props.Mltylt, + f.props.Sectr1, + f.props.Sectr2, + f.props.Siggrp, + f.props.Sigper, + f.props.Sigseq, + f.props.Status, + ).Scan(&fmid) + return err + }) + switch { + case err == sql.ErrNoRows: + outsideOrDup++ + // ignore -> filtered by responsibility area or a duplicate + case err != nil: + feedback.Error(pgxutils.ReadableError{Err: err}.Error()) + default: + features++ + } + } + return + }) + + return nil, err +} diff -r c4d84be3a476 -r 4c57d80ad7a7 pkg/imports/fm_notmrk.go --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pkg/imports/fm_notmrk.go Tue Feb 18 09:10:27 2020 +0100 @@ -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) 2020 by via donau +// – Österreichische Wasserstraßen-Gesellschaft mbH +// Software engineering by Intevation GmbH +// +// Author(s): +// * Tom Gottfried + +package imports + +import ( + "context" + "database/sql" + "strings" + + "gemma.intevation.de/gemma/pkg/pgxutils" +) + +// Notmrk is an import job to import +// fairway marks of type NOTMRK in form of point geometries +// and attribute data from a WFS service. +type Notmrk struct { + FairwayMarks +} + +// Description gives a short info about relevant facts of this import. +func (notmrk *Notmrk) Description() (string, error) { + return notmrk.URL + "|" + notmrk.FeatureType, nil +} + +// NOTMRKJobKind is the import queue type identifier. +const NOTMRKJobKind JobKind = "fm_notmrk" + +type notmrkJobCreator struct{} + +func init() { + RegisterJobCreator(NOTMRKJobKind, notmrkJobCreator{}) +} + +func (notmrkJobCreator) Description() string { return "fairway marks notmrk" } + +func (notmrkJobCreator) AutoAccept() bool { return true } + +func (notmrkJobCreator) Create() Job { return new(Notmrk) } + +func (notmrkJobCreator) Depends() [2][]string { + return [2][]string{ + {"fairway_marks_notmrk"}, + {}, + } +} + +// StageDone is a NOP for fairway marks imports. +func (notmrkJobCreator) StageDone(context.Context, *sql.Tx, int64) error { + return nil +} + +// CleanUp for fairway marks imports is a NOP. +func (*Notmrk) CleanUp() error { return nil } + +type notmrkProperties struct { + fairwayMarksProperties + Condtn *int `json:"hydro_condtn"` + Marsys *int `json:"hydro_bcnshp"` + Dirimp *string `json:"ienc_dirimp"` + Orient *float64 `json:"hydro_orient"` + Status *string `json:"hydro_status"` + Addmrk *string `json:"ienc_addmrk"` + Catnmk *int `json:"ienc_catnmk"` + Disipd *float64 `json:"ienc_disipd"` + Disipu *float64 `json:"ienc_disipu"` + Disbk1 *float64 `json:"ienc_disbk1"` + Disbk2 *float64 `json:"ienc_disbk2"` + Fnctnm *int `json:"ienc_fnctnm"` + Bnkwtw *int `json:"ienc_bnkwtw"` +} + +type notmrkFeaturetype struct { + geom pointSlice + props *notmrkProperties +} + +const ( + insertNotmrkDirimpSQL = ` +INSERT INTO waterway.fairway_marks_notmrk_dirimps (fm_notmrk_id, dirimp) + VALUES ($1, $2) +` +) + +// Do executes the actual import. +func (fm *Notmrk) Do( + ctx context.Context, + importID int64, + conn *sql.Conn, + feedback Feedback, +) (interface{}, error) { + + err := getFMFeatures( + ctx, + conn, + feedback, + fm.FairwayMarks, + func() interface{} { return new(notmrkProperties) }, + func(p pointSlice, props interface{}) interface{} { + return ¬mrkFeaturetype{p, props.(*notmrkProperties)} + }, + func( + tx *sql.Tx, epsg int, fms []interface{}, + ) (outsideOrDup int, features int, err error) { + + feedback.Info("Store fairway marks of type NOTMRK") + + insertStmt, err := tx.PrepareContext( + ctx, + getFMInsertSQL("notmrk", + "condtn", "marsys", "orient", + "status", "addmrk", "catnmk", + "disipd", "disipu", "disbk1", + "disbk2", "fnctnm", "bnkwtw"), + ) + if err != nil { + return + } + defer insertStmt.Close() + + insertNotmrkDirimpStmt, err := tx.PrepareContext( + ctx, insertNotmrkDirimpSQL) + if err != nil { + return + } + defer insertNotmrkDirimpStmt.Close() + + savepoint := Savepoint(ctx, tx, "feature") + + for _, fm := range fms { + + f := fm.(*notmrkFeaturetype) + + var fmid int64 + err := savepoint(func() error { + err := insertStmt.QueryRowContext( + ctx, + f.geom.asWKB(), + epsg, + f.props.Datsta, + f.props.Datend, + f.props.Persta, + f.props.Perend, + f.props.Objnam, + f.props.Nobjnm, + f.props.Inform, + f.props.Ninfom, + f.props.Scamin, + f.props.Picrep, + f.props.Txtdsc, + f.props.Sordat, + f.props.Sorind, + f.props.Condtn, + f.props.Marsys, + f.props.Orient, + f.props.Status, + f.props.Addmrk, + f.props.Catnmk, + f.props.Disipd, + f.props.Disipu, + f.props.Disbk1, + f.props.Disbk2, + f.props.Fnctnm, + f.props.Bnkwtw, + ).Scan(&fmid) + return err + }) + switch { + case err == sql.ErrNoRows: + outsideOrDup++ + // ignore -> filtered by responsibility area or a duplicate + // TODO: handle eventual changes to dirimp + case err != nil: + feedback.Error(pgxutils.ReadableError{Err: err}.Error()) + default: + features++ + + if f.props.Dirimp != nil && *f.props.Dirimp != "" { + dirimps := strings.Split(*f.props.Dirimp, ",") + for _, dirimp := range dirimps { + if err := savepoint(func() error { + _, err := insertNotmrkDirimpStmt.ExecContext( + ctx, fmid, dirimp) + return err + }); err != nil { + feedback.Warn( + pgxutils.ReadableError{Err: err}.Error()) + feedback.Info( + "Tried to import '%s' as dirimp value", + dirimp) + } + } + } + } + } + return + }) + + return nil, err +} diff -r c4d84be3a476 -r 4c57d80ad7a7 pkg/imports/fm_rtpbcn.go --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pkg/imports/fm_rtpbcn.go Tue Feb 18 09:10:27 2020 +0100 @@ -0,0 +1,157 @@ +// 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) 2020 by via donau +// – Österreichische Wasserstraßen-Gesellschaft mbH +// Software engineering by Intevation GmbH +// +// Author(s): +// * Tom Gottfried + +package imports + +import ( + "context" + "database/sql" + + "gemma.intevation.de/gemma/pkg/pgxutils" +) + +// Rtpbcn is an import job to import +// fairway marks of type RTPBCN in form of point geometries +// and attribute data from a WFS service. +type Rtpbcn struct { + FairwayMarks +} + +// Description gives a short info about relevant facts of this import. +func (rtpbcn *Rtpbcn) Description() (string, error) { + return rtpbcn.URL + "|" + rtpbcn.FeatureType, nil +} + +// RTPBCNJobKind is the import queue type identifier. +const RTPBCNJobKind JobKind = "fm_rtpbcn" + +type rtpbcnJobCreator struct{} + +func init() { + RegisterJobCreator(RTPBCNJobKind, rtpbcnJobCreator{}) +} + +func (rtpbcnJobCreator) Description() string { return "fairway marks rtpbcn" } + +func (rtpbcnJobCreator) AutoAccept() bool { return true } + +func (rtpbcnJobCreator) Create() Job { return new(Rtpbcn) } + +func (rtpbcnJobCreator) Depends() [2][]string { + return [2][]string{ + {"fairway_marks_rtpbcn"}, + {}, + } +} + +// StageDone is a NOP for fairway marks imports. +func (rtpbcnJobCreator) StageDone(context.Context, *sql.Tx, int64) error { + return nil +} + +// CleanUp for fairway marks imports is a NOP. +func (*Rtpbcn) CleanUp() error { return nil } + +type rtpbcnProperties struct { + fairwayMarksProperties + Condtn *int `json:"hydro_condtn"` + Siggrp *string `json:"hydro_siggrp"` + Catrtb *int `json:"hydro_catrtb"` + Radwal *string `json:"hydro_radwal"` +} + +type rtpbcnFeaturetype struct { + geom pointSlice + props *rtpbcnProperties +} + +// Do executes the actual import. +func (fm *Rtpbcn) Do( + ctx context.Context, + importID int64, + conn *sql.Conn, + feedback Feedback, +) (interface{}, error) { + + err := getFMFeatures( + ctx, + conn, + feedback, + fm.FairwayMarks, + func() interface{} { return new(rtpbcnProperties) }, + func(p pointSlice, props interface{}) interface{} { + return &rtpbcnFeaturetype{p, props.(*rtpbcnProperties)} + }, + func( + tx *sql.Tx, epsg int, fms []interface{}, + ) (outsideOrDup int, features int, err error) { + + feedback.Info("Store fairway marks of type RTPBCN") + + insertStmt, err := tx.PrepareContext( + ctx, + getFMInsertSQL("rtpbcn", + "condtn", "siggrp", "catrtb", "radwal"), + ) + if err != nil { + return + } + defer insertStmt.Close() + + savepoint := Savepoint(ctx, tx, "feature") + + for _, fm := range fms { + + f := fm.(*rtpbcnFeaturetype) + + var fmid int64 + err := savepoint(func() error { + err := insertStmt.QueryRowContext( + ctx, + f.geom.asWKB(), + epsg, + f.props.Datsta, + f.props.Datend, + f.props.Persta, + f.props.Perend, + f.props.Objnam, + f.props.Nobjnm, + f.props.Inform, + f.props.Ninfom, + f.props.Scamin, + f.props.Picrep, + f.props.Txtdsc, + f.props.Sordat, + f.props.Sorind, + f.props.Condtn, + f.props.Siggrp, + f.props.Catrtb, + f.props.Radwal, + ).Scan(&fmid) + return err + }) + switch { + case err == sql.ErrNoRows: + outsideOrDup++ + // ignore -> filtered by responsibility area or a duplicate + case err != nil: + feedback.Error(pgxutils.ReadableError{Err: err}.Error()) + default: + features++ + } + } + return + }) + + return nil, err +} diff -r c4d84be3a476 -r 4c57d80ad7a7 pkg/imports/fm_topmar.go --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pkg/imports/fm_topmar.go Tue Feb 18 09:10:27 2020 +0100 @@ -0,0 +1,157 @@ +// 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) 2020 by via donau +// – Österreichische Wasserstraßen-Gesellschaft mbH +// Software engineering by Intevation GmbH +// +// Author(s): +// * Tom Gottfried + +package imports + +import ( + "context" + "database/sql" + + "gemma.intevation.de/gemma/pkg/pgxutils" +) + +// Topmar is an import job to import +// fairway marks of type TOPMAR in form of point geometries +// and attribute data from a WFS service. +type Topmar struct { + FairwayMarks +} + +// Description gives a short info about relevant facts of this import. +func (topmar *Topmar) Description() (string, error) { + return topmar.URL + "|" + topmar.FeatureType, nil +} + +// TOPMARJobKind is the import queue type identifier. +const TOPMARJobKind JobKind = "fm_topmar" + +type topmarJobCreator struct{} + +func init() { + RegisterJobCreator(TOPMARJobKind, topmarJobCreator{}) +} + +func (topmarJobCreator) Description() string { return "fairway marks topmar" } + +func (topmarJobCreator) AutoAccept() bool { return true } + +func (topmarJobCreator) Create() Job { return new(Topmar) } + +func (topmarJobCreator) Depends() [2][]string { + return [2][]string{ + {"fairway_marks_topmar"}, + {}, + } +} + +// StageDone is a NOP for fairway marks imports. +func (topmarJobCreator) StageDone(context.Context, *sql.Tx, int64) error { + return nil +} + +// CleanUp for fairway marks imports is a NOP. +func (*Topmar) CleanUp() error { return nil } + +type topmarProperties struct { + fairwayMarksProperties + Colour *string `json:"hydro_colour"` + Colpat *string `json:"hydro_colpat"` + Condtn *int `json:"hydro_condtn"` + Topshp *int `json:"hydro_topshp"` +} + +type topmarFeaturetype struct { + geom pointSlice + props *topmarProperties +} + +// Do executes the actual import. +func (fm *Topmar) Do( + ctx context.Context, + importID int64, + conn *sql.Conn, + feedback Feedback, +) (interface{}, error) { + + err := getFMFeatures( + ctx, + conn, + feedback, + fm.FairwayMarks, + func() interface{} { return new(topmarProperties) }, + func(p pointSlice, props interface{}) interface{} { + return &topmarFeaturetype{p, props.(*topmarProperties)} + }, + func( + tx *sql.Tx, epsg int, fms []interface{}, + ) (outsideOrDup int, features int, err error) { + + feedback.Info("Store fairway marks of type TOPMAR") + + insertStmt, err := tx.PrepareContext( + ctx, + getFMInsertSQL("topmar", + "colour", "colpat", "condtn", "topshp"), + ) + if err != nil { + return + } + defer insertStmt.Close() + + savepoint := Savepoint(ctx, tx, "feature") + + for _, fm := range fms { + + f := fm.(*topmarFeaturetype) + + var fmid int64 + err := savepoint(func() error { + err := insertStmt.QueryRowContext( + ctx, + f.geom.asWKB(), + epsg, + f.props.Datsta, + f.props.Datend, + f.props.Persta, + f.props.Perend, + f.props.Objnam, + f.props.Nobjnm, + f.props.Inform, + f.props.Ninfom, + f.props.Scamin, + f.props.Picrep, + f.props.Txtdsc, + f.props.Sordat, + f.props.Sorind, + f.props.Colour, + f.props.Colpat, + f.props.Condtn, + f.props.Topshp, + ).Scan(&fmid) + return err + }) + switch { + case err == sql.ErrNoRows: + outsideOrDup++ + // ignore -> filtered by responsibility area or a duplicate + case err != nil: + feedback.Error(pgxutils.ReadableError{Err: err}.Error()) + default: + features++ + } + } + return + }) + + return nil, err +} diff -r c4d84be3a476 -r 4c57d80ad7a7 pkg/imports/modelconvert.go --- a/pkg/imports/modelconvert.go Tue Feb 18 09:10:05 2020 +0100 +++ b/pkg/imports/modelconvert.go Tue Feb 18 09:10:27 2020 +0100 @@ -30,6 +30,13 @@ BCNLATJobKind: func() interface{} { return new(models.FairwayMarksImport) }, BOYCARJobKind: func() interface{} { return new(models.FairwayMarksImport) }, BOYLATJobKind: func() interface{} { return new(models.FairwayMarksImport) }, + BOYSAWJobKind: func() interface{} { return new(models.FairwayMarksImport) }, + BOYSPPJobKind: func() interface{} { return new(models.FairwayMarksImport) }, + DAYMARJobKind: func() interface{} { return new(models.FairwayMarksImport) }, + LIGHTSJobKind: func() interface{} { return new(models.FairwayMarksImport) }, + RTPBCNJobKind: func() interface{} { return new(models.FairwayMarksImport) }, + TOPMARJobKind: func() interface{} { return new(models.FairwayMarksImport) }, + NOTMRKJobKind: func() interface{} { return new(models.FairwayMarksImport) }, STJobKind: func() interface{} { return new(models.StretchImport) }, SECJobKind: func() interface{} { return new(models.SectionImport) }, DSECJobKind: func() interface{} { return new(models.SectionDelete) }, @@ -172,6 +179,83 @@ } }, + BOYSAWJobKind: func(input interface{}) interface{} { + fmi := input.(*models.FairwayMarksImport) + return &FairwayMarks{ + URL: fmi.URL, + FeatureType: fmi.FeatureType, + SortBy: nilString(fmi.SortBy), + User: nilString(fmi.User), + Password: nilString(fmi.Password), + } + }, + + BOYSPPJobKind: func(input interface{}) interface{} { + fmi := input.(*models.FairwayMarksImport) + return &FairwayMarks{ + URL: fmi.URL, + FeatureType: fmi.FeatureType, + SortBy: nilString(fmi.SortBy), + User: nilString(fmi.User), + Password: nilString(fmi.Password), + } + }, + + DAYMARJobKind: func(input interface{}) interface{} { + fmi := input.(*models.FairwayMarksImport) + return &FairwayMarks{ + URL: fmi.URL, + FeatureType: fmi.FeatureType, + SortBy: nilString(fmi.SortBy), + User: nilString(fmi.User), + Password: nilString(fmi.Password), + } + }, + + LIGHTSJobKind: func(input interface{}) interface{} { + fmi := input.(*models.FairwayMarksImport) + return &FairwayMarks{ + URL: fmi.URL, + FeatureType: fmi.FeatureType, + SortBy: nilString(fmi.SortBy), + User: nilString(fmi.User), + Password: nilString(fmi.Password), + } + }, + + RTPBCNJobKind: func(input interface{}) interface{} { + fmi := input.(*models.FairwayMarksImport) + return &FairwayMarks{ + URL: fmi.URL, + FeatureType: fmi.FeatureType, + SortBy: nilString(fmi.SortBy), + User: nilString(fmi.User), + Password: nilString(fmi.Password), + } + }, + + TOPMARJobKind: func(input interface{}) interface{} { + fmi := input.(*models.FairwayMarksImport) + return &FairwayMarks{ + URL: fmi.URL, + FeatureType: fmi.FeatureType, + SortBy: nilString(fmi.SortBy), + User: nilString(fmi.User), + Password: nilString(fmi.Password), + } + }, + + NOTMRKJobKind: func(input interface{}) interface{} { + fmi := input.(*models.FairwayMarksImport) + return &FairwayMarks{ + URL: fmi.URL, + FeatureType: fmi.FeatureType, + SortBy: nilString(fmi.SortBy), + User: nilString(fmi.User), + Password: nilString(fmi.Password), + } + }, + STJobKind: func(input interface{}) interface{} { sti := input.(*models.StretchImport) return &Stretch{ diff -r c4d84be3a476 -r 4c57d80ad7a7 pkg/pgxutils/errors.go --- a/pkg/pgxutils/errors.go Tue Feb 18 09:10:05 2020 +0100 +++ b/pkg/pgxutils/errors.go Tue Feb 18 09:10:27 2020 +0100 @@ -98,6 +98,18 @@ return } } + switch err.TableName { + case "fairway_marks_bcnlat_dirimps", + "fairway_marks_daymar_dirimps", + "fairway_marks_notmrk_dirimps": + switch err.ConstraintName { + case "fairway_marks_bcnlat_dirimps_dirimp_fkey", + "fairway_marks_daymar_dirimps_dirimp_fkey", + "fairway_marks_notmrk_dirimps_dirimp_fkey": + m = "Invalid value for dirimp" + return + } + } } case uniqueViolation: switch err.SchemaName { diff -r c4d84be3a476 -r 4c57d80ad7a7 schema/gemma.sql --- a/schema/gemma.sql Tue Feb 18 09:10:05 2020 +0100 +++ b/schema/gemma.sql Tue Feb 18 09:10:27 2020 +0100 @@ -288,8 +288,7 @@ -- TODO: Do we need name and/or definition from IENC feature catalogue? -- (see page 381 of edition 2.3) ); -INSERT INTO dirimps VALUES (1), (2), (3), (4); --- dirimp_5 left out because it cannot be used for waterway area +INSERT INTO dirimps VALUES (1), (2), (3), (4), (5); CREATE TABLE depth_references ( depth_reference varchar(4) PRIMARY KEY @@ -941,6 +940,175 @@ 0, colour, colpat, conrad, marsys, boyshp, catlam ) AS fairway_marks_boylat) )) + + -- Additional attributes for IENC feature BOYSAW + CREATE TABLE fairway_marks_boysaw ( + id int PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY, + colour varchar, + colpat varchar, + conrad int, + marsys int, + boyshp int + ) INHERITS (fairway_marks) + -- Prevent identical entries using composite type comparison + -- (i.e. considering two NULL values in a field equal): + CREATE UNIQUE INDEX fairway_marks_boysaw_distinct_rows + ON fairway_marks_boysaw + ((CAST((geom, + datsta, datend, persta, perend, objnam, nobjnm, inform, ninfom, + scamin, picrep, txtdsc, sordat, sorind, + 0, colour, colpat, conrad, marsys, boyshp + ) AS fairway_marks_boysaw) + )) + + -- Additional attributes for IENC feature BOYSPP + CREATE TABLE fairway_marks_boyspp ( + id int PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY, + colour varchar, + colpat varchar, + conrad int, + marsys int, + boyshp int, + catspm varchar + ) INHERITS (fairway_marks) + -- Prevent identical entries using composite type comparison + -- (i.e. considering two NULL values in a field equal): + CREATE UNIQUE INDEX fairway_marks_boyspp_distinct_rows + ON fairway_marks_boyspp + ((CAST((geom, + datsta, datend, persta, perend, objnam, nobjnm, inform, ninfom, + scamin, picrep, txtdsc, sordat, sorind, + 0, colour, colpat, conrad, marsys, boyshp, catspm + ) AS fairway_marks_boyspp) + )) + + -- Additional attributes for IENC features DAYMAR/daymar + CREATE TABLE fairway_marks_daymar ( + id int PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY, + colour varchar, + colpat varchar, + condtn int, + topshp int, + orient double precision + ) INHERITS (fairway_marks) + -- Prevent identical entries using composite type comparison + -- (i.e. considering two NULL values in a field equal): + CREATE UNIQUE INDEX fairway_marks_daymar_distinct_rows + ON fairway_marks_daymar + ((CAST((geom, + datsta, datend, persta, perend, objnam, nobjnm, inform, ninfom, + scamin, picrep, txtdsc, sordat, sorind, + 0, colour, colpat, condtn, topshp, orient + ) AS fairway_marks_daymar) + )) + + CREATE TABLE fairway_marks_daymar_dirimps ( + fm_daymar_id int REFERENCES fairway_marks_daymar, + dirimp smallint REFERENCES dirimps, + PRIMARY KEY (fm_daymar_id, dirimp) + ) + + -- Additional attributes for IENC feature LIGHTS + CREATE TABLE fairway_marks_lights ( + id int PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY, + colour varchar, + condtn int, + orient double precision, + catlit varchar, + exclit int, + litchr int, + litvis varchar, + mltylt int, + sectr1 double precision, + sectr2 double precision, + siggrp varchar, + sigper double precision, + sigseq varchar, + status varchar + ) INHERITS (fairway_marks) + -- Prevent identical entries using composite type comparison + -- (i.e. considering two NULL values in a field equal): + CREATE UNIQUE INDEX fairway_marks_lights_distinct_rows + ON fairway_marks_lights + ((CAST((geom, + datsta, datend, persta, perend, objnam, nobjnm, inform, ninfom, + scamin, picrep, txtdsc, sordat, sorind, + 0, colour, condtn, orient, catlit, exclit, litchr, litvis, + mltylt, sectr1, sectr2, siggrp, sigper, sigseq, status + ) AS fairway_marks_lights) + )) + + -- Additional attributes for IENC feature RTPBCN + CREATE TABLE fairway_marks_rtpbcn ( + id int PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY, + condtn int, + siggrp varchar, + catrtb int, + radwal varchar + ) INHERITS (fairway_marks) + -- Prevent identical entries using composite type comparison + -- (i.e. considering two NULL values in a field equal): + CREATE UNIQUE INDEX fairway_marks_rtpbcn_distinct_rows + ON fairway_marks_rtpbcn + ((CAST((geom, + datsta, datend, persta, perend, objnam, nobjnm, inform, ninfom, + scamin, picrep, txtdsc, sordat, sorind, + 0, condtn, siggrp, catrtb, radwal + ) AS fairway_marks_rtpbcn) + )) + + -- Additional attributes for IENC feature TOPMAR + CREATE TABLE fairway_marks_topmar ( + id int PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY, + colour varchar, + colpat varchar, + condtn int, + topshp int + ) INHERITS (fairway_marks) + -- Prevent identical entries using composite type comparison + -- (i.e. considering two NULL values in a field equal): + CREATE UNIQUE INDEX fairway_marks_topmar_distinct_rows + ON fairway_marks_topmar + ((CAST((geom, + datsta, datend, persta, perend, objnam, nobjnm, inform, ninfom, + scamin, picrep, txtdsc, sordat, sorind, + 0, colour, colpat, condtn, topshp + ) AS fairway_marks_topmar) + )) + + -- Additional attributes for IENC feature NOTMRK + CREATE TABLE fairway_marks_notmrk ( + id int PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY, + condtn int, + marsys int, + orient double precision, + status varchar, + addmrk varchar, + catnmk int, + disipd double precision, + disipu double precision, + disbk1 double precision, + disbk2 double precision, + fnctnm int, + bnkwtw int + ) INHERITS (fairway_marks) + -- Prevent identical entries using composite type comparison + -- (i.e. considering two NULL values in a field equal): + CREATE UNIQUE INDEX fairway_marks_notmrk_distinct_rows + ON fairway_marks_notmrk + ((CAST((geom, + datsta, datend, persta, perend, objnam, nobjnm, inform, ninfom, + scamin, picrep, txtdsc, sordat, sorind, + 0, condtn, marsys, orient, status, addmrk, catnmk, + disipd, disipu, disbk1, disbk2, fnctnm, bnkwtw + ) AS fairway_marks_notmrk) + )) + + CREATE TABLE fairway_marks_notmrk_dirimps ( + fm_notmrk_id int REFERENCES fairway_marks_notmrk, + dirimp smallint REFERENCES dirimps, + PRIMARY KEY (fm_notmrk_id, dirimp) + ) ; diff -r c4d84be3a476 -r 4c57d80ad7a7 schema/updates/1403/01.add_dirimp_5.sql --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/schema/updates/1403/01.add_dirimp_5.sql Tue Feb 18 09:10:27 2020 +0100 @@ -0,0 +1,1 @@ +INSERT INTO dirimps VALUES (5); diff -r c4d84be3a476 -r 4c57d80ad7a7 schema/updates/1403/02.add_fairway_mark_types.sql --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/schema/updates/1403/02.add_fairway_mark_types.sql Tue Feb 18 09:10:27 2020 +0100 @@ -0,0 +1,151 @@ +CREATE TABLE waterway.fairway_marks_boysaw ( + id int PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY, + colour varchar, + colpat varchar, + conrad int, + marsys int, + boyshp int +) INHERITS (waterway.fairway_marks); +CREATE UNIQUE INDEX fairway_marks_boysaw_distinct_rows + ON waterway.fairway_marks_boysaw + ((CAST((geom, + datsta, datend, persta, perend, objnam, nobjnm, inform, ninfom, + scamin, picrep, txtdsc, sordat, sorind, + 0, colour, colpat, conrad, marsys, boyshp + ) AS waterway.fairway_marks_boysaw) + )); + +CREATE TABLE waterway.fairway_marks_boyspp ( + id int PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY, + colour varchar, + colpat varchar, + conrad int, + marsys int, + boyshp int, + catspm varchar +) INHERITS (waterway.fairway_marks); +CREATE UNIQUE INDEX fairway_marks_boyspp_distinct_rows + ON waterway.fairway_marks_boyspp + ((CAST((geom, + datsta, datend, persta, perend, objnam, nobjnm, inform, ninfom, + scamin, picrep, txtdsc, sordat, sorind, + 0, colour, colpat, conrad, marsys, boyshp, catspm + ) AS waterway.fairway_marks_boyspp) + )); + +CREATE TABLE waterway.fairway_marks_daymar ( + id int PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY, + colour varchar, + colpat varchar, + condtn int, + topshp int, + orient double precision +) INHERITS (waterway.fairway_marks); +CREATE UNIQUE INDEX fairway_marks_daymar_distinct_rows + ON waterway.fairway_marks_daymar + ((CAST((geom, + datsta, datend, persta, perend, objnam, nobjnm, inform, ninfom, + scamin, picrep, txtdsc, sordat, sorind, + 0, colour, colpat, condtn, topshp, orient + ) AS waterway.fairway_marks_daymar) + )); + +CREATE TABLE waterway.fairway_marks_daymar_dirimps ( + fm_daymar_id int REFERENCES waterway.fairway_marks_daymar, + dirimp smallint REFERENCES dirimps, + PRIMARY KEY (fm_daymar_id, dirimp) +); + +CREATE TABLE waterway.fairway_marks_lights ( + id int PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY, + colour varchar, + condtn int, + orient double precision, + catlit varchar, + exclit int, + litchr int, + litvis varchar, + mltylt int, + sectr1 double precision, + sectr2 double precision, + siggrp varchar, + sigper double precision, + sigseq varchar, + status varchar +) INHERITS (waterway.fairway_marks); +CREATE UNIQUE INDEX fairway_marks_lights_distinct_rows + ON waterway.fairway_marks_lights + ((CAST((geom, + datsta, datend, persta, perend, objnam, nobjnm, inform, ninfom, + scamin, picrep, txtdsc, sordat, sorind, + 0, colour, condtn, orient, catlit, exclit, litchr, litvis, + mltylt, sectr1, sectr2, siggrp, sigper, sigseq, status + ) AS waterway.fairway_marks_lights) + )); + +CREATE TABLE waterway.fairway_marks_rtpbcn ( + id int PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY, + condtn int, + siggrp varchar, + catrtb int, + radwal varchar +) INHERITS (waterway.fairway_marks); +CREATE UNIQUE INDEX fairway_marks_rtpbcn_distinct_rows + ON waterway.fairway_marks_rtpbcn + ((CAST((geom, + datsta, datend, persta, perend, objnam, nobjnm, inform, ninfom, + scamin, picrep, txtdsc, sordat, sorind, + 0, condtn, siggrp, catrtb, radwal + ) AS waterway.fairway_marks_rtpbcn) + )); + +CREATE TABLE waterway.fairway_marks_topmar ( + id int PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY, + colour varchar, + colpat varchar, + condtn int, + topshp int +) INHERITS (waterway.fairway_marks); +CREATE UNIQUE INDEX fairway_marks_topmar_distinct_rows + ON waterway.fairway_marks_topmar + ((CAST((geom, + datsta, datend, persta, perend, objnam, nobjnm, inform, ninfom, + scamin, picrep, txtdsc, sordat, sorind, + 0, colour, colpat, condtn, topshp + ) AS waterway.fairway_marks_topmar) + )); + +CREATE TABLE waterway.fairway_marks_notmrk ( + id int PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY, + condtn int, + marsys int, + orient double precision, + status varchar, + addmrk varchar, + catnmk int, + disipd double precision, + disipu double precision, + disbk1 double precision, + disbk2 double precision, + fnctnm int, + bnkwtw int +) INHERITS (waterway.fairway_marks); +CREATE UNIQUE INDEX fairway_marks_notmrk_distinct_rows + ON waterway.fairway_marks_notmrk + ((CAST((geom, + datsta, datend, persta, perend, objnam, nobjnm, inform, ninfom, + scamin, picrep, txtdsc, sordat, sorind, + 0, condtn, marsys, orient, status, addmrk, catnmk, + disipd, disipu, disbk1, disbk2, fnctnm, bnkwtw + ) AS waterway.fairway_marks_notmrk) + )); + +CREATE TABLE waterway.fairway_marks_notmrk_dirimps ( + fm_notmrk_id int REFERENCES waterway.fairway_marks_notmrk, + dirimp smallint REFERENCES dirimps, + PRIMARY KEY (fm_notmrk_id, dirimp) +); + +GRANT SELECT on ALL tables in schema waterway TO waterway_user ; +GRANT INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA waterway + TO waterway_admin;