add postgres hstore type support
This commit is contained in:
parent
744cb7dfda
commit
5f0e640f3d
46
main_test.go
46
main_test.go
@ -145,6 +145,11 @@ type Animal struct {
|
|||||||
UpdatedAt time.Time
|
UpdatedAt time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Details struct {
|
||||||
|
Id int64
|
||||||
|
Bulk gorm.Hstore
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
db gorm.DB
|
db gorm.DB
|
||||||
t1, t2, t3, t4, t5 time.Time
|
t1, t2, t3, t4, t5 time.Time
|
||||||
@ -2037,3 +2042,44 @@ func TestIndices(t *testing.T) {
|
|||||||
t.Errorf("Got error when tried to create index: %+v", err)
|
t.Errorf("Got error when tried to create index: %+v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestHstore(t *testing.T) {
|
||||||
|
if dialect := os.Getenv("GORM_DIALECT"); dialect != "postgres" {
|
||||||
|
t.Skip()
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := db.Exec("CREATE EXTENSION IF NOT EXISTS hstore").Error; err != nil {
|
||||||
|
panic(fmt.Sprintf("No error should happen when create hstore extension, but got %+v", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
db.Exec("drop table details")
|
||||||
|
|
||||||
|
if err := db.CreateTable(&Details{}).Error; err != nil {
|
||||||
|
panic(fmt.Sprintf("No error should happen when create table, but got %+v", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
bankAccountId, phoneNumber, opinion := "123456", "14151321232", "sharkbait"
|
||||||
|
bulk := map[string]*string{
|
||||||
|
"bankAccountId": &bankAccountId,
|
||||||
|
"phoneNumber": &phoneNumber,
|
||||||
|
"opinion": &opinion,
|
||||||
|
}
|
||||||
|
d := Details{Bulk: bulk}
|
||||||
|
db.Save(&d)
|
||||||
|
|
||||||
|
var d2 Details
|
||||||
|
if err := db.First(&d2).Error; err != nil {
|
||||||
|
t.Errorf("Got error when tried to fetch details: %+v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for k := range bulk {
|
||||||
|
r, ok := d2.Bulk[k]
|
||||||
|
if !ok {
|
||||||
|
t.Errorf("Details should be existed")
|
||||||
|
}
|
||||||
|
if res, _ := bulk[k]; *res != *r {
|
||||||
|
t.Errorf("Details should be equal")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
48
postgres.go
48
postgres.go
@ -1,8 +1,12 @@
|
|||||||
package gorm
|
package gorm
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"database/sql"
|
||||||
|
"database/sql/driver"
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
|
"github.com/lib/pq/hstore"
|
||||||
)
|
)
|
||||||
|
|
||||||
type postgres struct {
|
type postgres struct {
|
||||||
@ -35,6 +39,10 @@ func (d *postgres) SqlTag(value reflect.Value, size int) string {
|
|||||||
if value.Type() == timeType {
|
if value.Type() == timeType {
|
||||||
return "timestamp with time zone"
|
return "timestamp with time zone"
|
||||||
}
|
}
|
||||||
|
case reflect.Map:
|
||||||
|
if value.Type() == hstoreType {
|
||||||
|
return "hstore"
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
if _, ok := value.Interface().([]byte); ok {
|
if _, ok := value.Interface().([]byte); ok {
|
||||||
return "bytea"
|
return "bytea"
|
||||||
@ -80,3 +88,43 @@ func (s *postgres) HasColumn(scope *Scope, tableName string, columnName string)
|
|||||||
newScope.DB().QueryRow(newScope.Sql, newScope.SqlVars...).Scan(&count)
|
newScope.DB().QueryRow(newScope.Sql, newScope.SqlVars...).Scan(&count)
|
||||||
return count > 0
|
return count > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var hstoreType = reflect.TypeOf(Hstore{})
|
||||||
|
|
||||||
|
type Hstore map[string]*string
|
||||||
|
|
||||||
|
func (h Hstore) Value() (driver.Value, error) {
|
||||||
|
hstore := hstore.Hstore{Map: map[string]sql.NullString{}}
|
||||||
|
if len(h) == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for key, value := range h {
|
||||||
|
hstore.Map[key] = sql.NullString{*value, true}
|
||||||
|
}
|
||||||
|
return hstore.Value()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Hstore) Scan(value interface{}) error {
|
||||||
|
hstore := hstore.Hstore{}
|
||||||
|
|
||||||
|
if err := hstore.Scan(value); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(hstore.Map) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
*h = Hstore{}
|
||||||
|
for k := range hstore.Map {
|
||||||
|
if hstore.Map[k].Valid {
|
||||||
|
s := hstore.Map[k].String
|
||||||
|
(*h)[k] = &s
|
||||||
|
} else {
|
||||||
|
(*h)[k] = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user