@@ -136,10 +136,20 @@ const (
136
136
jsonArrayKeyDescendingMarker = jsonTrueKeyDescendingMarker - 1
137
137
jsonObjectKeyDescendingMarker = jsonArrayKeyDescendingMarker - 1
138
138
139
+ // LTREE key encoding markers
140
+ ltreeKeyMarker = jsonEmptyArrayKeyDescendingMarker + 1
141
+ ltreeKeyDescendingMarker = ltreeKeyMarker + 1
142
+
139
143
// Terminators for JSON Key encoding.
140
144
jsonKeyTerminator byte = 0x00
141
145
jsonKeyDescendingTerminator byte = 0xFF
142
146
147
+ // Terminators for LTREE Key encoding.
148
+ ltreeKeyTerminator byte = 0x00
149
+ ltreeKeyDescendingTerminator byte = 0xFF
150
+ ltreeLabelKeyTerminator byte = 0x01
151
+ ltreeLabelKeyDescendingTerminator byte = 0xFE
152
+
143
153
// IntMin is chosen such that the range of int tags does not overlap the
144
154
// ascii character set that is frequently used in testing.
145
155
IntMin = 0x80 // 128
@@ -863,6 +873,20 @@ func getBytesLength(b []byte, e escapes) (int, error) {
863
873
}
864
874
}
865
875
876
+ // getLTreeLength finds the length of a ltree encoding.
877
+ func getLTreeLength (b []byte , dir Direction ) (int , error ) {
878
+ var i int
879
+ if dir == Ascending {
880
+ i = bytes .IndexByte (b , ltreeKeyTerminator )
881
+ } else {
882
+ i = bytes .IndexByte (b , ltreeKeyDescendingTerminator )
883
+ }
884
+ if i == - 1 {
885
+ return 0 , errors .Errorf ("did not find terminator" )
886
+ }
887
+ return i + 1 , nil
888
+ }
889
+
866
890
// prettyPrintInvertedIndexKey returns a string representation of the path part of a JSON inverted
867
891
// index.
868
892
func prettyPrintInvertedIndexKey (b []byte ) (string , []byte , error ) {
@@ -1726,6 +1750,101 @@ func DecodeBitArrayDescending(b []byte) ([]byte, bitarray.BitArray, error) {
1726
1750
return b , ba , err
1727
1751
}
1728
1752
1753
+ // EncodeLTreeAscending encodes a ltree.T value, appends it to the
1754
+ // supplied buffer, and returns the final buffer. The encoding is guaranteed to
1755
+ // be ordered such that if t1 < t2 then bytes.Compare will order them the same
1756
+ // way after encoding.
1757
+ //
1758
+ // The encoding is in the below format:
1759
+ // [ ltreeMarker ]
1760
+ // for each label:
1761
+ //
1762
+ // [ label raw bytes ] [ ltreeLabelKeyTerminator ]
1763
+ //
1764
+ // [ ltreeKeyTerminator ]
1765
+ func EncodeLTreeAscending (b []byte , d ltree.T ) []byte {
1766
+ b = append (b , ltreeKeyMarker )
1767
+ d .ForEachLabel (func (i int , label string ) {
1768
+ b = append (b , []byte (label )... )
1769
+ b = append (b , ltreeLabelKeyTerminator )
1770
+ })
1771
+ b = append (b , ltreeKeyTerminator )
1772
+ return b
1773
+ }
1774
+
1775
+ // EncodeLTreeDescending is the descending version of EncodeLTreeAscending.
1776
+ func EncodeLTreeDescending (b []byte , d ltree.T ) []byte {
1777
+ b = append (b , ltreeKeyDescendingMarker )
1778
+ d .ForEachLabel (func (i int , label string ) {
1779
+ n := len (b )
1780
+ b = append (b , []byte (label )... )
1781
+ onesComplement (b [n :])
1782
+ b = append (b , ltreeLabelKeyDescendingTerminator )
1783
+ })
1784
+ b = append (b , ltreeKeyDescendingTerminator )
1785
+ return b
1786
+ }
1787
+
1788
+ // DecodeLTreeAscending decodes a ltree.T value which was encoded using
1789
+ // EncodeLTreeAscending. The remainder of the input buffer and the
1790
+ // decoded ltree.T are returned.
1791
+ func DecodeLTreeAscending (b []byte ) ([]byte , ltree.T , error ) {
1792
+ if PeekType (b ) != LTree {
1793
+ return nil , ltree .Empty , errors .Errorf ("did not find marker %#x" , b )
1794
+ }
1795
+ b = b [1 :]
1796
+
1797
+ var labels []string
1798
+ for {
1799
+ if len (b ) != 0 && b [0 ] == ltreeKeyTerminator {
1800
+ b = b [1 :]
1801
+ break
1802
+ }
1803
+ i := bytes .IndexByte (b , ltreeLabelKeyTerminator )
1804
+ if i == - 1 {
1805
+ return nil , ltree .Empty , errors .Errorf ("malformed ltree encoding" )
1806
+ }
1807
+ labels = append (labels , string (b [:i ]))
1808
+ b = b [i + 1 :]
1809
+ }
1810
+ l , err := ltree .ParseLTreeFromLabels (labels )
1811
+ if err != nil {
1812
+ return nil , ltree .Empty , err
1813
+ }
1814
+ return b , l , nil
1815
+ }
1816
+
1817
+ // DecodeLTreeDescending is the descending version of DecodeLTreeAscending.
1818
+ func DecodeLTreeDescending (b []byte ) ([]byte , ltree.T , error ) {
1819
+ if PeekType (b ) != LTreeDesc {
1820
+ return nil , ltree .Empty , errors .Errorf ("did not find marker %#x" , b )
1821
+ }
1822
+ b = b [1 :]
1823
+
1824
+ var labels []string
1825
+ for {
1826
+ if len (b ) != 0 && b [0 ] == ltreeKeyDescendingTerminator {
1827
+ b = b [1 :]
1828
+ break
1829
+ }
1830
+ i := bytes .IndexByte (b , ltreeLabelKeyDescendingTerminator )
1831
+ if i == - 1 {
1832
+ return nil , ltree .Empty , errors .Errorf ("malformed ltree encoding" )
1833
+ }
1834
+ // Deep copying here is necessary to avoid modifying the input buffer slice.
1835
+ var label []byte
1836
+ label = append (label , b [:i ]... )
1837
+ onesComplement (label )
1838
+ labels = append (labels , string (label ))
1839
+ b = b [i + 1 :]
1840
+ }
1841
+ l , err := ltree .ParseLTreeFromLabels (labels )
1842
+ if err != nil {
1843
+ return nil , ltree .Empty , err
1844
+ }
1845
+ return b , l , nil
1846
+ }
1847
+
1729
1848
// Type represents the type of a value encoded by
1730
1849
// Encode{Null,NotNull,Varint,Uvarint,Float,Bytes}.
1731
1850
//
@@ -1788,6 +1907,7 @@ const (
1788
1907
JsonEmptyArrayDesc Type = 43
1789
1908
PGVector Type = 44
1790
1909
LTree Type = 45
1910
+ LTreeDesc Type = 46
1791
1911
)
1792
1912
1793
1913
// typMap maps an encoded type byte to a decoded Type. It's got 256 slots, one
@@ -1890,6 +2010,10 @@ func slowPeekType(b []byte) Type {
1890
2010
return Decimal
1891
2011
case m == voidMarker :
1892
2012
return Void
2013
+ case m == ltreeKeyMarker :
2014
+ return LTree
2015
+ case m == ltreeKeyDescendingMarker :
2016
+ return LTreeDesc
1893
2017
}
1894
2018
}
1895
2019
return Unknown
@@ -2086,6 +2210,10 @@ func PeekLength(b []byte) (int, error) {
2086
2210
return 0 , errors .Errorf ("slice too short for float (%d)" , len (b ))
2087
2211
}
2088
2212
return 9 , nil
2213
+ case ltreeKeyMarker :
2214
+ return getLTreeLength (b , Ascending )
2215
+ case ltreeKeyDescendingMarker :
2216
+ return getLTreeLength (b , Descending )
2089
2217
}
2090
2218
if m >= IntMin && m <= IntMax {
2091
2219
return getVarintLen (b )
@@ -2384,6 +2512,26 @@ func prettyPrintFirstValue(dir Direction, b []byte) ([]byte, string, error) {
2384
2512
return b , "" , err
2385
2513
}
2386
2514
return b , d .StringNanos (), nil
2515
+ case LTree :
2516
+ if dir == Descending {
2517
+ return b , "" , errors .Errorf ("ascending ltree column dir but descending ltree encoding" )
2518
+ }
2519
+ var l ltree.T
2520
+ b , l , err = DecodeLTreeAscending (b )
2521
+ if err != nil {
2522
+ return b , "" , err
2523
+ }
2524
+ return b , l .String (), nil
2525
+ case LTreeDesc :
2526
+ if dir == Ascending {
2527
+ return b , "" , errors .Errorf ("descending ltree column dir but ascending ltree encoding" )
2528
+ }
2529
+ var l ltree.T
2530
+ b , l , err = DecodeLTreeDescending (b )
2531
+ if err != nil {
2532
+ return b , "" , err
2533
+ }
2534
+ return b , l .String (), nil
2387
2535
default :
2388
2536
if len (b ) >= 1 {
2389
2537
switch b [0 ] {
0 commit comments