Skip to content
Open
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion mapbox/tilejson/tilejson.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
// https://github.com/mapbox/tilejson-spec
package tilejson

const Version = "2.1.0"
const (
Version2 = "2.0.0"
Version3 = "3.0.0"
)

type GeomType string

Expand Down Expand Up @@ -135,4 +138,7 @@ type VectorLayer struct {
MaxZoom uint `json:"maxzoom"`
// Tegola supports individual layer tiles.
Tiles []string `json:"tiles"`
// REQUIRED in TileJSON 3.0.0. An object whose keys and values are the names
// and descriptions of attributes available in this layer.
Fields map[string]any `json:"fields,omitempty"`
}
64 changes: 64 additions & 0 deletions provider/postgis/postgis.go
Original file line number Diff line number Diff line change
Expand Up @@ -1069,6 +1069,70 @@ func (p Provider) TileFeatures(
return rows.Err()
}

// LayerFields returns a map of field names to their types for a given layer.
// It executes a sample query (LIMIT 0) to get column information without fetching data.
func (p Provider) LayerFields(ctx context.Context, layerName string) (map[string]interface{}, error) {
Comment thread
iwpnd marked this conversation as resolved.
Outdated
Comment thread
iwpnd marked this conversation as resolved.
Outdated
plyr, ok := p.Layer(layerName)
if !ok {
return nil, ErrLayerNotFound{layerName}
}

// Use a dummy tile to replace tokens in the SQL
dummyTile := provider.NewTile(0, 0, 0, 256, 3857)
sql, err := replaceTokens(plyr.sql, &plyr, dummyTile, true)
if err != nil {
return nil, fmt.Errorf("error replacing layer tokens for layer (%s): %w", layerName, err)
}

// Wrap the query to get column information without fetching rows
sql = fmt.Sprintf("SELECT * FROM (%s) AS subquery LIMIT 0", sql)

rows, err := p.pool.Query(ctx, sql)
if err != nil {
return nil, fmt.Errorf("error querying fields for layer (%s): %w", layerName, err)
}
defer rows.Close()

fields := make(map[string]any)
fdescs := rows.FieldDescriptions()

for _, desc := range fdescs {
fieldName := desc.Name

// Skip geometry and ID fields as they're not attributes
if fieldName == plyr.GeomFieldName() || fieldName == plyr.IDFieldName() {
continue
}

// Map PostgreSQL OID types to simple type names
fieldType := postgresTypeToString(desc.DataTypeOID)
fields[fieldName] = fieldType
}

return fields, nil
}

// postgresTypeToString converts PostgreSQL OID types to simple type strings
func postgresTypeToString(oid uint32) string {
Comment thread
Rub21 marked this conversation as resolved.
Outdated
// Common PostgreSQL type OIDs using pgtype constants
switch oid {
case pgtype.BoolOID:
return "Boolean"
case pgtype.Int8OID, pgtype.Int2OID, pgtype.Int4OID, pgtype.OIDOID:
return "Number"
case pgtype.Float4OID, pgtype.Float8OID, pgtype.NumericOID:
return "Number"
case pgtype.QCharOID, pgtype.NameOID, pgtype.TextOID, pgtype.BPCharOID, pgtype.VarcharOID:
return "String"
case pgtype.TimestampOID, pgtype.TimestamptzOID:
return "String"
case pgtype.JSONOID, pgtype.JSONBOID:
return "String"
default:
return "String"
}
}

func (p Provider) MVTForLayers(
ctx context.Context,
tile provider.Tile,
Expand Down
8 changes: 8 additions & 0 deletions provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,14 @@ type Tiler interface {
TileFeatures(ctx context.Context, layer string, t Tile, params Params, fn func(f *Feature) error) error
}

// LayerFielder is an optional interface that providers can implement to expose
// field information for their layers. This is used to populate the "fields"
// property in TileJSON 3.0.0 capabilities.
type LayerFielder interface {
// LayerFields returns a map of field names to their type descriptions for the given layer
LayerFields(ctx context.Context, layerName string) (map[string]any, error)
}

// TilerUnion represents either a Std Tiler or and MVTTiler; only one should be not nil.
type TilerUnion struct {
Std Tiler
Expand Down
Loading
Loading