rbdc_pg/types/
value.rs

1use crate::arguments::PgArgumentBuffer;
2use crate::type_info::PgType;
3use crate::type_info::PgTypeInfo;
4use crate::type_info::PgTypeKind;
5use crate::types::decode::Decode;
6use crate::types::encode::{Encode, IsNull};
7use crate::types::json::{decode_json, encode_json};
8use crate::types::money::Money;
9use crate::types::timestamptz::Timestamptz;
10use crate::types::timetz::Timetz;
11use crate::types::Oid;
12use crate::types::TypeInfo;
13use crate::value::{PgValue, PgValueFormat};
14use rbdc::date::Date;
15use rbdc::datetime::DateTime;
16use rbdc::decimal::Decimal;
17use rbdc::json::Json;
18use rbdc::timestamp::Timestamp;
19use rbdc::types::time::Time;
20use rbdc::uuid::Uuid;
21use rbdc::Error;
22use rbs::Value;
23use std::str::FromStr;
24
25impl TypeInfo for Value {
26    fn type_info(&self) -> PgTypeInfo {
27        match self {
28            Value::Null => PgTypeInfo::UNKNOWN,
29            Value::Bool(_) => PgTypeInfo::BOOL,
30            Value::I32(_) => PgTypeInfo::INT4,
31            Value::I64(_) => PgTypeInfo::INT8,
32            Value::U32(_) => PgTypeInfo::INT4,
33            Value::U64(_) => PgTypeInfo::INT8,
34            Value::F32(_) => PgTypeInfo::FLOAT4,
35            Value::F64(_) => PgTypeInfo::FLOAT8,
36            Value::String(_) => PgTypeInfo::VARCHAR,
37            Value::Binary(_) => PgTypeInfo::BYTEA,
38            Value::Array(_) => PgTypeInfo::JSON,
39            Value::Map(_) => PgTypeInfo::JSON,
40            Value::Ext(type_name, _) => {
41                match *type_name {
42                    "Uuid" => PgTypeInfo::UUID,
43                    //decimal = 12345678
44                    "Decimal" => PgTypeInfo::NUMERIC,
45                    //Date = "1993-02-06"
46                    "Date" => PgTypeInfo::DATE,
47                    //RFC3339NanoTime = "15:04:05.999999999"
48                    "Time" => PgTypeInfo::TIME,
49                    //RFC3339 = "2006-01-02 15:04:05.999999"
50                    "Timestamp" => PgTypeInfo::TIMESTAMP,
51                    "DateTime" => PgTypeInfo::TIMESTAMP,
52                    "Bool" => PgTypeInfo::BOOL,
53                    "Bytea" => PgTypeInfo::BYTEA,
54                    "Char" => PgTypeInfo::CHAR,
55                    "Name" => PgTypeInfo::NAME,
56                    "Int8" => PgTypeInfo::INT8,
57                    "Int2" => PgTypeInfo::INT2,
58                    "Int4" => PgTypeInfo::INT4,
59                    "Text" => PgTypeInfo::TEXT,
60                    "Oid" => PgTypeInfo::OID,
61                    "Json" => PgTypeInfo::JSON,
62                    "Point" => PgTypeInfo::POINT,
63                    "TsVector" => PgTypeInfo::UNKNOWN,
64                    "TsQuery" => PgTypeInfo::UNKNOWN,
65                    "Hstore" => PgTypeInfo::UNKNOWN,
66                    "Lseg" => PgTypeInfo::LSEG,
67                    "Path" => PgTypeInfo::PATH,
68                    "Box" => PgTypeInfo::BOX,
69                    "Polygon" => PgTypeInfo::POLYGON,
70                    "Line" => PgTypeInfo::LINE,
71                    "Cidr" => PgTypeInfo::CIDR,
72                    "Float4" => PgTypeInfo::FLOAT4,
73                    "Float8" => PgTypeInfo::FLOAT8,
74                    "Unknown" => PgTypeInfo::UNKNOWN,
75                    "Circle" => PgTypeInfo::CIRCLE,
76                    "Macaddr8" => PgTypeInfo::MACADDR8,
77                    "Macaddr" => PgTypeInfo::MACADDR,
78                    "Inet" => PgTypeInfo::INET,
79                    "Bpchar" => PgTypeInfo::BPCHAR,
80                    "Varchar" => PgTypeInfo::VARCHAR,
81                    "Timestamptz" => PgTypeInfo::TIMESTAMPTZ,
82                    "Interval" => PgTypeInfo::INTERVAL,
83                    "Timetz" => PgTypeInfo::TIMETZ,
84                    "Bit" => PgTypeInfo::BIT,
85                    "Varbit" => PgTypeInfo::VARBIT,
86                    "Numeric" => PgTypeInfo::NUMERIC,
87                    "Record" => PgTypeInfo::RECORD,
88                    "Jsonb" => PgTypeInfo::JSONB,
89                    "Int4Range" => PgTypeInfo::INT4_RANGE,
90                    "NumRange" => PgTypeInfo::NUM_RANGE,
91                    "TsRange" => PgTypeInfo::TS_RANGE,
92                    "TstzRange" => PgTypeInfo::TSTZ_RANGE,
93                    "DateRange" => PgTypeInfo::DATE_RANGE,
94                    "Int8Range" => PgTypeInfo::INT8_RANGE,
95                    "Jsonpath" => PgTypeInfo::JSONPATH,
96                    "Money" => PgTypeInfo::MONEY,
97                    "Void" => PgTypeInfo::VOID,
98                    "Custom" => PgTypeInfo::UNKNOWN,
99                    "DeclareWithName" => PgTypeInfo::UNKNOWN,
100                    "DeclareWithOid" => PgTypeInfo::UNKNOWN,
101                    _ => PgTypeInfo::UNKNOWN,
102                }
103            }
104        }
105    }
106}
107
108impl Decode for Value {
109    fn decode(arg: PgValue) -> Result<Self, Error> {
110        if arg.value.is_none() {
111            return Ok(Value::Null);
112        }
113        Ok(match arg.type_info().0 {
114            PgType::Bool => Value::Bool(Decode::decode(arg)?),
115            PgType::Bytea => Value::Binary(Vec::<u8>::decode(arg)?), //Vec<u8> is Bytea
116            PgType::Char => Value::String(Decode::decode(arg)?),
117            PgType::Name => Value::String(Decode::decode(arg)?),
118            PgType::Int8 => Value::I64(Decode::decode(arg)?),
119            PgType::Int2 => Value::I32({
120                let i16: i16 = Decode::decode(arg)?;
121                i16 as i32
122            }),
123            PgType::Int4 => Value::I32(Decode::decode(arg)?),
124            PgType::Text => Value::String(Decode::decode(arg)?),
125            PgType::Oid => Value::Ext("Oid", Box::new(Value::U32(Decode::decode(arg)?))),
126            PgType::Json => decode_json(arg)?,
127            PgType::Point => {
128                use crate::types::point::Point;
129                Point::decode(arg)?.into()
130            }
131            PgType::Lseg => Value::Ext(
132                "Lseg",
133                Box::new(Value::Binary({
134                    match arg.format() {
135                        PgValueFormat::Binary => arg.as_bytes()?.to_owned(),
136                        PgValueFormat::Text => arg.as_str()?.as_bytes().to_vec(),
137                    }
138                })),
139            ),
140            PgType::Path => Value::Ext(
141                "Path",
142                Box::new(Value::Binary({
143                    match arg.format() {
144                        PgValueFormat::Binary => arg.as_bytes()?.to_owned(),
145                        PgValueFormat::Text => arg.as_str()?.as_bytes().to_vec(),
146                    }
147                })),
148            ),
149            PgType::Box => Value::Ext(
150                "Box",
151                Box::new(Value::Binary({
152                    match arg.format() {
153                        PgValueFormat::Binary => arg.as_bytes()?.to_owned(),
154                        PgValueFormat::Text => arg.as_str()?.as_bytes().to_vec(),
155                    }
156                })),
157            ),
158            PgType::Polygon => Value::Ext(
159                "Polygon",
160                Box::new(Value::Binary({
161                    match arg.format() {
162                        PgValueFormat::Binary => arg.as_bytes()?.to_owned(),
163                        PgValueFormat::Text => arg.as_str()?.as_bytes().to_vec(),
164                    }
165                })),
166            ),
167            PgType::Line => Value::Ext(
168                "Line",
169                Box::new(Value::Binary({
170                    match arg.format() {
171                        PgValueFormat::Binary => arg.as_bytes()?.to_owned(),
172                        PgValueFormat::Text => arg.as_str()?.as_bytes().to_vec(),
173                    }
174                })),
175            ),
176            PgType::Cidr => Value::Ext(
177                "Cidr",
178                Box::new(Value::Binary({
179                    match arg.format() {
180                        PgValueFormat::Binary => arg.as_bytes()?.to_owned(),
181                        PgValueFormat::Text => arg.as_str()?.as_bytes().to_vec(),
182                    }
183                })),
184            ),
185
186            PgType::Float4 => Value::F32(Decode::decode(arg)?),
187            PgType::Float8 => Value::F64(Decode::decode(arg)?),
188            PgType::Unknown => Value::Null,
189            PgType::Circle => Value::Ext(
190                "Circle",
191                Box::new(Value::Binary({
192                    match arg.format() {
193                        PgValueFormat::Binary => arg.as_bytes()?.to_owned(),
194                        PgValueFormat::Text => arg.as_str()?.as_bytes().to_vec(),
195                    }
196                })),
197            ),
198            PgType::Macaddr8 => Value::Ext(
199                "Macaddr8",
200                Box::new(Value::Binary({
201                    match arg.format() {
202                        PgValueFormat::Binary => arg.as_bytes()?.to_owned(),
203                        PgValueFormat::Text => arg.as_str()?.as_bytes().to_vec(),
204                    }
205                })),
206            ),
207            PgType::Macaddr => Value::Ext(
208                "Macaddr",
209                Box::new(Value::Binary({
210                    match arg.format() {
211                        PgValueFormat::Binary => arg.as_bytes()?.to_owned(),
212                        PgValueFormat::Text => arg.as_str()?.as_bytes().to_vec(),
213                    }
214                })),
215            ),
216            PgType::Inet => Value::Ext(
217                "Inet",
218                Box::new(Value::Binary({
219                    match arg.format() {
220                        PgValueFormat::Binary => arg.as_bytes()?.to_owned(),
221                        PgValueFormat::Text => arg.as_str()?.as_bytes().to_vec(),
222                    }
223                })),
224            ),
225            PgType::Bpchar | PgType::Varchar => Value::String(Decode::decode(arg)?),
226            PgType::Date => {
227                let v: Date = Decode::decode(arg)?;
228                v
229            }
230            .into(),
231            PgType::Time => {
232                let v: Time = Decode::decode(arg)?;
233                v
234            }
235            .into(),
236            PgType::Timestamp => {
237                let v: Timestamp = Decode::decode(arg)?;
238                v
239            }
240            .into(),
241            PgType::Timestamptz => Timestamptz::decode(arg)?.into(),
242            PgType::Interval => Value::Ext(
243                "Interval",
244                Box::new(Value::Binary({
245                    match arg.format() {
246                        PgValueFormat::Binary => arg.as_bytes()?.to_owned(),
247                        PgValueFormat::Text => arg.as_str()?.as_bytes().to_vec(),
248                    }
249                })),
250            ),
251            PgType::Timetz => Timetz::decode(arg)?.into(),
252            PgType::Bit => Value::Ext(
253                "Bit",
254                Box::new(Value::Binary({
255                    match arg.format() {
256                        PgValueFormat::Binary => arg.as_bytes()?.to_owned(),
257                        PgValueFormat::Text => arg.as_str()?.as_bytes().to_vec(),
258                    }
259                })),
260            ),
261            PgType::Varbit => Value::Ext(
262                "Varbit",
263                Box::new(Value::Binary({
264                    match arg.format() {
265                        PgValueFormat::Binary => arg.as_bytes()?.to_owned(),
266                        PgValueFormat::Text => arg.as_str()?.as_bytes().to_vec(),
267                    }
268                })),
269            ),
270            PgType::Numeric => Decimal::decode(arg)?.into(),
271            PgType::Record => Value::Ext(
272                "Record",
273                Box::new(Value::Binary({
274                    match arg.format() {
275                        PgValueFormat::Binary => arg.as_bytes()?.to_owned(),
276                        PgValueFormat::Text => arg.as_str()?.as_bytes().to_vec(),
277                    }
278                })),
279            ),
280            PgType::Uuid => Uuid::decode(arg)?.into(),
281            PgType::Jsonb => decode_json(arg)?,
282            PgType::Tsvector => {
283                use crate::types::tsvector::TsVector;
284                TsVector::decode(arg)?.into()
285            }
286            PgType::Tsquery => {
287                use crate::types::tsquery::TsQuery;
288                TsQuery::decode(arg)?.into()
289            }
290            PgType::Hstore => {
291                use crate::types::hstore::Hstore;
292                Hstore::decode(arg)?.into()
293            }
294            PgType::HstoreArray => Value::Array(Decode::decode(arg)?),
295            PgType::Int4Range => Value::Ext(
296                "Int4Range",
297                Box::new(Value::Binary({
298                    match arg.format() {
299                        PgValueFormat::Binary => arg.as_bytes()?.to_owned(),
300                        PgValueFormat::Text => arg.as_str()?.as_bytes().to_vec(),
301                    }
302                })),
303            ),
304            PgType::NumRange => Value::Ext(
305                "NumRange",
306                Box::new(Value::Binary({
307                    match arg.format() {
308                        PgValueFormat::Binary => arg.as_bytes()?.to_owned(),
309                        PgValueFormat::Text => arg.as_str()?.as_bytes().to_vec(),
310                    }
311                })),
312            ),
313            PgType::TsRange => Value::Ext(
314                "TsRange",
315                Box::new(Value::Binary({
316                    match arg.format() {
317                        PgValueFormat::Binary => arg.as_bytes()?.to_owned(),
318                        PgValueFormat::Text => arg.as_str()?.as_bytes().to_vec(),
319                    }
320                })),
321            ),
322            PgType::TstzRange => Value::Ext(
323                "TstzRange",
324                Box::new(Value::Binary({
325                    match arg.format() {
326                        PgValueFormat::Binary => arg.as_bytes()?.to_owned(),
327                        PgValueFormat::Text => arg.as_str()?.as_bytes().to_vec(),
328                    }
329                })),
330            ),
331            PgType::DateRange => Value::Ext(
332                "DateRange",
333                Box::new(Value::Binary({
334                    match arg.format() {
335                        PgValueFormat::Binary => arg.as_bytes()?.to_owned(),
336                        PgValueFormat::Text => arg.as_str()?.as_bytes().to_vec(),
337                    }
338                })),
339            ),
340            PgType::Int8Range => Value::Ext(
341                "Int8Range",
342                Box::new(Value::Binary({
343                    match arg.format() {
344                        PgValueFormat::Binary => arg.as_bytes()?.to_owned(),
345                        PgValueFormat::Text => arg.as_str()?.as_bytes().to_vec(),
346                    }
347                })),
348            ),
349            PgType::Jsonpath => Value::Ext(
350                "Jsonpath",
351                Box::new(Value::Binary({
352                    match arg.format() {
353                        PgValueFormat::Binary => arg.as_bytes()?.to_owned(),
354                        PgValueFormat::Text => arg.as_str()?.as_bytes().to_vec(),
355                    }
356                })),
357            ),
358            PgType::Money => Money::decode(arg)?.into(),
359            PgType::Void => Value::Ext(
360                "Ext",
361                Box::new(Value::Binary({
362                    match arg.format() {
363                        PgValueFormat::Binary => arg.as_bytes()?.to_owned(),
364                        PgValueFormat::Text => arg.as_str()?.as_bytes().to_vec(),
365                    }
366                })),
367            ),
368            PgType::Custom(ref pg_custom_type) => match &pg_custom_type.kind {
369                PgTypeKind::Enum(_) => Value::String(Decode::decode(arg)?),
370                _ => Value::Ext(
371                    "Custom",
372                    Box::new(Value::Binary({
373                        match arg.format() {
374                            PgValueFormat::Binary => arg.as_bytes()?.to_owned(),
375                            PgValueFormat::Text => arg.as_str()?.as_bytes().to_vec(),
376                        }
377                    })),
378                ),
379            },
380            PgType::DeclareWithName(_) => Value::Ext(
381                "DeclareWithName",
382                Box::new(Value::Binary({
383                    match arg.format() {
384                        PgValueFormat::Binary => arg.as_bytes()?.to_owned(),
385                        PgValueFormat::Text => arg.as_str()?.as_bytes().to_vec(),
386                    }
387                })),
388            ),
389            PgType::DeclareWithOid(_) => Value::Ext(
390                "DeclareWithOid",
391                Box::new(Value::Binary({
392                    match arg.format() {
393                        PgValueFormat::Binary => arg.as_bytes()?.to_owned(),
394                        PgValueFormat::Text => arg.as_str()?.as_bytes().to_vec(),
395                    }
396                })),
397            ),
398            PgType::JsonArray => Value::Array(Decode::decode(arg)?),
399            PgType::LineArray => Value::Array(Decode::decode(arg)?),
400            PgType::CidrArray => Value::Array(Decode::decode(arg)?),
401            PgType::CircleArray => Value::Array(Decode::decode(arg)?),
402            PgType::Macaddr8Array => Value::Array(Decode::decode(arg)?),
403            PgType::BoolArray => Value::Array(Decode::decode(arg)?),
404            PgType::ByteaArray => Value::Array(Decode::decode(arg)?),
405            PgType::CharArray => Value::Array(Decode::decode(arg)?),
406            PgType::NameArray => Value::Array(Decode::decode(arg)?),
407            PgType::Int2Array => Value::Array(Decode::decode(arg)?),
408            PgType::Int4Array => Value::Array(Decode::decode(arg)?),
409            PgType::TextArray => Value::Array(Decode::decode(arg)?),
410            PgType::BpcharArray => Value::Array(Decode::decode(arg)?),
411            PgType::VarcharArray => Value::Array(Decode::decode(arg)?),
412            PgType::Int8Array => Value::Array(Decode::decode(arg)?),
413            PgType::PointArray => Value::Array(Decode::decode(arg)?),
414            PgType::LsegArray => Value::Array(Decode::decode(arg)?),
415            PgType::PathArray => Value::Array(Decode::decode(arg)?),
416            PgType::BoxArray => Value::Array(Decode::decode(arg)?),
417            PgType::Float4Array => Value::Array(Decode::decode(arg)?),
418            PgType::Float8Array => Value::Array(Decode::decode(arg)?),
419            PgType::PolygonArray => Value::Array(Decode::decode(arg)?),
420            PgType::OidArray => Value::Array(Decode::decode(arg)?),
421            PgType::MacaddrArray => Value::Array(Decode::decode(arg)?),
422            PgType::InetArray => Value::Array(Decode::decode(arg)?),
423            PgType::TimestampArray => Value::Array(Decode::decode(arg)?),
424            PgType::DateArray => Value::Array(Decode::decode(arg)?),
425            PgType::TimeArray => Value::Array(Decode::decode(arg)?),
426            PgType::TimestamptzArray => Value::Array(Decode::decode(arg)?),
427            PgType::IntervalArray => Value::Array(Decode::decode(arg)?),
428            PgType::NumericArray => Value::Array(Decode::decode(arg)?),
429            PgType::TimetzArray => Value::Array(Decode::decode(arg)?),
430            PgType::BitArray => Value::Array(Decode::decode(arg)?),
431            PgType::VarbitArray => Value::Array(Decode::decode(arg)?),
432            PgType::RecordArray => Value::Array(Decode::decode(arg)?),
433            PgType::UuidArray => Value::Array(Decode::decode(arg)?),
434            PgType::JsonbArray => Value::Array(Decode::decode(arg)?),
435            PgType::Int4RangeArray => Value::Array(Decode::decode(arg)?),
436            PgType::NumRangeArray => Value::Array(Decode::decode(arg)?),
437            PgType::TsRangeArray => Value::Array(Decode::decode(arg)?),
438            PgType::TstzRangeArray => Value::Array(Decode::decode(arg)?),
439            PgType::DateRangeArray => Value::Array(Decode::decode(arg)?),
440            PgType::Int8RangeArray => Value::Array(Decode::decode(arg)?),
441            PgType::JsonpathArray => Value::Array(Decode::decode(arg)?),
442            PgType::MoneyArray => Value::Array(Decode::decode(arg)?),
443        })
444    }
445}
446
447impl Encode for Value {
448    fn encode(self, buf: &mut PgArgumentBuffer) -> Result<IsNull, Error> {
449        Ok(match self {
450            Value::Null => IsNull::Yes,
451            Value::Bool(v) => v.encode(buf)?,
452            Value::I32(v) => v.encode(buf)?,
453            Value::I64(v) => v.encode(buf)?,
454            Value::U32(v) => v.encode(buf)?,
455            Value::U64(v) => v.encode(buf)?,
456            Value::F32(v) => v.encode(buf)?,
457            Value::F64(v) => v.encode(buf)?,
458            Value::String(v) => {
459                //default -> string
460                v.encode(buf)?
461            }
462            Value::Binary(v) => v.encode(buf)?,
463            Value::Array(v) => encode_json(Value::Array(v), buf)?,
464            Value::Map(v) => encode_json(Value::Map(v), buf)?,
465            Value::Ext(type_name, v) => {
466                match type_name {
467                    "Uuid" => Uuid(v.into_string().unwrap_or_default()).encode(buf)?,
468                    //decimal = 12345678
469                    "Decimal" => Decimal::from_str(v.as_str().unwrap_or_default())
470                        .unwrap_or_default()
471                        .encode(buf)?,
472                    //Date = "1993-02-06"
473                    "Date" => Date(
474                        fastdate::Date::from_str(&v.into_string().unwrap_or_default())
475                            .map_err(|e| Error::from(e.to_string()))?,
476                    )
477                    .encode(buf)?,
478                    //RFC3339NanoTime = "15:04:05.999999999"
479                    "Time" => Time(
480                        fastdate::Time::from_str(&v.into_string().unwrap_or_default())
481                            .map_err(|e| Error::from(e.to_string()))?,
482                    )
483                    .encode(buf)?,
484                    //RFC3339 = "2006-01-02 15:04:05.999999"
485                    "Timestamp" => Timestamp(v.as_i64().unwrap_or_default()).encode(buf)?,
486                    "DateTime" => DateTime(
487                        fastdate::DateTime::from_str(&v.into_string().unwrap_or_default())
488                            .map_err(|e| Error::from(e.to_string()))?,
489                    )
490                    .encode(buf)?,
491                    "Bytea" => v.as_slice().unwrap_or_default().encode(buf)?,
492                    "Char" => v.into_string().unwrap_or_default().encode(buf)?,
493                    "Name" => v.into_string().unwrap_or_default().encode(buf)?,
494                    "Int8" => (v.as_i64().unwrap_or_default() as i32).encode(buf)?,
495                    "Int2" => (v.as_i64().unwrap_or_default() as i8).encode(buf)?,
496                    "Int4" => (v.as_i64().unwrap_or_default() as i16).encode(buf)?,
497                    "Text" => v.into_string().unwrap_or_default().encode(buf)?,
498                    "Oid" => Oid::from(v.as_u64().unwrap_or_default() as u32).encode(buf)?,
499                    "Json" => Json(v.into_string().unwrap_or_default()).encode(buf)?,
500                    "Lseg" => v.into_bytes().unwrap_or_default().encode(buf)?,
501                    "Path" => v.into_bytes().unwrap_or_default().encode(buf)?,
502                    "Box" => v.into_bytes().unwrap_or_default().encode(buf)?,
503                    "Polygon" => v.into_bytes().unwrap_or_default().encode(buf)?,
504                    "Line" => v.into_bytes().unwrap_or_default().encode(buf)?,
505                    "Cidr" => v.into_bytes().unwrap_or_default().encode(buf)?,
506                    "Float4" => (v.as_f64().unwrap_or_default() as f32).encode(buf)?,
507                    "Float8" => v.as_f64().unwrap_or_default().encode(buf)?,
508                    "Unknown" => v.into_bytes().unwrap_or_default().encode(buf)?,
509                    "Circle" => v.into_bytes().unwrap_or_default().encode(buf)?,
510                    "Macaddr8" => v.into_bytes().unwrap_or_default().encode(buf)?,
511                    "Macaddr" => v.into_bytes().unwrap_or_default().encode(buf)?,
512                    "Inet" => v.into_bytes().unwrap_or_default().encode(buf)?,
513                    "Bpchar" => v.into_bytes().unwrap_or_default().encode(buf)?,
514                    "Varchar" => v.into_bytes().unwrap_or_default().encode(buf)?,
515                    "Timestamptz" => {
516                        let tz: Timestamptz = rbs::from_value(Value::Ext(type_name, v))?;
517                        tz.encode(buf)?
518                    }
519                    "Interval" => v.into_bytes().unwrap_or_default().encode(buf)?,
520                    "Timetz" => {
521                        Timetz(rbs::from_value(*v).map_err(|e| Error::from(e.to_string()))?)
522                            .encode(buf)?
523                    }
524                    "Bit" => v.into_bytes().unwrap_or_default().encode(buf)?,
525                    "Varbit" => v.into_bytes().unwrap_or_default().encode(buf)?,
526                    "Numeric" => Decimal::from_str(v.as_str().unwrap_or_default())
527                        .unwrap_or_default()
528                        .encode(buf)?,
529                    "Record" => v.into_bytes().unwrap_or_default().encode(buf)?,
530                    "Jsonb" => Json(v.into_string().unwrap_or_default()).encode(buf)?,
531                    "Int4Range" => v.into_bytes().unwrap_or_default().encode(buf)?,
532                    "NumRange" => v.into_bytes().unwrap_or_default().encode(buf)?,
533                    "TsRange" => v.into_bytes().unwrap_or_default().encode(buf)?,
534                    "TstzRange" => v.into_bytes().unwrap_or_default().encode(buf)?,
535                    "DateRange" => v.into_bytes().unwrap_or_default().encode(buf)?,
536                    "Int8Range" => v.into_bytes().unwrap_or_default().encode(buf)?,
537                    "Jsonpath" => v.into_bytes().unwrap_or_default().encode(buf)?,
538                    "Money" => Money(v.as_i64().unwrap_or_default()).encode(buf)?,
539                    "Void" => v.into_bytes().unwrap_or_default().encode(buf)?,
540                    "TsVector" => {
541                        use crate::types::tsvector::TsVector;
542                        let s = v.as_str().unwrap_or_default();
543                        TsVector(s.to_string()).encode(buf)?
544                    }
545                    "TsQuery" => {
546                        use crate::types::tsquery::TsQuery;
547                        let s = v.as_str().unwrap_or_default();
548                        TsQuery(s.to_string()).encode(buf)?
549                    }
550                    "Hstore" => {
551                        use crate::types::hstore::Hstore;
552                        let s = v.as_str().unwrap_or_default();
553                        // Parse hstore text format: "key1=>value1, key2=>value2"
554                        let mut map = std::collections::HashMap::new();
555                        for pair in s.split(',') {
556                            let pair = pair.trim();
557                            if let Some(pos) = pair.find("=>") {
558                                let key = pair[..pos].trim().to_string();
559                                let value = pair[pos + 2..].trim().to_string();
560                                map.insert(key, value);
561                            }
562                        }
563                        Hstore(map).encode(buf)?
564                    }
565                    "Point" => {
566                        use crate::types::point::Point;
567                        let s = v.as_str().unwrap_or_default();
568                        // Parse POINT(x y) format
569                        if let Some(start) = s.find('(') {
570                            if let Some(end) = s.find(')') {
571                                let coords = &s[start + 1..end];
572                                let parts: Vec<&str> = coords.split_whitespace().collect();
573                                if parts.len() == 2 {
574                                    let x = parts[0].parse::<f64>().unwrap_or(0.0);
575                                    let y = parts[1].parse::<f64>().unwrap_or(0.0);
576                                    Point { x, y }.encode(buf)?;
577                                }
578                            }
579                        }
580                        return Err(Error::from("Invalid POINT format"));
581                    }
582                    "Custom" => v.into_bytes().unwrap_or_default().encode(buf)?,
583                    "DeclareWithName" => v.into_bytes().unwrap_or_default().encode(buf)?,
584                    "DeclareWithOid" => v.into_bytes().unwrap_or_default().encode(buf)?,
585                    _ => IsNull::Yes,
586                }
587            }
588        })
589    }
590}