package pgx import ( "database/sql/driver" "fmt" "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgtype" "github.com/pgvector/pgvector-go" ) type SparseVectorCodec struct{} func (SparseVectorCodec) FormatSupported(format int16) bool { return format == pgx.BinaryFormatCode || format == pgx.TextFormatCode } func (SparseVectorCodec) PreferredFormat() int16 { return pgx.BinaryFormatCode } func (SparseVectorCodec) PlanEncode(m *pgtype.Map, oid uint32, format int16, value any) pgtype.EncodePlan { _, ok := value.(pgvector.SparseVector) if !ok { return nil } switch format { case pgx.BinaryFormatCode: return encodePlanSparseVectorCodecBinary{} case pgx.TextFormatCode: return encodePlanSparseVectorCodecText{} } return nil } type encodePlanSparseVectorCodecBinary struct{} func (encodePlanSparseVectorCodecBinary) Encode(value any, buf []byte) (newBuf []byte, err error) { v := value.(pgvector.SparseVector) return v.EncodeBinary(buf) } type encodePlanSparseVectorCodecText struct{} func (encodePlanSparseVectorCodecText) Encode(value any, buf []byte) (newBuf []byte, err error) { v := value.(pgvector.SparseVector) // use String() for now to avoid adding another method to SparseVector return append(buf, v.String()...), nil } func (SparseVectorCodec) PlanScan(m *pgtype.Map, oid uint32, format int16, target any) pgtype.ScanPlan { _, ok := target.(*pgvector.SparseVector) if !ok { return nil } switch format { case pgx.BinaryFormatCode: return scanPlanSparseVectorCodecBinary{} case pgx.TextFormatCode: return scanPlanSparseVectorCodecText{} } return nil } type scanPlanSparseVectorCodecBinary struct{} func (scanPlanSparseVectorCodecBinary) Scan(src []byte, dst any) error { v := (dst).(*pgvector.SparseVector) return v.DecodeBinary(src) } type scanPlanSparseVectorCodecText struct{} func (scanPlanSparseVectorCodecText) Scan(src []byte, dst any) error { v := (dst).(*pgvector.SparseVector) return v.Scan(src) } func (c SparseVectorCodec) DecodeDatabaseSQLValue(m *pgtype.Map, oid uint32, format int16, src []byte) (driver.Value, error) { return c.DecodeValue(m, oid, format, src) } func (c SparseVectorCodec) DecodeValue(m *pgtype.Map, oid uint32, format int16, src []byte) (any, error) { if src == nil { return nil, nil } var vec pgvector.SparseVector scanPlan := c.PlanScan(m, oid, format, &vec) if scanPlan == nil { return nil, fmt.Errorf("Unable to decode sparsevec type") } err := scanPlan.Scan(src, &vec) if err != nil { return nil, err } return vec, nil }