From ed47f42470666d4d4a70960a5027ec1eb5cbf1ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Carlos=20Nieto?= Date: Sat, 19 Aug 2017 12:27:16 +0000 Subject: [PATCH] db/lib/sqlbuilder: add missing custom_types.go file --- lib/sqlbuilder/custom_types.go | 61 +++++++++++++++++++++++++++++++++ postgresql/adapter_test.go | 12 +++---- postgresql/custom_types.go | 26 +++++++++----- postgresql/custom_types_test.go | 14 ++++---- 4 files changed, 92 insertions(+), 21 deletions(-) create mode 100644 lib/sqlbuilder/custom_types.go diff --git a/lib/sqlbuilder/custom_types.go b/lib/sqlbuilder/custom_types.go new file mode 100644 index 00000000..bf4b0b0a --- /dev/null +++ b/lib/sqlbuilder/custom_types.go @@ -0,0 +1,61 @@ +// Copyright (c) 2012-present The upper.io/db authors. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +package sqlbuilder + +import ( + "database/sql" + "database/sql/driver" + + "reflect" +) + +var ( + // ValuerType is the reflection type for the driver.Valuer interface. + ValuerType = reflect.TypeOf((*driver.Valuer)(nil)).Elem() + + // ScannerType is the reflection type for the sql.Scanner interface. + ScannerType = reflect.TypeOf((*sql.Scanner)(nil)).Elem() + + // ValueWrapperType is the reflection type for the sql.ValueWrapper interface. + ValueWrapperType = reflect.TypeOf((*ValueWrapper)(nil)).Elem() +) + +// ValueWrapper defines a method WrapValue that query arguments can use to wrap +// themselves around helper types right before being used in a query. +// +// Example: +// +// func (a MyCustomArray) WrapValue(value interface{}) interface{} { +// // postgresql.Array adds a driver.Valuer and sql.Scanner around +// // custom arrays. +// return postgresql.Array(values) +// } +type ValueWrapper interface { + WrapValue(value interface{}) interface{} +} + +// ScannerValuer represents a value that satisfies both driver.Valuer and +// sql.Scanner interfaces. +type ScannerValuer interface { + driver.Valuer + sql.Scanner +} diff --git a/postgresql/adapter_test.go b/postgresql/adapter_test.go index 6a863060..b2911a39 100644 --- a/postgresql/adapter_test.go +++ b/postgresql/adapter_test.go @@ -230,11 +230,11 @@ type customJSONB struct { } func (c customJSONB) Value() (driver.Value, error) { - return ToJSONBValue(c) + return JSONBValue(c) } func (c *customJSONB) Scan(src interface{}) error { - return FromJSONBValue(c, src) + return ScanJSONB(c, src) } type autoCustomJSONB struct { @@ -332,8 +332,8 @@ func testPostgreSQLTypes(t *testing.T, sess sqlbuilder.Database) { Int64Value int64Compat `db:"int64_value"` Int64ValueArray int64CompatArray `db:"int64_value_array"` - IntegerArray Int64Array `db:"integer_array"` - StringArray StringArray `db:"string_array"` + IntegerArray Int64Array `db:"integer_array,jsonb"` + StringArray StringArray `db:"string_array,stringarray"` JSONBMap JSONBMap `db:"jsonb_map"` PGTypeInline `db:",inline"` @@ -836,10 +836,10 @@ type Settings struct { } func (s *Settings) Scan(src interface{}) error { - return FromJSONBValue(s, src) + return ScanJSONB(s, src) } func (s Settings) Value() (driver.Value, error) { - return ToJSONBValue(s) + return JSONBValue(s) } func TestOptionTypeJsonbStruct(t *testing.T) { diff --git a/postgresql/custom_types.go b/postgresql/custom_types.go index 4fbd83b9..28c47a8a 100644 --- a/postgresql/custom_types.go +++ b/postgresql/custom_types.go @@ -202,13 +202,13 @@ type JSONBMap map[string]interface{} // Value satisfies the driver.Valuer interface. func (m JSONBMap) Value() (driver.Value, error) { - return ToJSONBValue(m) + return JSONBValue(m) } // Scan satisfies the sql.Scanner interface. func (m *JSONBMap) Scan(src interface{}) error { *m = map[string]interface{}(nil) - return FromJSONBValue(m, src) + return ScanJSONB(m, src) } // JSONBArray represents an array of any type (`[]interface{}`) that is @@ -218,27 +218,37 @@ type JSONBArray []interface{} // Value satisfies the driver.Valuer interface. func (a JSONBArray) Value() (driver.Value, error) { - return ToJSONBValue(a) + return JSONBValue(a) } // Scan satisfies the sql.Scanner interface. func (a *JSONBArray) Scan(src interface{}) error { - return FromJSONBValue(a, src) + return ScanJSONB(a, src) } -// ToJSONBValue takes an interface and provides a driver.Value that can be +// JSONBValue takes an interface and provides a driver.Value that can be // stored as a JSONB column. -func ToJSONBValue(i interface{}) (driver.Value, error) { +func JSONBValue(i interface{}) (driver.Value, error) { v := JSONB{i} return v.Value() } -// FromJSONBValue decodes a JSON byte stream into the passed dst value. -func FromJSONBValue(dst interface{}, src interface{}) error { +// ScanJSONB decodes a JSON byte stream into the passed dst value. +func ScanJSONB(dst interface{}, src interface{}) error { v := JSONB{dst} return v.Scan(src) } +// EncodeJSONB is deprecated and going to be removed. Use ScanJSONB instead. +func EncodeJSONB(i interface{}) (driver.Value, error) { + return JSONBValue(i) +} + +// DecodeJSONB is deprecated and going to be removed. Use JSONBValue instead. +func DecodeJSONB(dst interface{}, src interface{}) error { + return ScanJSONB(dst, src) +} + // JSONBConverter provides a helper method WrapValue that satisfies // sqlbuilder.ValueWrapper, can be used to encode Go structs into JSONB // PostgreSQL types and vice versa. diff --git a/postgresql/custom_types_test.go b/postgresql/custom_types_test.go index 2e81092b..8cf41830 100644 --- a/postgresql/custom_types_test.go +++ b/postgresql/custom_types_test.go @@ -12,10 +12,10 @@ type testStruct struct { V JSONB `json:"v"` } -func TestFromJSONBValue(t *testing.T) { +func TestScanJSONB(t *testing.T) { { a := testStruct{} - err := FromJSONBValue(&a, []byte(`{"x": 5, "z": "Hello", "v": 1}`)) + err := ScanJSONB(&a, []byte(`{"x": 5, "z": "Hello", "v": 1}`)) assert.NoError(t, err) assert.Equal(t, "Hello", a.Z) assert.Equal(t, float64(1), a.V.V) @@ -23,7 +23,7 @@ func TestFromJSONBValue(t *testing.T) { } { a := testStruct{} - err := FromJSONBValue(&a, []byte(`{"x": 5, "z": "Hello", "v": null}`)) + err := DecodeJSONB(&a, []byte(`{"x": 5, "z": "Hello", "v": null}`)) assert.NoError(t, err) assert.Equal(t, "Hello", a.Z) assert.Equal(t, nil, a.V.V) @@ -31,7 +31,7 @@ func TestFromJSONBValue(t *testing.T) { } { a := testStruct{} - err := FromJSONBValue(&a, []byte(`{"x": 5, "z": "Hello"}`)) + err := ScanJSONB(&a, []byte(`{"x": 5, "z": "Hello"}`)) assert.NoError(t, err) assert.Equal(t, "Hello", a.Z) assert.Equal(t, nil, a.V.V) @@ -39,19 +39,19 @@ func TestFromJSONBValue(t *testing.T) { } { a := testStruct{} - err := FromJSONBValue(&a, []byte(`{"v": "Hello"}`)) + err := ScanJSONB(&a, []byte(`{"v": "Hello"}`)) assert.NoError(t, err) assert.Equal(t, "Hello", a.V.V) } { a := testStruct{} - err := FromJSONBValue(&a, []byte(`{"v": true}`)) + err := ScanJSONB(&a, []byte(`{"v": true}`)) assert.NoError(t, err) assert.Equal(t, true, a.V.V) } { a := testStruct{} - err := FromJSONBValue(&a, []byte(`{}`)) + err := ScanJSONB(&a, []byte(`{}`)) assert.NoError(t, err) assert.Equal(t, nil, a.V.V) }