func (b *writeBuffer) writeTextDatum(d parser.Datum, sessionLoc *time.Location) { if log.V(2) { log.Infof(context.TODO(), "pgwire writing TEXT datum of type: %T, %#v", d, d) } if d == parser.DNull { // NULL is encoded as -1; all other values have a length prefix. b.putInt32(-1) return } switch v := d.(type) { case *parser.DBool: b.putInt32(1) if *v { b.writeByte('t') } else { b.writeByte('f') } case *parser.DInt: // Start at offset 4 because `putInt32` clobbers the first 4 bytes. s := strconv.AppendInt(b.putbuf[4:4], int64(*v), 10) b.putInt32(int32(len(s))) b.write(s) case *parser.DFloat: // Start at offset 4 because `putInt32` clobbers the first 4 bytes. s := strconv.AppendFloat(b.putbuf[4:4], float64(*v), 'f', -1, 64) b.putInt32(int32(len(s))) b.write(s) case *parser.DDecimal: b.writeLengthPrefixedDatum(v) case *parser.DBytes: // http://www.postgresql.org/docs/current/static/datatype-binary.html#AEN5667 // Code cribbed from github.com/lib/pq. result := make([]byte, 2+hex.EncodedLen(len(*v))) result[0] = '\\' result[1] = 'x' hex.Encode(result[2:], []byte(*v)) b.putInt32(int32(len(result))) b.write(result) case *parser.DString: b.writeLengthPrefixedString(string(*v)) case *parser.DCollatedString: b.writeLengthPrefixedString(v.Contents) case *parser.DDate: t := time.Unix(int64(*v)*secondsInDay, 0) // Start at offset 4 because `putInt32` clobbers the first 4 bytes. s := formatTs(t, nil, b.putbuf[4:4]) b.putInt32(int32(len(s))) b.write(s) case *parser.DTimestamp: // Start at offset 4 because `putInt32` clobbers the first 4 bytes. s := formatTs(v.Time, nil, b.putbuf[4:4]) b.putInt32(int32(len(s))) b.write(s) case *parser.DTimestampTZ: // Start at offset 4 because `putInt32` clobbers the first 4 bytes. s := formatTs(v.Time, sessionLoc, b.putbuf[4:4]) b.putInt32(int32(len(s))) b.write(s) case *parser.DInterval: b.writeLengthPrefixedString(v.ValueAsString()) case *parser.DTuple: b.variablePutbuf.WriteString("(") for i, d := range *v { if i > 0 { b.variablePutbuf.WriteString(",") } if d == parser.DNull { // Emit nothing on NULL. continue } d.Format(&b.variablePutbuf, parser.FmtSimple) } b.variablePutbuf.WriteString(")") b.writeLengthPrefixedVariablePutbuf() case *parser.DArray: b.variablePutbuf.WriteString("{") for i, d := range v.Array { if i > 0 { b.variablePutbuf.WriteString(",") } d.Format(&b.variablePutbuf, parser.FmtSimple) } b.variablePutbuf.WriteString("}") b.writeLengthPrefixedVariablePutbuf() default: b.setError(errors.Errorf("unsupported type %T", d)) } }
// writeLengthPrefixedDatum writes a length-prefixed Datum in its // string representation. The length is encoded as an int32. func (b *writeBuffer) writeLengthPrefixedDatum(d parser.Datum) { d.Format(&b.variablePutbuf, parser.FmtSimple) b.writeLengthPrefixedVariablePutbuf() }