ConvertValue mirrors the reference/default converter in database/sql/driver with _one_ exception. We support uint64 with their high bit and the default implementation does not. This function should be kept in sync with database/sql/driver defaultConverter.ConvertValue() except for that deliberate
(v any)
| 159 | // database/sql/driver defaultConverter.ConvertValue() except for that |
| 160 | // deliberate difference. |
| 161 | func (c converter) ConvertValue(v any) (driver.Value, error) { |
| 162 | if driver.IsValue(v) { |
| 163 | return v, nil |
| 164 | } |
| 165 | |
| 166 | if vr, ok := v.(driver.Valuer); ok { |
| 167 | sv, err := callValuerValue(vr) |
| 168 | if err != nil { |
| 169 | return nil, err |
| 170 | } |
| 171 | if driver.IsValue(sv) { |
| 172 | return sv, nil |
| 173 | } |
| 174 | // A value returned from the Valuer interface can be "a type handled by |
| 175 | // a database driver's NamedValueChecker interface" so we should accept |
| 176 | // uint64 here as well. |
| 177 | if u, ok := sv.(uint64); ok { |
| 178 | return u, nil |
| 179 | } |
| 180 | return nil, fmt.Errorf("non-Value type %T returned from Value", sv) |
| 181 | } |
| 182 | rv := reflect.ValueOf(v) |
| 183 | switch rv.Kind() { |
| 184 | case reflect.Ptr: |
| 185 | // indirect pointers |
| 186 | if rv.IsNil() { |
| 187 | return nil, nil |
| 188 | } else { |
| 189 | return c.ConvertValue(rv.Elem().Interface()) |
| 190 | } |
| 191 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: |
| 192 | return rv.Int(), nil |
| 193 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: |
| 194 | return rv.Uint(), nil |
| 195 | case reflect.Float32, reflect.Float64: |
| 196 | return rv.Float(), nil |
| 197 | case reflect.Bool: |
| 198 | return rv.Bool(), nil |
| 199 | case reflect.Slice: |
| 200 | switch t := rv.Type(); { |
| 201 | case t == jsonType: |
| 202 | return v, nil |
| 203 | case t.Elem().Kind() == reflect.Uint8: |
| 204 | return rv.Bytes(), nil |
| 205 | default: |
| 206 | return nil, fmt.Errorf("unsupported type %T, a slice of %s", v, t.Elem().Kind()) |
| 207 | } |
| 208 | case reflect.String: |
| 209 | return rv.String(), nil |
| 210 | } |
| 211 | return nil, fmt.Errorf("unsupported type %T, a %s", v, rv.Kind()) |
| 212 | } |
| 213 | |
| 214 | var valuerReflectType = reflect.TypeFor[driver.Valuer]() |
| 215 |