@@ -137,10 +137,15 @@ func (c converter) ConvertValue(v interface{}) (driver.Value, error) {
137137 return v , nil
138138 }
139139
140- if v != nil {
141- if valuer , ok := v .(driver.Valuer ); ok {
142- return valuer .Value ()
140+ if vr , ok := v .(driver.Valuer ); ok {
141+ sv , err := callValuerValue (vr )
142+ if err != nil {
143+ return nil , err
144+ }
145+ if ! driver .IsValue (sv ) {
146+ return nil , fmt .Errorf ("non-Value type %T returned from Value" , sv )
143147 }
148+ return sv , nil
144149 }
145150
146151 rv := reflect .ValueOf (v )
@@ -149,8 +154,9 @@ func (c converter) ConvertValue(v interface{}) (driver.Value, error) {
149154 // indirect pointers
150155 if rv .IsNil () {
151156 return nil , nil
157+ } else {
158+ return c .ConvertValue (rv .Elem ().Interface ())
152159 }
153- return c .ConvertValue (rv .Elem ().Interface ())
154160 case reflect .Int , reflect .Int8 , reflect .Int16 , reflect .Int32 , reflect .Int64 :
155161 return rv .Int (), nil
156162 case reflect .Uint , reflect .Uint8 , reflect .Uint16 , reflect .Uint32 :
@@ -176,3 +182,24 @@ func (c converter) ConvertValue(v interface{}) (driver.Value, error) {
176182 }
177183 return nil , fmt .Errorf ("unsupported type %T, a %s" , v , rv .Kind ())
178184}
185+
186+ var valuerReflectType = reflect .TypeOf ((* driver .Valuer )(nil )).Elem ()
187+
188+ // callValuerValue returns vr.Value(), with one exception:
189+ // If vr.Value is an auto-generated method on a pointer type and the
190+ // pointer is nil, it would panic at runtime in the panicwrap
191+ // method. Treat it like nil instead.
192+ //
193+ // This is so people can implement driver.Value on value types and
194+ // still use nil pointers to those types to mean nil/NULL, just like
195+ // string/*string.
196+ //
197+ // This function is copied from the database/sql package.
198+ func callValuerValue (vr driver.Valuer ) (v driver.Value , err error ) {
199+ if rv := reflect .ValueOf (vr ); rv .Kind () == reflect .Ptr &&
200+ rv .IsNil () &&
201+ rv .Type ().Elem ().Implements (valuerReflectType ) {
202+ return nil , nil
203+ }
204+ return vr .Value ()
205+ }
0 commit comments