1010import java .io .IOException ;
1111import java .math .BigDecimal ;
1212import java .math .BigInteger ;
13+ import java .net .Inet4Address ;
14+ import java .net .InetAddress ;
1315import java .nio .charset .StandardCharsets ;
1416import java .sql .Connection ;
1517import java .sql .SQLException ;
@@ -31,6 +33,16 @@ public interface ToShortFunction<T> {
3133 short applyAsShort (T value );
3234 }
3335
36+ // Geometric Types
37+ public record PgPoint (double x , double y ) {}
38+ public record PgLine (double a , double b , double c ) {}
39+ public record PgLseg (PgPoint p1 , PgPoint p2 ) {}
40+ public record PgBox (PgPoint p1 , PgPoint p2 ) {}
41+ public record PgPath (boolean closed , List <PgPoint > points ) {}
42+ public record PgPolygon (List <PgPoint > points ) {}
43+ public record PgCircle (PgPoint center , double radius ) {}
44+
45+
3446 public record PgRange <T >(T lower , T upper , boolean lowerInclusive , boolean upperInclusive , boolean lowerInfinite ,
3547 boolean upperInfinite , boolean empty ) {
3648 public static <T > PgRange <T > emptyRange () {
@@ -114,8 +126,23 @@ public interface BinaryRowWriter {
114126
115127 void writeHstore (Map <String , String > v ) throws IOException ;
116128
129+ // Network
130+ void writeInet (InetAddress v ) throws IOException ;
131+ void writeMacAddress (String v ) throws IOException ;
132+
133+ // Geometry
134+ void writePoint (PgPoint v ) throws IOException ;
135+ void writeLine (PgLine v ) throws IOException ;
136+ void writeLseg (PgLseg v ) throws IOException ;
137+ void writeBox (PgBox v ) throws IOException ;
138+ void writePath (PgPath v ) throws IOException ;
139+ void writePolygon (PgPolygon v ) throws IOException ;
140+ void writeCircle (PgCircle v ) throws IOException ;
141+
142+ // Arrays
117143 <E > void writeArray (Collection <?> elements , PgType <E > baseElementType ) throws IOException ;
118144
145+ // Ranges
119146 <E > void writeRange (PgRange <E > range , PgType <E > elementType ) throws IOException ;
120147 }
121148
@@ -297,15 +324,54 @@ public void writeHstore(Map<String, String> v) throws IOException {
297324 }
298325 }
299326
327+ @ Override public void writeInet (InetAddress v ) throws IOException {
328+ byte [] addr = v .getAddress ();
329+ out .writeInt (addr .length + 4 );
330+ out .writeByte (v instanceof Inet4Address ? 2 : 3 ); // PGSQL_AF_INET or INET6
331+ out .writeByte (addr .length * 8 ); // mask
332+ out .writeByte (0 ); // is_res
333+ out .writeByte (addr .length );
334+ out .write (addr );
335+ }
336+
337+ @ Override public void writeMacAddress (String v ) throws IOException {
338+ String [] hex = v .split ("[:-]" );
339+ out .writeInt (6 );
340+ for (String s : hex ) out .writeByte (Integer .parseInt (s , 16 ));
341+ }
342+
343+ @ Override public void writePoint (PgPoint v ) throws IOException { out .writeInt (16 ); out .writeDouble (v .x ()); out .writeDouble (v .y ()); }
344+
345+ @ Override public void writeLine (PgLine v ) throws IOException { out .writeInt (24 ); out .writeDouble (v .a ()); out .writeDouble (v .b ()); out .writeDouble (v .c ()); }
346+
347+ @ Override public void writeLseg (PgLseg v ) throws IOException { out .writeInt (32 ); writePointInternal (v .p1 ()); writePointInternal (v .p2 ()); }
348+
349+ @ Override public void writeBox (PgBox v ) throws IOException { out .writeInt (32 ); writePointInternal (v .p1 ()); writePointInternal (v .p2 ()); }
350+
351+ @ Override public void writePath (PgPath v ) throws IOException {
352+ out .writeInt (1 + 4 + (v .points ().size () * 16 ));
353+ out .writeByte (v .closed () ? 1 : 0 );
354+ out .writeInt (v .points ().size ());
355+ for (PgPoint p : v .points ()) writePointInternal (p );
356+ }
357+
358+ @ Override public void writePolygon (PgPolygon v ) throws IOException {
359+ out .writeInt (4 + (v .points ().size () * 16 ));
360+ out .writeInt (v .points ().size ());
361+ for (PgPoint p : v .points ()) writePointInternal (p );
362+ }
363+
364+ @ Override public void writeCircle (PgCircle v ) throws IOException { out .writeInt (24 ); writePointInternal (v .center ()); out .writeDouble (v .radius ()); }
365+
366+ private void writePointInternal (PgPoint p ) throws IOException { out .writeDouble (p .x ()); out .writeDouble (p .y ()); }
300367
301368 @ Override public <E > void writeArray (Collection <?> elements , PgType <E > baseElementType ) throws IOException {
302369 if (elements == null ) { writeNull (); return ; }
303370
304371 // Determine dimensions
305372 List <Integer > dims = new ArrayList <>();
306373 Object current = elements ;
307- while (current instanceof Collection ) {
308- Collection <?> c = (Collection <?>) current ;
374+ while (current instanceof Collection <?> c ) {
309375 dims .add (c .size ());
310376 if (c .isEmpty ()) break ;
311377 current = c .iterator ().next ();
@@ -685,6 +751,24 @@ public void write(BinaryRowWriter w, Instant v) throws IOException {
685751 }
686752 };
687753
754+ // Geometry
755+ public static final PgType <PgPoint > POINT = createType (600 , BinaryRowWriter ::writePoint );
756+ public static final PgType <PgLine > LINE = createType (628 , BinaryRowWriter ::writeLine );
757+ public static final PgType <PgLseg > LSEG = createType (601 , BinaryRowWriter ::writeLseg );
758+ public static final PgType <PgBox > BOX = createType (603 , BinaryRowWriter ::writeBox );
759+ public static final PgType <PgPath > PATH = createType (602 , BinaryRowWriter ::writePath );
760+ public static final PgType <PgPolygon > POLYGON = createType (604 , BinaryRowWriter ::writePolygon );
761+ public static final PgType <PgCircle > CIRCLE = createType (718 , BinaryRowWriter ::writeCircle );
762+
763+ // Ranges
764+ public static final PgType <PgRange <Integer >> INT4RANGE = createType (3904 , (w , v ) -> w .writeRange (v , INT4 ));
765+ public static final PgType <PgRange <Long >> INT8RANGE = createType (3926 , (w , v ) -> w .writeRange (v , INT8 ));
766+ public static final PgType <PgRange <BigDecimal >> NUMRANGE = createType (3906 , (w , v ) -> w .writeRange (v , NUMERIC ));
767+ public static final PgType <PgRange <LocalDateTime >> TSRANGE = createType (3908 , (w , v ) -> w .writeRange (v , TIMESTAMP ));
768+ public static final PgType <PgRange <Instant >> TSTZRANGE = createType (3910 , (w , v ) -> w .writeRange (v , TIMESTAMPTZ ));
769+ public static final PgType <PgRange <LocalDate >> DATERANGE = createType (3912 , (w , v ) -> w .writeRange (v , DATE ));
770+
771+ // Arrays
688772 public static <E > PgType <Collection <E >> array (PgType <E > baseType ) {
689773 return createType (0 , (w , v ) -> w .writeArray (v , baseType ));
690774 }
0 commit comments