refactored fields mapping

master
Oliver Tonnhofer 2013-05-15 11:05:02 +02:00
parent c875284b8c
commit 36341c7575
3 changed files with 90 additions and 64 deletions

View File

@ -1,24 +1,55 @@
package db
type ColumnType struct {
Name string
ValueTemplate string
import (
"fmt"
)
type ColumnType interface {
Name() string
PrepareInsertSql(i int,
spec *TableSpec) string
}
type simpleColumnType struct {
name string
}
func (t *simpleColumnType) Name() string {
return t.name
}
func (t *simpleColumnType) PrepareInsertSql(i int, spec *TableSpec) string {
return fmt.Sprintf("$%d", i)
}
type geometryType struct {
name string
}
func (t *geometryType) Name() string {
return t.name
}
func (t *geometryType) PrepareInsertSql(i int, spec *TableSpec) string {
return fmt.Sprintf("ST_GeomFromWKB($%d, %d)",
i, spec.Srid,
)
}
var pgTypes map[string]ColumnType
func init() {
pgTypes = map[string]ColumnType{
"id": {"BIGINT", ""},
"geometry": {"GEOMETRY", "ST_GeomFromWKB($%d, 3857)"},
"bool": {"BOOL", ""},
"string": {"VARCHAR", ""},
"name": {"VARCHAR", ""},
"direction": {"SMALLINT", ""},
"integer": {"INTEGER", ""},
"wayzorder": {"INTEGER", ""},
"pseudoarea": {"REAL", ""},
"mapping_key": {"VARCHAR", ""},
"mapping_value": {"VARCHAR", ""},
"id": &simpleColumnType{"BIGINT"},
"geometry": &geometryType{"GEOMETRY"},
"bool": &simpleColumnType{"BOOL"},
"string": &simpleColumnType{"VARCHAR"},
"name": &simpleColumnType{"VARCHAR"},
"direction": &simpleColumnType{"SMALLINT"},
"integer": &simpleColumnType{"INTEGER"},
"wayzorder": &simpleColumnType{"INTEGER"},
"pseudoarea": &simpleColumnType{"REAL"},
"mapping_key": &simpleColumnType{"VARCHAR"},
"mapping_value": &simpleColumnType{"VARCHAR"},
}
}

View File

@ -35,16 +35,15 @@ type TableSpec struct {
}
func (col *ColumnSpec) AsSQL() string {
return fmt.Sprintf("\"%s\" %s", col.Name, col.Type.Name)
return fmt.Sprintf("\"%s\" %s", col.Name, col.Type.Name())
}
func (spec *TableSpec) CreateTableSQL() string {
cols := []string{
"id SERIAL PRIMARY KEY",
// "osm_id BIGINT",
}
for _, col := range spec.Columns {
if col.Type.Name == "GEOMETRY" {
if col.Type.Name() == "GEOMETRY" {
continue
}
cols = append(cols, col.AsSQL())
@ -61,23 +60,12 @@ func (spec *TableSpec) CreateTableSQL() string {
}
func (spec *TableSpec) InsertSQL() string {
cols := []string{
// "osm_id",
// "geometry",
}
vars := []string{
// "$1",
// fmt.Sprintf("ST_GeomFromWKB($2, %d)", spec.Srid),
}
var cols []string
var vars []string
for _, col := range spec.Columns {
cols = append(cols, col.Name)
if col.Type.ValueTemplate != "" {
vars = append(vars, fmt.Sprintf(
col.Type.ValueTemplate,
len(vars)+1))
} else {
vars = append(vars, fmt.Sprintf("$%d", len(vars)+1))
}
vars = append(vars,
col.Type.PrepareInsertSql(len(vars)+1, spec))
}
columns := strings.Join(cols, ", ")
placeholders := strings.Join(vars, ", ")
@ -98,11 +86,12 @@ func NewTableSpec(conf *Config, t *mapping.Table) *TableSpec {
Srid: conf.Srid,
}
for _, field := range t.Fields {
col := ColumnSpec{field.Name, pgTypes[field.Type]}
if col.Type.Name == "" {
pgType, ok := pgTypes[field.Type]
if !ok {
log.Println("unhandled", field)
col.Type.Name = "VARCHAR"
pgType = pgTypes["string"]
}
col := ColumnSpec{field.Name, pgType}
spec.Columns = append(spec.Columns, col)
}
return &spec

View File

@ -6,15 +6,16 @@ import (
"strconv"
)
type MakeValue func(string, *element.OSMElem, Match) interface{}
type FieldSpec struct {
Name string
Type string
ValueFunc func(string, *element.OSMElem, Match) interface{}
Name string
Type FieldType
}
func (f *FieldSpec) Value(elem *element.OSMElem, match Match) interface{} {
if f.ValueFunc != nil {
return f.ValueFunc(elem.Tags[f.Name], elem, match)
if f.Type.Func != nil {
return f.Type.Func(elem.Tags[f.Name], elem, match)
}
return nil
}
@ -36,37 +37,42 @@ func (t *Table) TableFields() *TableFields {
for _, mappingField := range t.Fields {
field := FieldSpec{}
field.Name = mappingField.Key
field.Name = mappingField.Name
switch mappingField.Type {
case "id":
field.ValueFunc = Id
case "string":
field.ValueFunc = String
case "direction":
field.ValueFunc = Direction
case "bool":
field.ValueFunc = Bool
case "integer":
field.ValueFunc = Integer
case "wayzorder":
field.ValueFunc = WayZOrder
case "mapping_key":
field.ValueFunc = Key
case "mapping_value":
field.ValueFunc = Value
case "geometry":
field.ValueFunc = Geometry
case "pseudoarea":
field.ValueFunc = PseudoArea
default:
fieldType, ok := FieldTypes[mappingField.Type]
if !ok {
log.Println("unhandled type:", mappingField.Type)
} else {
field.Type = fieldType
}
result.fields = append(result.fields, field)
}
return &result
}
type FieldType struct {
Name string
GoType string
Func MakeValue
}
var FieldTypes map[string]FieldType
func init() {
FieldTypes = map[string]FieldType{
"bool": {"bool", "bool", Bool},
"id": {"id", "int64", Id},
"string": {"string", "string", String},
"direction": {"direction", "int8", Direction},
"integer": {"integer", "int32", Integer},
"mapping_key": {"mapping_key", "string", Key},
"mapping_value": {"mapping_value", "string", Value},
"geometry": {"geometry", "geometry", Geometry},
"wayzorder": {"wayzorder", "int32", WayZOrder},
"pseudoarea": {"pseudoarea", "float32", PseudoArea},
}
}
func Bool(val string, elem *element.OSMElem, match Match) interface{} {
if val == "" || val == "0" || val == "false" || val == "no" {
return false
@ -117,7 +123,7 @@ func PseudoArea(val string, elem *element.OSMElem, match Match) interface{} {
if area == 0.0 {
return nil
}
return area
return float32(area)
}
var wayRanks map[string]int