Skip to content

Commit

Permalink
Add HANA tile providers
Browse files Browse the repository at this point in the history
  • Loading branch information
mrylov committed Mar 21, 2023
1 parent b358d4d commit 3f4852f
Show file tree
Hide file tree
Showing 440 changed files with 47,953 additions and 10,965 deletions.
4 changes: 3 additions & 1 deletion .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
# The main owners and contributes of this project.
* @gdey @ARolek

# Mainter of the gpkg package:
# Maintainer of the gpkg package:
/provider/gpkg @gdey
/ui @ARolek @mapl
# Maintainer of the HANA database provider:
/provider/hana @mrylov
4 changes: 4 additions & 0 deletions .github/workflows/on_pr_push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ jobs:
PGSSLKEY: ""
PGSSLCERT: ""
PGSSLROOTCERT: ""

# HANA tests
RUN_HANA_TESTS: yes
HANA_CONNECTION_STRING: "hdb://TEGOLACI:iZgd6$nOdhf@917df316-4e01-4a10-be54-eac1b6ab15fb.hana.prod-us10.hanacloud.ondemand.com:443?TLSInsecureSkipVerify&TLSServerName=host&timeout=1000&max_connections=10"
run: |
go test -mod vendor -covermode atomic -coverprofile=profile.cov ./...
Expand Down
12 changes: 12 additions & 0 deletions atlas/provider_hana.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// +build !noHanaProvider

package atlas

// The point of this file is to load and register the HANA provider.
// the HANA provider can be excluded during the build with the `noHanaProvider` build flag
// for example from the cmd/tegola directory:
//
// go build -tags 'noHanaProvider'
import (
_ "github.com/go-spatial/tegola/provider/hana"
)
30 changes: 17 additions & 13 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
module github.com/go-spatial/tegola

go 1.17
go 1.18

require (
cloud.google.com/go/storage v1.28.0
github.com/Azure/azure-storage-blob-go v0.0.0-20180706173141-f0a732ea9441
github.com/BurntSushi/toml v0.4.1
github.com/SAP/go-hdb v0.111.9
github.com/ajstarks/svgo v0.0.0-20170507103333-2489f1e6d405
github.com/akrylysov/algnhsa v0.12.1
github.com/aws/aws-sdk-go v1.27.0
Expand All @@ -22,7 +23,7 @@ require (
github.com/mattn/go-sqlite3 v1.14.6
github.com/mattn/goveralls v0.0.5
github.com/pborman/uuid v1.2.0
github.com/prometheus/client_golang v1.9.0
github.com/prometheus/client_golang v1.14.0
github.com/theckman/goconstraint v1.10.1-0.20180216224824-e867bde6e4e1
go.uber.org/zap v1.21.0
gopkg.in/go-playground/colors.v1 v1.0.2-0.20150924111726-b53ecfb39623
Expand All @@ -37,7 +38,7 @@ require (
github.com/arolek/p v0.0.0-20191103215535-df3c295ed582 // indirect
github.com/aws/aws-lambda-go v1.13.3 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.1.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/gofrs/uuid v4.0.0+incompatible // indirect
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect
github.com/google/go-cmp v0.5.9 // indirect
Expand All @@ -52,20 +53,23 @@ require (
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b // indirect
github.com/jackc/puddle v1.2.0 // indirect
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
github.com/prometheus/client_model v0.2.0 // indirect
github.com/prometheus/common v0.15.0 // indirect
github.com/prometheus/procfs v0.2.0 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/onsi/ginkgo v1.16.5 // indirect
github.com/onsi/gomega v1.26.0 // indirect
github.com/prometheus/client_model v0.3.0 // indirect
github.com/prometheus/common v0.39.0 // indirect
github.com/prometheus/procfs v0.9.0 // indirect
github.com/spf13/pflag v1.0.1 // indirect
go.opencensus.io v0.23.0 // indirect
go.uber.org/atomic v1.7.0 // indirect
go.uber.org/multierr v1.6.0 // indirect
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 // indirect
golang.org/x/net v0.0.0-20221014081412-f15817d10f9b // indirect
golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 // indirect
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 // indirect
golang.org/x/text v0.4.0 // indirect
golang.org/x/tools v0.1.12 // indirect
golang.org/x/crypto v0.5.0 // indirect
golang.org/x/exp v0.0.0-20230116083435-1de6713980de // indirect
golang.org/x/net v0.5.0 // indirect
golang.org/x/oauth2 v0.3.0 // indirect
golang.org/x/sys v0.4.0 // indirect
golang.org/x/text v0.6.0 // indirect
golang.org/x/tools v0.2.0 // indirect
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
google.golang.org/api v0.102.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
Expand Down
357 changes: 60 additions & 297 deletions go.sum

Large diffs are not rendered by default.

132 changes: 132 additions & 0 deletions mvtprovider/hana/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
# HANA MVT Provider

The HANA MVT provider manages querying for tile requests against a HANA database with [Vector Tiles support](https://help.sap.com/docs/HANA_CLOUD_DATABASE/bc9e455fe75541b8a248b4c09b086cf5/8cd683c4bb664fd8a71fc3f19ffa7e42.html) to handle the MVT encoding at the database.

The connection between tegola and HANA is configured in a `tegola.toml` file. An example minimum connection config:


```toml
[[providers]]
name = "test_hana" # provider name is referenced from map layers (required)
type = "mvt_hana" # the type of data provider must be "mvt_hana" for this data provider (required)
uri = "hdb://myuser:[email protected]:443?" # HANA connection string (required)
```

### Connection Properties

- `uri` (string): [Required] HANA connection string
- `name` (string): [Required] provider name is referenced from map layers
- `type` (string): [Required] the type of data provider. must be "hana" to use this data provider
- `srid` (int): [Optional] The default SRID for the provider. Defaults to WebMercator (3857) but also supports WGS84 (4326)

#### Connection string properties

**Example**

```
# {protocol}://{user}:{password}@{host}:{port}/{database}?{options}=
hdb://myuser:[email protected]:443?TLSInsecureSkipVerify&timeout=3600&max_connections=30
```

**Options**

- `timeout`: [Optional] Driver side connection timeout in seconds.
- `TLSRootCAFile` [Optional] Path,- filename to root certificate(s).
- `TLSServerName` [Optional] ServerName to verify the hostname. By setting TLSServerName=host, the provider will set TLSServerName same as 'host' value in `uri`.
- `TLSInsecureSkipVerify` [Optional] Controls whether a client verifies the server's certificate chain and host name.
- `max_connections`: [Optional] The max connections to maintain in the connection pool. Defaults to 100. 0 means no max.
- `max_connection_idle_time`: [Optional] The maximum time an idle connection is kept alive. Defaults to "30m".
- `max_connection_life_time` [Optional] The maximum time a connection lives before it is terminated and recreated. Defaults to "1h".

## Provider Layers

In addition to the connection configuration above, Provider Layers need to be configured. A Provider Layer tells tegola how to query HANA for a certain layer. When using the HANA MVT Provider the `ST_AsMVTGeom()` MUST be used. An example minimum config using the `sql` config option:

```toml
[[providers.layers]]
name = "landuse"
# MVT data provider can use both table names and SQL statements. Internally, the provider wraps an SQL query by using
# ST_AsMVT and ST_AsMVTGeom functions.
tablename = "gis.zoning_base_3857"
```

### Provider Layers Properties

- `name` (string): [Required] the name of the layer. This is used to reference this layer from map layers.
- `geometry_fieldname` (string): [Optional] the name of the filed which contains the geometry for the feature. Defaults to `geom`.
- `id_fieldname` (string): [Optional] the name of the feature id field. defaults to `gid`.
- `geometry_type` (string): [Optional] the layer geometry type. If not set, the table will be inspected at startup to try and infer the gemetry type. Valid values are: `Point`, `LineString`, `Polygon`, `MultiPoint`, `MultiLineString`, `MultiPolygon`, `GeometryCollection`.
- `srid` (int): [Optional] the SRID of the layer. Supports `3857` (WebMercator) only.
- `sql` (string): [Required] custom SQL to use use. Supports the following tokens:
- `!BBOX!` - [Required] will be replaced with the bounding box of the tile before the query is sent to the database. `!bbox!` and`!BOX!` are supported as well for compatibilitiy with queries from Mapnik and MapServer styles.
- `!X!` - [Optional] will replaced with the "X" value of the requested tile.
- `!Y!` - [Optional] will replaced with the "Y" value of the requested tile.
- `!Z!` - [Optional] will replaced with the "Z" value of the requested tile.
- `!ZOOM!` - [Optional] will be replaced with the "Z" (zoom) value of the requested tile.
- `!SCALE_DENOMINATOR!` - [Optional] scale denominator, assuming 90.7 DPI (i.e. 0.28mm pixel size)
- `!PIXEL_WIDTH!` - [Optional] the pixel width in meters, assuming 256x256 tiles
- `!PIXEL_HEIGHT!` - [Optional] the pixel height in meters, assuming 256x256 tiles
- `!ID_FIELD!` - [Optional] the id field name
- `!GEOM_FIELD!` - [Optional] the geom field name
- `!GEOM_TYPE!` - [Optional] the geom type if defined otherwise ""
- `buffer` (int): [Optional] the buffer distance by which the clipped geometry may exceed the tile's area. Defaults to 256.
- `clip_geometry` (bool): [Optional] the flag to control whether the geometry is clipped to the tile bounds or not. Defaults to `TRUE`.

## Example mvt_hana and map config

```toml
[[providers]]
name = "test_hana"
type = "mvt_hana"
uri = "hdb://myuser:[email protected]:443?" # HANA connection string (required)
srid = 3857 # The only supported srid is 3857 (optional)

[[providers.layers]]
name = "landuse"
sql = "SELECT geom, gid FROM gis.landuse WHERE !BBOX!"

[[maps]]
name = "cities"
center = [-90.2,38.6,3.0] # where to center of the map (lon, lat, zoom)

[[maps.layers]]
name = "landuse"
provider_layer = "test_hana.landuse"
min_zoom = 0
max_zoom = 14
```

## Example mvt_hana and map config for SRID 4326

When using a 4326 projection with ST_AsMVT the SQL statement needs to be modified. `ST_AsMVTGeom` is expecting data in 3857 projection so the geometries and the `!BBOX!` token need to be transformed prior to `ST_AsMVTGeom` processing them. For example:

```toml
[[providers]]
name = "test_hana"
type = "mvt_hana"
uri = "hdb://myuser:[email protected]:443?" # HANA connection string (required)
srid = 3857 # The only supported srid is 3857 (optional)

[[providers.layers]]
name = "landuse"
sql = "SELECT * FROM (SELECT id, name, geom.ST_Transform(3857) AS geom FROM ne_50m_rivers_lake_centerlines) AS sub WHERE !BBOX!"

[[maps]]
name = "cities"
center = [-90.2,38.6,3.0] # where to center of the map (lon, lat, zoom)

[[maps.layers]]
name = "landuse"
provider_layer = "test_hana.landuse"
min_zoom = 0
max_zoom = 14
```

## Testing

Testing is designed to work against a live SAP HANA database. To see how to set up a database check this [github actions script](https://github.com/go-spatial/tegola/blob/master/.github/worksflows/on_pr_push.yml). To run the HANA tests, the following environment variables need to be set:

```bash
$ export RUN_HANA_TESTS=yes
$ export HANA_CONNECTION_STRING="hdb://myuser:[email protected]:443?TLSInsecureSkipVerify"
```
5 changes: 5 additions & 0 deletions mvtprovider/hana/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// Package hana is a placeholder for the SAP HANA database.
// The hana provider is provided by the provider.Hana provider
// please consult that for information on how to use it.
// please note that the provider type will be mvt_hana
package hana
101 changes: 101 additions & 0 deletions provider/hana/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# HANA
The HANA provider manages querying for tile requests against an [SAP HANA](https://www.sap.com/products/hana.html) database. The connection between tegola and HANA is configured in a `tegola.toml` file. An example minimum connection config:


```toml
[[providers]]
name = "test_hana" # provider name is referenced from map layers (required)
type = "hana" # the type of data provider must be "hana" for this data provider (required)
uri = "hdb://myuser:[email protected]:443?" # HANA connection string (required)
```

### Connection Properties

- `uri` (string): [Required] HANA connection string
- `name` (string): [Required] provider name is referenced from map layers
- `type` (string): [Required] the type of data provider. must be "hana" to use this data provider
- `srid` (int): [Optional] The default SRID for the provider. Defaults to WebMercator (3857) but also supports WGS84 (4326)

#### Connection string properties

**Example**

```
# {protocol}://{user}:{password}@{host}:{port}/{database}?{options}=
hdb://myuser:[email protected]:443?TLSInsecureSkipVerify&timeout=3600&max_connections=30
```

**Options**

- `timeout`: [Optional] Driver side connection timeout in seconds.
- `TLSRootCAFile` [Optional] Path,- filename to root certificate(s).
- `TLSServerName` [Optional] ServerName to verify the hostname. By setting TLSServerName=host, the provider will set TLSServerName same as 'host' value in `uri`.
- `TLSInsecureSkipVerify` [Optional] Controls whether a client verifies the server's certificate chain and host name.
- `max_connections`: [Optional] The max connections to maintain in the connection pool. Defaults to 100. 0 means no max.
- `max_connection_idle_time`: [Optional] The maximum time an idle connection is kept alive. Defaults to "30m".
- `max_connection_life_time` [Optional] The maximum time a connection lives before it is terminated and recreated. Defaults to "1h".

## Provider Layers
In addition to the connection configuration above, Provider Layers need to be configured. A Provider Layer tells tegola how to query HANA for a certain layer. An example minimum config:

```toml
[[providers.layers]]
name = "landuse"
# this table uses "geom" for the geometry_fieldname and "gid" for the id_fieldname so they don't need to be configured
tablename = "gis.zoning_base_3857"
```

### Provider Layers Properties

- `name` (string): [Required] the name of the layer. This is used to reference this layer from map layers.
- `tablename` (string): [*Required] the name of the database table to query against. Required if `sql` is not defined.
- `geometry_fieldname` (string): [Optional] the name of the filed which contains the geometry for the feature. defaults to `geom`.
- `id_fieldname` (string): [Optional] the name of the feature id field. defaults to `gid`.
- `fields` ([]string): [Optional] a list of fields to include alongside the feature. Can be used if `sql` is not defined.
- `srid` (int): [Optional] the SRID of the layer. Supports `3857` (WebMercator) or `4326` (WGS84).
- `geometry_type` (string): [Optional] the layer geometry type. If not set, the table will be inspected at startup to try and infer the gemetry type. Valid values are: `Point`, `LineString`, `Polygon`, `MultiPoint`, `MultiLineString`, `MultiPolygon`, `GeometryCollection`.
- `sql` (string): [*Required] custom SQL to use use. Required if `tablename` is not defined. Supports the following tokens:
- `!BBOX!` - [Required] will be replaced with the bounding box of the tile before the query is sent to the database. `!bbox!` and`!BOX!` are supported as well for compatibilitiy with queries from Mapnik and MapServer styles.
- `!ZOOM!` - [Optional] will be replaced with the "Z" (zoom) value of the requested tile.
- `!X!` - [Optional] will be replaced with the "X" value of the requested tile.
- `!Y!` - [Optional] will be replaced with the "Y" value of the requested tile.
- `!Z!` - [Optional] will be replaced with the "Z" value of the requested tile.
- `!SCALE_DENOMINATOR!` - [Optional] scale denominator, assuming 90.7 DPI (i.e. 0.28mm pixel size).
- `!PIXEL_WIDTH!` - [Optional] the pixel width in meters, assuming 256x256 tiles.
- `!PIXEL_HEIGHT!` - [Optional] the pixel height in meters, assuming 256x256 tiles.
- `!ID_FIELD!` - [Optional] the id field name.
- `!GEOM_FIELD!` - [Optional] the geom field name.
- `!GEOM_TYPE!` - [Optional] the geom type field name.

`*Required`: either the `tablename` or `sql` must be defined, but not both.

**Example minimum custom SQL config**

```toml
[[providers.layers]]
name = "rivers"
# Custom sql to be used for this layer as a sub query. ST_AsBinary and !BBOX! filter are applied automatically.
sql = "(SELECT id, geom FROM gis.rivers) AS sub"
```

## Environment Variable support
Helpful debugging environment variables:

- `TEGOLA_SQL_DEBUG`: specify the type of SQL debug information to output. Supports the following values:
- `LAYER_SQL`: print layer SQL as they’re parsed from the config file.
- `EXECUTE_SQL`: print SQL that is executed for each tile request and the number of items it returns or an error.
- `LAYER_SQL:EXECUTE_SQL`: print `LAYER_SQL` and `EXECUTE_SQL`.

Example:

```
$ TEGOLA_SQL_DEBUG=LAYER_SQL tegola serve --config=/path/to/conf.toml
```

## Testing
Testing is designed to work against a live SAP HANA database. To see how to set up a database check this [github actions script](https://github.com/go-spatial/tegola/blob/master/.github/worksflows/on_pr_push.yml). To run the HANA tests, the following environment variables need to be set:

```bash
$ export RUN_HANA_TESTS=yes
$ export HANA_CONNECTION_STRING="hdb://myuser:[email protected]:443?TLSInsecureSkipVerify"
```
27 changes: 27 additions & 0 deletions provider/hana/debug.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package hana

import (
"os"
"strings"
)

// debug determines weather extra debugging output is enabled.
// change debug to true to enable additional debugging output
// for this package
const debug = false

const (
EnvSQLDebugName = "TEGOLA_SQL_DEBUG"
EnvSQLDebugLayer = "LAYER_SQL"
EnvSQLDebugExecute = "EXECUTE_SQL"
)

var (
debugLayerSQL bool
debugExecuteSQL bool
)

func init() {
debugLayerSQL = strings.Contains(os.Getenv(EnvSQLDebugName), EnvSQLDebugLayer)
debugExecuteSQL = strings.Contains(os.Getenv(EnvSQLDebugName), EnvSQLDebugExecute)
}
Loading

0 comments on commit 3f4852f

Please sign in to comment.