github.com/RevenueMonster/sqlike@v1.0.6/sql/schema/schema.go (about)

     1  package schema
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"reflect"
     7  	"sync"
     8  	"time"
     9  
    10  	"cloud.google.com/go/civil"
    11  	"github.com/RevenueMonster/sqlike/reflext"
    12  	"github.com/RevenueMonster/sqlike/sql/driver"
    13  	sqltype "github.com/RevenueMonster/sqlike/sql/type"
    14  	"github.com/RevenueMonster/sqlike/sqlike/columns"
    15  	"github.com/google/uuid"
    16  	"github.com/paulmach/orb"
    17  	gouuid "github.com/satori/go.uuid"
    18  	"golang.org/x/text/currency"
    19  	"golang.org/x/text/language"
    20  )
    21  
    22  // DataTyper :
    23  type DataTyper interface {
    24  	DataType(info driver.Info, sf reflext.StructFielder) columns.Column
    25  }
    26  
    27  // DataTypeFunc :
    28  type DataTypeFunc func(sf reflext.StructFielder) columns.Column
    29  
    30  // Builder :
    31  type Builder struct {
    32  	mutex    *sync.Mutex
    33  	typeMap  map[interface{}]sqltype.Type
    34  	builders map[sqltype.Type]DataTypeFunc
    35  }
    36  
    37  // NewBuilder :
    38  func NewBuilder() *Builder {
    39  	sb := &Builder{
    40  		mutex:    new(sync.Mutex),
    41  		typeMap:  make(map[interface{}]sqltype.Type),
    42  		builders: make(map[sqltype.Type]DataTypeFunc),
    43  	}
    44  	sb.SetDefaultTypes()
    45  	return sb
    46  }
    47  
    48  // SetType :
    49  func (sb *Builder) SetType(it interface{}, t sqltype.Type) {
    50  	sb.mutex.Lock()
    51  	defer sb.mutex.Unlock()
    52  	sb.typeMap[it] = t
    53  }
    54  
    55  // SetTypeBuilder :
    56  func (sb *Builder) SetTypeBuilder(t sqltype.Type, builder DataTypeFunc) {
    57  	sb.mutex.Lock()
    58  	defer sb.mutex.Unlock()
    59  	sb.builders[t] = builder
    60  }
    61  
    62  // LookUpType :
    63  func (sb *Builder) LookUpType(t reflect.Type) (typ sqltype.Type, exists bool) {
    64  	t = reflext.Deref(t)
    65  	typ, exists = sb.typeMap[t]
    66  	return
    67  }
    68  
    69  // GetColumn :
    70  func (sb *Builder) GetColumn(info driver.Info, sf reflext.StructFielder) (columns.Column, error) {
    71  	t := reflext.Deref(sf.Type())
    72  	v := reflect.New(t)
    73  	if x, ok := v.Interface().(DataTyper); ok {
    74  		return x.DataType(info, sf), nil
    75  	}
    76  
    77  	if x, ok := sb.typeMap[t]; ok {
    78  		return sb.builders[x](sf), nil
    79  	}
    80  
    81  	if x, ok := sb.typeMap[t.Kind()]; ok {
    82  		return sb.builders[x](sf), nil
    83  	}
    84  
    85  	return columns.Column{}, fmt.Errorf("schema: invalid data type support %v", t)
    86  }
    87  
    88  // SetDefaultTypes :
    89  func (sb *Builder) SetDefaultTypes() {
    90  	sb.SetType(reflect.TypeOf([]byte{}), sqltype.Byte)
    91  	sb.SetType(reflect.TypeOf(uuid.UUID{}), sqltype.UUID)
    92  	sb.SetType(reflect.TypeOf(gouuid.UUID{}), sqltype.UUID)
    93  	sb.SetType(reflect.TypeOf(language.Tag{}), sqltype.String)
    94  	sb.SetType(reflect.TypeOf(currency.Unit{}), sqltype.Char)
    95  	sb.SetType(reflect.TypeOf(time.Time{}), sqltype.DateTime)
    96  	sb.SetType(reflect.TypeOf(time.Location{}), sqltype.String)
    97  	sb.SetType(reflect.TypeOf(civil.Date{}), sqltype.Date)
    98  	sb.SetType(reflect.TypeOf(civil.Time{}), sqltype.Time)
    99  	sb.SetType(reflect.TypeOf(json.RawMessage{}), sqltype.JSON)
   100  	sb.SetType(reflect.TypeOf(orb.Point{}), sqltype.Point)
   101  	sb.SetType(reflect.TypeOf(orb.LineString{}), sqltype.LineString)
   102  	sb.SetType(reflect.TypeOf(orb.Polygon{}), sqltype.Polygon)
   103  	sb.SetType(reflect.TypeOf(orb.MultiPoint{}), sqltype.MultiPoint)
   104  	sb.SetType(reflect.TypeOf(orb.MultiLineString{}), sqltype.MultiLineString)
   105  	sb.SetType(reflect.TypeOf(orb.MultiPolygon{}), sqltype.MultiPolygon)
   106  	sb.SetType(reflect.String, sqltype.String)
   107  	sb.SetType(reflect.Bool, sqltype.Bool)
   108  	sb.SetType(reflect.Int, sqltype.Int)
   109  	sb.SetType(reflect.Int8, sqltype.Int8)
   110  	sb.SetType(reflect.Int16, sqltype.Int16)
   111  	sb.SetType(reflect.Int32, sqltype.Int32)
   112  	sb.SetType(reflect.Int64, sqltype.Int64)
   113  	sb.SetType(reflect.Uint, sqltype.Uint)
   114  	sb.SetType(reflect.Uint8, sqltype.Uint8)
   115  	sb.SetType(reflect.Uint16, sqltype.Uint16)
   116  	sb.SetType(reflect.Uint32, sqltype.Uint32)
   117  	sb.SetType(reflect.Uint64, sqltype.Uint64)
   118  	sb.SetType(reflect.Float32, sqltype.Float32)
   119  	sb.SetType(reflect.Float64, sqltype.Float64)
   120  	sb.SetType(reflect.Struct, sqltype.Struct)
   121  	sb.SetType(reflect.Array, sqltype.Array)
   122  	sb.SetType(reflect.Slice, sqltype.Slice)
   123  	sb.SetType(reflect.Map, sqltype.Map)
   124  }