mirror of
https://github.com/jackc/pgx.git
synced 2025-05-31 11:42:24 +00:00
Allow NullTime to work with timestamp
This commit is contained in:
parent
28ef19702f
commit
fc484ab5fd
2
conn.go
2
conn.go
@ -557,7 +557,7 @@ func (c *Conn) sendPreparedQuery(ps *PreparedStatement, arguments ...interface{}
|
|||||||
wbuf.WriteInt16(TextFormatCode)
|
wbuf.WriteInt16(TextFormatCode)
|
||||||
default:
|
default:
|
||||||
switch oid {
|
switch oid {
|
||||||
case BoolOid, ByteaOid, Int2Oid, Int4Oid, Int8Oid, Float4Oid, Float8Oid, TimestampTzOid, TimestampTzArrayOid, TimestampArrayOid, BoolArrayOid, Int2ArrayOid, Int4ArrayOid, Int8ArrayOid, Float4ArrayOid, Float8ArrayOid, TextArrayOid, VarcharArrayOid, OidOid:
|
case BoolOid, ByteaOid, Int2Oid, Int4Oid, Int8Oid, Float4Oid, Float8Oid, TimestampTzOid, TimestampTzArrayOid, TimestampOid, TimestampArrayOid, BoolArrayOid, Int2ArrayOid, Int4ArrayOid, Int8ArrayOid, Float4ArrayOid, Float8ArrayOid, TextArrayOid, VarcharArrayOid, OidOid:
|
||||||
wbuf.WriteInt16(BinaryFormatCode)
|
wbuf.WriteInt16(BinaryFormatCode)
|
||||||
default:
|
default:
|
||||||
wbuf.WriteInt16(TextFormatCode)
|
wbuf.WriteInt16(TextFormatCode)
|
||||||
|
34
values.go
34
values.go
@ -71,6 +71,7 @@ func init() {
|
|||||||
DefaultTypeFormats["int4"] = BinaryFormatCode
|
DefaultTypeFormats["int4"] = BinaryFormatCode
|
||||||
DefaultTypeFormats["int8"] = BinaryFormatCode
|
DefaultTypeFormats["int8"] = BinaryFormatCode
|
||||||
DefaultTypeFormats["oid"] = BinaryFormatCode
|
DefaultTypeFormats["oid"] = BinaryFormatCode
|
||||||
|
DefaultTypeFormats["timestamp"] = BinaryFormatCode
|
||||||
DefaultTypeFormats["timestamptz"] = BinaryFormatCode
|
DefaultTypeFormats["timestamptz"] = BinaryFormatCode
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -388,7 +389,8 @@ type NullTime struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (n *NullTime) Scan(vr *ValueReader) error {
|
func (n *NullTime) Scan(vr *ValueReader) error {
|
||||||
if vr.Type().DataType != TimestampTzOid {
|
oid := vr.Type().DataType
|
||||||
|
if oid != TimestampTzOid && oid != TimestampOid {
|
||||||
return SerializationError(fmt.Sprintf("NullTime.Scan cannot decode OID %d", vr.Type().DataType))
|
return SerializationError(fmt.Sprintf("NullTime.Scan cannot decode OID %d", vr.Type().DataType))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -398,7 +400,11 @@ func (n *NullTime) Scan(vr *ValueReader) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
n.Valid = true
|
n.Valid = true
|
||||||
n.Time = decodeTimestampTz(vr)
|
if oid == TimestampTzOid {
|
||||||
|
n.Time = decodeTimestampTz(vr)
|
||||||
|
} else {
|
||||||
|
n.Time = decodeTimestamp(vr)
|
||||||
|
}
|
||||||
|
|
||||||
return vr.Err()
|
return vr.Err()
|
||||||
}
|
}
|
||||||
@ -406,7 +412,7 @@ func (n *NullTime) Scan(vr *ValueReader) error {
|
|||||||
func (n NullTime) FormatCode() int16 { return BinaryFormatCode }
|
func (n NullTime) FormatCode() int16 { return BinaryFormatCode }
|
||||||
|
|
||||||
func (n NullTime) Encode(w *WriteBuf, oid Oid) error {
|
func (n NullTime) Encode(w *WriteBuf, oid Oid) error {
|
||||||
if oid != TimestampTzOid {
|
if oid != TimestampTzOid && oid != TimestampOid {
|
||||||
return SerializationError(fmt.Sprintf("NullTime.Encode cannot encode into OID %d", oid))
|
return SerializationError(fmt.Sprintf("NullTime.Encode cannot encode into OID %d", oid))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -415,7 +421,11 @@ func (n NullTime) Encode(w *WriteBuf, oid Oid) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return encodeTimestampTz(w, n.Time)
|
if oid == TimestampTzOid {
|
||||||
|
return encodeTimestampTz(w, n.Time)
|
||||||
|
} else {
|
||||||
|
return encodeTimestamp(w, n.Time)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hstore represents an hstore column. It does not support a null column or null
|
// Hstore represents an hstore column. It does not support a null column or null
|
||||||
@ -1159,8 +1169,12 @@ func decodeTimestamp(vr *ValueReader) time.Time {
|
|||||||
}
|
}
|
||||||
return t
|
return t
|
||||||
case BinaryFormatCode:
|
case BinaryFormatCode:
|
||||||
vr.Fatal(ProtocolError("Can't decode binary timestamp"))
|
if vr.Len() != 8 {
|
||||||
return zeroTime
|
vr.Fatal(ProtocolError(fmt.Sprintf("Received an invalid size for an timestamp: %d", vr.Len())))
|
||||||
|
}
|
||||||
|
microsecSinceY2K := vr.ReadInt64()
|
||||||
|
microsecSinceUnixEpoch := microsecFromUnixEpochToY2K + microsecSinceY2K
|
||||||
|
return time.Unix(microsecSinceUnixEpoch/1000000, (microsecSinceUnixEpoch%1000000)*1000)
|
||||||
default:
|
default:
|
||||||
vr.Fatal(ProtocolError(fmt.Sprintf("Unknown field description format code: %v", vr.Type().FormatCode)))
|
vr.Fatal(ProtocolError(fmt.Sprintf("Unknown field description format code: %v", vr.Type().FormatCode)))
|
||||||
return zeroTime
|
return zeroTime
|
||||||
@ -1168,13 +1182,7 @@ func decodeTimestamp(vr *ValueReader) time.Time {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func encodeTimestamp(w *WriteBuf, value interface{}) error {
|
func encodeTimestamp(w *WriteBuf, value interface{}) error {
|
||||||
t, ok := value.(time.Time)
|
return encodeTimestampTz(w, value)
|
||||||
if !ok {
|
|
||||||
return fmt.Errorf("Expected time.Time, received %T", value)
|
|
||||||
}
|
|
||||||
|
|
||||||
s := t.Format("2006-01-02 15:04:05.999999")
|
|
||||||
return encodeText(w, s)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func decode1dArrayHeader(vr *ValueReader) (length int32, err error) {
|
func decode1dArrayHeader(vr *ValueReader) (length int32, err error) {
|
||||||
|
@ -130,6 +130,8 @@ func TestNullX(t *testing.T) {
|
|||||||
{"select $1::bool", []interface{}{pgx.NullBool{Bool: true, Valid: false}}, []interface{}{&actual.b}, allTypes{b: pgx.NullBool{Bool: false, Valid: false}}},
|
{"select $1::bool", []interface{}{pgx.NullBool{Bool: true, Valid: false}}, []interface{}{&actual.b}, allTypes{b: pgx.NullBool{Bool: false, Valid: false}}},
|
||||||
{"select $1::timestamptz", []interface{}{pgx.NullTime{Time: time.Unix(123, 5000), Valid: true}}, []interface{}{&actual.t}, allTypes{t: pgx.NullTime{Time: time.Unix(123, 5000), Valid: true}}},
|
{"select $1::timestamptz", []interface{}{pgx.NullTime{Time: time.Unix(123, 5000), Valid: true}}, []interface{}{&actual.t}, allTypes{t: pgx.NullTime{Time: time.Unix(123, 5000), Valid: true}}},
|
||||||
{"select $1::timestamptz", []interface{}{pgx.NullTime{Time: time.Unix(123, 5000), Valid: false}}, []interface{}{&actual.t}, allTypes{t: pgx.NullTime{Time: time.Time{}, Valid: false}}},
|
{"select $1::timestamptz", []interface{}{pgx.NullTime{Time: time.Unix(123, 5000), Valid: false}}, []interface{}{&actual.t}, allTypes{t: pgx.NullTime{Time: time.Time{}, Valid: false}}},
|
||||||
|
{"select $1::timestamp", []interface{}{pgx.NullTime{Time: time.Unix(123, 5000), Valid: true}}, []interface{}{&actual.t}, allTypes{t: pgx.NullTime{Time: time.Unix(123, 5000), Valid: true}}},
|
||||||
|
{"select $1::timestamp", []interface{}{pgx.NullTime{Time: time.Unix(123, 5000), Valid: false}}, []interface{}{&actual.t}, allTypes{t: pgx.NullTime{Time: time.Time{}, Valid: false}}},
|
||||||
{"select 42::int4, $1::float8", []interface{}{pgx.NullFloat64{Float64: 1.23, Valid: true}}, []interface{}{&actual.i32, &actual.f64}, allTypes{i32: pgx.NullInt32{Int32: 42, Valid: true}, f64: pgx.NullFloat64{Float64: 1.23, Valid: true}}},
|
{"select 42::int4, $1::float8", []interface{}{pgx.NullFloat64{Float64: 1.23, Valid: true}}, []interface{}{&actual.i32, &actual.f64}, allTypes{i32: pgx.NullInt32{Int32: 42, Valid: true}, f64: pgx.NullFloat64{Float64: 1.23, Valid: true}}},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user