8
8
#include <ctype.h>
9
9
10
10
#include "crc32.h"
11
+ #include "libpq/pqformat.h"
11
12
#include "ltree.h"
12
13
#include "utils/memutils.h"
13
14
14
- PG_FUNCTION_INFO_V1 (ltree_in );
15
- PG_FUNCTION_INFO_V1 (ltree_out );
16
- PG_FUNCTION_INFO_V1 (lquery_in );
17
- PG_FUNCTION_INFO_V1 (lquery_out );
18
-
19
15
20
16
typedef struct
21
17
{
22
- char * start ;
18
+ const char * start ;
23
19
int len ; /* length in bytes */
24
20
int flag ;
25
21
int wlen ; /* length in characters */
@@ -28,11 +24,14 @@ typedef struct
28
24
#define LTPRS_WAITNAME 0
29
25
#define LTPRS_WAITDELIM 1
30
26
31
- Datum
32
- ltree_in (PG_FUNCTION_ARGS )
27
+ /*
28
+ * expects a null terminated string
29
+ * returns an ltree
30
+ */
31
+ static ltree *
32
+ parse_ltree (const char * buf )
33
33
{
34
- char * buf = (char * ) PG_GETARG_POINTER (0 );
35
- char * ptr ;
34
+ const char * ptr ;
36
35
nodeitem * list ,
37
36
* lptr ;
38
37
int num = 0 ,
@@ -141,15 +140,18 @@ ltree_in(PG_FUNCTION_ARGS)
141
140
}
142
141
143
142
pfree (list );
144
- PG_RETURN_POINTER ( result ) ;
143
+ return result ;
145
144
146
145
#undef UNCHAR
147
146
}
148
147
149
- Datum
150
- ltree_out (PG_FUNCTION_ARGS )
148
+ /*
149
+ * expects an ltree
150
+ * returns a null terminated string
151
+ */
152
+ static char *
153
+ deparse_ltree (const ltree * in )
151
154
{
152
- ltree * in = PG_GETARG_LTREE_P (0 );
153
155
char * buf ,
154
156
* ptr ;
155
157
int i ;
@@ -170,11 +172,84 @@ ltree_out(PG_FUNCTION_ARGS)
170
172
}
171
173
172
174
* ptr = '\0' ;
173
- PG_FREE_IF_COPY (in , 0 );
175
+ return buf ;
176
+ }
177
+
178
+ /*
179
+ * Basic ltree I/O functions
180
+ */
181
+ PG_FUNCTION_INFO_V1 (ltree_in );
182
+ Datum
183
+ ltree_in (PG_FUNCTION_ARGS )
184
+ {
185
+ char * buf = (char * ) PG_GETARG_POINTER (0 );
186
+
187
+ PG_RETURN_POINTER (parse_ltree (buf ));
188
+ }
189
+
190
+ PG_FUNCTION_INFO_V1 (ltree_out );
191
+ Datum
192
+ ltree_out (PG_FUNCTION_ARGS )
193
+ {
194
+ ltree * in = PG_GETARG_LTREE_P (0 );
195
+
196
+ PG_RETURN_POINTER (deparse_ltree (in ));
197
+ }
198
+
199
+ /*
200
+ * ltree type send function
201
+ *
202
+ * The type is sent as text in binary mode, so this is almost the same
203
+ * as the output function, but it's prefixed with a version number so we
204
+ * can change the binary format sent in future if necessary. For now,
205
+ * only version 1 is supported.
206
+ */
207
+ PG_FUNCTION_INFO_V1 (ltree_send );
208
+ Datum
209
+ ltree_send (PG_FUNCTION_ARGS )
210
+ {
211
+ ltree * in = PG_GETARG_LTREE_P (0 );
212
+ StringInfoData buf ;
213
+ int version = 1 ;
214
+ char * res = deparse_ltree (in );
215
+
216
+ pq_begintypsend (& buf );
217
+ pq_sendint8 (& buf , version );
218
+ pq_sendtext (& buf , res , strlen (res ));
219
+ pfree (res );
220
+
221
+ PG_RETURN_BYTEA_P (pq_endtypsend (& buf ));
222
+ }
223
+
224
+ /*
225
+ * ltree type recv function
226
+ *
227
+ * The type is sent as text in binary mode, so this is almost the same
228
+ * as the input function, but it's prefixed with a version number so we
229
+ * can change the binary format sent in future if necessary. For now,
230
+ * only version 1 is supported.
231
+ */
232
+ PG_FUNCTION_INFO_V1 (ltree_recv );
233
+ Datum
234
+ ltree_recv (PG_FUNCTION_ARGS )
235
+ {
236
+ StringInfo buf = (StringInfo ) PG_GETARG_POINTER (0 );
237
+ int version = pq_getmsgint (buf , 1 );
238
+ char * str ;
239
+ int nbytes ;
240
+ ltree * res ;
174
241
175
- PG_RETURN_POINTER (buf );
242
+ if (version != 1 )
243
+ elog (ERROR , "unsupported ltree version number %d" , version );
244
+
245
+ str = pq_getmsgtext (buf , buf -> len - buf -> cursor , & nbytes );
246
+ res = parse_ltree (str );
247
+ pfree (str );
248
+
249
+ PG_RETURN_POINTER (res );
176
250
}
177
251
252
+
178
253
#define LQPRS_WAITLEVEL 0
179
254
#define LQPRS_WAITDELIM 1
180
255
#define LQPRS_WAITOPEN 2
@@ -190,11 +265,14 @@ ltree_out(PG_FUNCTION_ARGS)
190
265
#define ITEMSIZE MAXALIGN(LQL_HDRSIZE+sizeof(nodeitem*))
191
266
#define NEXTLEV (x ) ( (lquery_level*)( ((char*)(x)) + ITEMSIZE) )
192
267
193
- Datum
194
- lquery_in (PG_FUNCTION_ARGS )
268
+ /*
269
+ * expects a null terminated string
270
+ * returns an lquery
271
+ */
272
+ static lquery *
273
+ parse_lquery (const char * buf )
195
274
{
196
- char * buf = (char * ) PG_GETARG_POINTER (0 );
197
- char * ptr ;
275
+ const char * ptr ;
198
276
int num = 0 ,
199
277
totallen = 0 ,
200
278
numOR = 0 ;
@@ -563,15 +641,18 @@ lquery_in(PG_FUNCTION_ARGS)
563
641
}
564
642
565
643
pfree (tmpql );
566
- PG_RETURN_POINTER ( result ) ;
644
+ return result ;
567
645
568
646
#undef UNCHAR
569
647
}
570
648
571
- Datum
572
- lquery_out (PG_FUNCTION_ARGS )
649
+ /*
650
+ * expects an lquery
651
+ * returns a null terminated string
652
+ */
653
+ static char *
654
+ deparse_lquery (const lquery * in )
573
655
{
574
- lquery * in = PG_GETARG_LQUERY_P (0 );
575
656
char * buf ,
576
657
* ptr ;
577
658
int i ,
@@ -679,7 +760,79 @@ lquery_out(PG_FUNCTION_ARGS)
679
760
}
680
761
681
762
* ptr = '\0' ;
682
- PG_FREE_IF_COPY (in , 0 );
763
+ return buf ;
764
+ }
765
+
766
+ /*
767
+ * Basic lquery I/O functions
768
+ */
769
+ PG_FUNCTION_INFO_V1 (lquery_in );
770
+ Datum
771
+ lquery_in (PG_FUNCTION_ARGS )
772
+ {
773
+ char * buf = (char * ) PG_GETARG_POINTER (0 );
774
+
775
+ PG_RETURN_POINTER (parse_lquery (buf ));
776
+ }
777
+
778
+ PG_FUNCTION_INFO_V1 (lquery_out );
779
+ Datum
780
+ lquery_out (PG_FUNCTION_ARGS )
781
+ {
782
+ lquery * in = PG_GETARG_LQUERY_P (0 );
783
+
784
+ PG_RETURN_POINTER (deparse_lquery (in ));
785
+ }
786
+
787
+ /*
788
+ * lquery type send function
789
+ *
790
+ * The type is sent as text in binary mode, so this is almost the same
791
+ * as the output function, but it's prefixed with a version number so we
792
+ * can change the binary format sent in future if necessary. For now,
793
+ * only version 1 is supported.
794
+ */
795
+ PG_FUNCTION_INFO_V1 (lquery_send );
796
+ Datum
797
+ lquery_send (PG_FUNCTION_ARGS )
798
+ {
799
+ lquery * in = PG_GETARG_LQUERY_P (0 );
800
+ StringInfoData buf ;
801
+ int version = 1 ;
802
+ char * res = deparse_lquery (in );
803
+
804
+ pq_begintypsend (& buf );
805
+ pq_sendint8 (& buf , version );
806
+ pq_sendtext (& buf , res , strlen (res ));
807
+ pfree (res );
808
+
809
+ PG_RETURN_BYTEA_P (pq_endtypsend (& buf ));
810
+ }
811
+
812
+ /*
813
+ * lquery type recv function
814
+ *
815
+ * The type is sent as text in binary mode, so this is almost the same
816
+ * as the input function, but it's prefixed with a version number so we
817
+ * can change the binary format sent in future if necessary. For now,
818
+ * only version 1 is supported.
819
+ */
820
+ PG_FUNCTION_INFO_V1 (lquery_recv );
821
+ Datum
822
+ lquery_recv (PG_FUNCTION_ARGS )
823
+ {
824
+ StringInfo buf = (StringInfo ) PG_GETARG_POINTER (0 );
825
+ int version = pq_getmsgint (buf , 1 );
826
+ char * str ;
827
+ int nbytes ;
828
+ lquery * res ;
829
+
830
+ if (version != 1 )
831
+ elog (ERROR , "unsupported lquery version number %d" , version );
832
+
833
+ str = pq_getmsgtext (buf , buf -> len - buf -> cursor , & nbytes );
834
+ res = parse_lquery (str );
835
+ pfree (str );
683
836
684
- PG_RETURN_POINTER (buf );
837
+ PG_RETURN_POINTER (res );
685
838
}
0 commit comments