imposm3/database/postgis/spec.go

222 lines
4.8 KiB
Go
Raw Permalink Normal View History

2013-06-11 12:42:32 +04:00
package postgis
import (
"fmt"
"strings"
2015-02-24 12:24:00 +03:00
"github.com/omniscale/imposm3/mapping"
"github.com/omniscale/imposm3/mapping/config"
"github.com/pkg/errors"
2013-06-11 12:42:32 +04:00
)
type ColumnSpec struct {
Name string
FieldType mapping.ColumnType
2013-06-11 12:42:32 +04:00
Type ColumnType
}
type TableSpec struct {
Name string
2013-10-29 11:28:44 +04:00
FullName string
Schema string
Columns []ColumnSpec
GeometryType string
Srid int
Generalizations []*GeneralizedTableSpec
2013-06-11 12:42:32 +04:00
}
type GeneralizedTableSpec struct {
Name string
2013-10-29 11:28:44 +04:00
FullName string
2013-10-28 19:33:39 +04:00
Schema string
2013-06-11 12:42:32 +04:00
SourceName string
Source *TableSpec
SourceGeneralized *GeneralizedTableSpec
Tolerance float64
Where string
created bool
Generalizations []*GeneralizedTableSpec
2013-06-11 12:42:32 +04:00
}
func (col *ColumnSpec) AsSQL() string {
return fmt.Sprintf("\"%s\" %s", col.Name, col.Type.Name())
}
func (spec *TableSpec) CreateTableSQL() string {
2015-02-24 12:24:00 +03:00
foundIdCol := false
for _, cs := range spec.Columns {
if cs.Name == "id" {
foundIdCol = true
}
2013-06-11 12:42:32 +04:00
}
2015-02-24 12:24:00 +03:00
cols := []string{}
if !foundIdCol {
// only add id column if there is no id configured
// TODO allow to disable id column?
cols = append(cols, "id SERIAL PRIMARY KEY")
}
2013-06-11 12:42:32 +04:00
for _, col := range spec.Columns {
if col.Type.Name() == "GEOMETRY" {
continue
}
cols = append(cols, col.AsSQL())
}
columnSQL := strings.Join(cols, ",\n")
return fmt.Sprintf(`
CREATE TABLE IF NOT EXISTS "%s"."%s" (
%s
);`,
spec.Schema,
2013-10-29 11:28:44 +04:00
spec.FullName,
2013-06-11 12:42:32 +04:00
columnSQL,
)
}
func (spec *TableSpec) InsertSQL() string {
var cols []string
var vars []string
for _, col := range spec.Columns {
cols = append(cols, "\""+col.Name+"\"")
vars = append(vars,
col.Type.PrepareInsertSql(len(vars)+1, spec))
}
columns := strings.Join(cols, ", ")
placeholders := strings.Join(vars, ", ")
return fmt.Sprintf(`INSERT INTO "%s"."%s" (%s) VALUES (%s)`,
spec.Schema,
2013-10-29 11:28:44 +04:00
spec.FullName,
2013-06-11 12:42:32 +04:00
columns,
placeholders,
)
}
2013-06-17 17:17:39 +04:00
func (spec *TableSpec) CopySQL() string {
var cols []string
for _, col := range spec.Columns {
cols = append(cols, "\""+col.Name+"\"")
}
columns := strings.Join(cols, ", ")
return fmt.Sprintf(`COPY "%s"."%s" (%s) FROM STDIN`,
spec.Schema,
2013-10-29 11:28:44 +04:00
spec.FullName,
2013-06-17 17:17:39 +04:00
columns,
)
}
2013-06-11 12:42:32 +04:00
func (spec *TableSpec) DeleteSQL() string {
2013-10-28 19:33:39 +04:00
var idColumnName string
2013-06-11 12:42:32 +04:00
for _, col := range spec.Columns {
if col.FieldType.Name == "id" {
2013-10-28 19:33:39 +04:00
idColumnName = col.Name
2013-06-11 12:42:32 +04:00
break
}
}
2013-10-28 19:33:39 +04:00
if idColumnName == "" {
2013-06-11 12:42:32 +04:00
panic("missing id column")
}
return fmt.Sprintf(`DELETE FROM "%s"."%s" WHERE "%s" = $1`,
spec.Schema,
2013-10-29 11:28:44 +04:00
spec.FullName,
2013-10-28 19:33:39 +04:00
idColumnName,
2013-06-11 12:42:32 +04:00
)
}
func NewTableSpec(pg *PostGIS, t *config.Table) (*TableSpec, error) {
2016-01-04 13:19:28 +03:00
var geomType string
if mapping.TableType(t.Type) == mapping.RelationMemberTable {
2016-01-04 13:19:28 +03:00
geomType = "geometry"
} else {
2016-01-04 13:19:28 +03:00
geomType = string(t.Type)
}
2013-06-11 12:42:32 +04:00
spec := TableSpec{
2013-10-28 19:33:39 +04:00
Name: t.Name,
2013-10-29 11:28:44 +04:00
FullName: pg.Prefix + t.Name,
Schema: pg.Config.ImportSchema,
2016-01-04 13:19:28 +03:00
GeometryType: geomType,
2013-06-11 12:42:32 +04:00
Srid: pg.Config.Srid,
}
for _, column := range t.Columns {
columnType, err := mapping.MakeColumnType(column)
if err != nil {
return nil, err
2013-06-11 12:42:32 +04:00
}
pgType, ok := pgTypes[columnType.GoType]
2013-06-11 12:42:32 +04:00
if !ok {
return nil, errors.Errorf("unhandled column type %v, using string type", columnType)
2013-06-11 12:42:32 +04:00
pgType = pgTypes["string"]
}
col := ColumnSpec{column.Name, *columnType, pgType}
2013-06-11 12:42:32 +04:00
spec.Columns = append(spec.Columns, col)
}
return &spec, nil
2013-06-11 12:42:32 +04:00
}
func NewGeneralizedTableSpec(pg *PostGIS, t *config.GeneralizedTable) *GeneralizedTableSpec {
2013-06-11 12:42:32 +04:00
spec := GeneralizedTableSpec{
2013-10-28 19:33:39 +04:00
Name: t.Name,
2013-10-29 11:28:44 +04:00
FullName: pg.Prefix + t.Name,
Schema: pg.Config.ImportSchema,
2013-06-11 12:42:32 +04:00
Tolerance: t.Tolerance,
Where: t.SqlFilter,
SourceName: t.SourceTableName,
}
return &spec
}
2013-10-28 19:33:39 +04:00
func (spec *GeneralizedTableSpec) DeleteSQL() string {
var idColumnName string
for _, col := range spec.Source.Columns {
if col.FieldType.Name == "id" {
idColumnName = col.Name
break
}
}
if idColumnName == "" {
panic("missing id column")
}
return fmt.Sprintf(`DELETE FROM "%s"."%s" WHERE "%s" = $1`,
spec.Schema,
2013-10-29 11:28:44 +04:00
spec.FullName,
2013-10-28 19:33:39 +04:00
idColumnName,
)
}
func (spec *GeneralizedTableSpec) InsertSQL() string {
var idColumnName string
for _, col := range spec.Source.Columns {
if col.FieldType.Name == "id" {
idColumnName = col.Name
break
}
}
if idColumnName == "" {
panic("missing id column")
}
var cols []string
for _, col := range spec.Source.Columns {
cols = append(cols, col.Type.GeneralizeSql(&col, spec))
}
where := fmt.Sprintf(` WHERE "%s" = $1`, idColumnName)
if spec.Where != "" {
where += " AND (" + spec.Where + ")"
}
columnSQL := strings.Join(cols, ",\n")
sql := fmt.Sprintf(`INSERT INTO "%s"."%s" (SELECT %s FROM "%s"."%s"%s)`,
2013-10-29 11:28:44 +04:00
spec.Schema, spec.FullName, columnSQL, spec.Source.Schema,
spec.Source.FullName, where)
2013-10-28 19:33:39 +04:00
return sql
}