2 * contrib/hstore/hstore_op.c
6 #include "access/htup_details.h"
7 #include "catalog/pg_type.h"
8 #include "common/hashfn.h"
11 #include "utils/builtins.h"
12 #include "utils/memutils.h"
14 /* old names for C functions */
15 HSTORE_POLLUTE(hstore_fetchval
, fetchval
);
16 HSTORE_POLLUTE(hstore_exists
, exists
);
17 HSTORE_POLLUTE(hstore_defined
, defined
);
18 HSTORE_POLLUTE(hstore_delete
, delete);
19 HSTORE_POLLUTE(hstore_concat
, hs_concat
);
20 HSTORE_POLLUTE(hstore_contains
, hs_contains
);
21 HSTORE_POLLUTE(hstore_contained
, hs_contained
);
22 HSTORE_POLLUTE(hstore_akeys
, akeys
);
23 HSTORE_POLLUTE(hstore_avals
, avals
);
24 HSTORE_POLLUTE(hstore_skeys
, skeys
);
25 HSTORE_POLLUTE(hstore_svals
, svals
);
26 HSTORE_POLLUTE(hstore_each
, each
);
30 * We're often finding a sequence of keys in ascending order. The
31 * "lowbound" parameter is used to cache lower bounds of searches
32 * between calls, based on this assumption. Pass NULL for it for
33 * one-off or unordered searches.
36 hstoreFindKey(HStore
*hs
, int *lowbound
, char *key
, int keylen
)
38 HEntry
*entries
= ARRPTR(hs
);
39 int stopLow
= lowbound
? *lowbound
: 0;
40 int stopHigh
= HS_COUNT(hs
);
42 char *base
= STRPTR(hs
);
44 while (stopLow
< stopHigh
)
48 stopMiddle
= stopLow
+ (stopHigh
- stopLow
) / 2;
50 if (HSTORE_KEYLEN(entries
, stopMiddle
) == keylen
)
51 difference
= memcmp(HSTORE_KEY(entries
, base
, stopMiddle
), key
, keylen
);
53 difference
= (HSTORE_KEYLEN(entries
, stopMiddle
) > keylen
) ? 1 : -1;
58 *lowbound
= stopMiddle
+ 1;
61 else if (difference
< 0)
62 stopLow
= stopMiddle
+ 1;
64 stopHigh
= stopMiddle
;
73 hstoreArrayToPairs(ArrayType
*a
, int *npairs
)
83 deconstruct_array_builtin(a
, TEXTOID
, &key_datums
, &key_nulls
, &key_count
);
92 * A text array uses at least eight bytes per element, so any overflow in
93 * "key_count * sizeof(Pairs)" is small enough for palloc() to catch.
94 * However, credible improvements to the array format could invalidate
95 * that assumption. Therefore, use an explicit check rather than relying
96 * on palloc() to complain.
98 if (key_count
> MaxAllocSize
/ sizeof(Pairs
))
100 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED
),
101 errmsg("number of pairs (%d) exceeds the maximum allowed (%d)",
102 key_count
, (int) (MaxAllocSize
/ sizeof(Pairs
)))));
104 key_pairs
= palloc(sizeof(Pairs
) * key_count
);
106 for (i
= 0, j
= 0; i
< key_count
; i
++)
110 key_pairs
[j
].key
= VARDATA(key_datums
[i
]);
111 key_pairs
[j
].keylen
= VARSIZE(key_datums
[i
]) - VARHDRSZ
;
112 key_pairs
[j
].val
= NULL
;
113 key_pairs
[j
].vallen
= 0;
114 key_pairs
[j
].needfree
= 0;
115 key_pairs
[j
].isnull
= 1;
120 *npairs
= hstoreUniquePairs(key_pairs
, j
, &bufsiz
);
126 PG_FUNCTION_INFO_V1(hstore_fetchval
);
128 hstore_fetchval(PG_FUNCTION_ARGS
)
130 HStore
*hs
= PG_GETARG_HSTORE_P(0);
131 text
*key
= PG_GETARG_TEXT_PP(1);
132 HEntry
*entries
= ARRPTR(hs
);
134 int idx
= hstoreFindKey(hs
, NULL
,
135 VARDATA_ANY(key
), VARSIZE_ANY_EXHDR(key
));
137 if (idx
< 0 || HSTORE_VALISNULL(entries
, idx
))
140 out
= cstring_to_text_with_len(HSTORE_VAL(entries
, STRPTR(hs
), idx
),
141 HSTORE_VALLEN(entries
, idx
));
143 PG_RETURN_TEXT_P(out
);
147 PG_FUNCTION_INFO_V1(hstore_exists
);
149 hstore_exists(PG_FUNCTION_ARGS
)
151 HStore
*hs
= PG_GETARG_HSTORE_P(0);
152 text
*key
= PG_GETARG_TEXT_PP(1);
153 int idx
= hstoreFindKey(hs
, NULL
,
154 VARDATA_ANY(key
), VARSIZE_ANY_EXHDR(key
));
156 PG_RETURN_BOOL(idx
>= 0);
160 PG_FUNCTION_INFO_V1(hstore_exists_any
);
162 hstore_exists_any(PG_FUNCTION_ARGS
)
164 HStore
*hs
= PG_GETARG_HSTORE_P(0);
165 ArrayType
*keys
= PG_GETARG_ARRAYTYPE_P(1);
167 Pairs
*key_pairs
= hstoreArrayToPairs(keys
, &nkeys
);
173 * we exploit the fact that the pairs list is already sorted into strictly
174 * increasing order to narrow the hstoreFindKey search; each search can
175 * start one entry past the previous "found" entry, or at the lower bound
176 * of the last search.
178 for (i
= 0; i
< nkeys
; i
++)
180 int idx
= hstoreFindKey(hs
, &lowbound
,
181 key_pairs
[i
].key
, key_pairs
[i
].keylen
);
194 PG_FUNCTION_INFO_V1(hstore_exists_all
);
196 hstore_exists_all(PG_FUNCTION_ARGS
)
198 HStore
*hs
= PG_GETARG_HSTORE_P(0);
199 ArrayType
*keys
= PG_GETARG_ARRAYTYPE_P(1);
201 Pairs
*key_pairs
= hstoreArrayToPairs(keys
, &nkeys
);
207 * we exploit the fact that the pairs list is already sorted into strictly
208 * increasing order to narrow the hstoreFindKey search; each search can
209 * start one entry past the previous "found" entry, or at the lower bound
210 * of the last search.
212 for (i
= 0; i
< nkeys
; i
++)
214 int idx
= hstoreFindKey(hs
, &lowbound
,
215 key_pairs
[i
].key
, key_pairs
[i
].keylen
);
228 PG_FUNCTION_INFO_V1(hstore_defined
);
230 hstore_defined(PG_FUNCTION_ARGS
)
232 HStore
*hs
= PG_GETARG_HSTORE_P(0);
233 text
*key
= PG_GETARG_TEXT_PP(1);
234 HEntry
*entries
= ARRPTR(hs
);
235 int idx
= hstoreFindKey(hs
, NULL
,
236 VARDATA_ANY(key
), VARSIZE_ANY_EXHDR(key
));
237 bool res
= (idx
>= 0 && !HSTORE_VALISNULL(entries
, idx
));
243 PG_FUNCTION_INFO_V1(hstore_delete
);
245 hstore_delete(PG_FUNCTION_ARGS
)
247 HStore
*hs
= PG_GETARG_HSTORE_P(0);
248 text
*key
= PG_GETARG_TEXT_PP(1);
249 char *keyptr
= VARDATA_ANY(key
);
250 int keylen
= VARSIZE_ANY_EXHDR(key
);
251 HStore
*out
= palloc(VARSIZE(hs
));
258 int count
= HS_COUNT(hs
);
261 SET_VARSIZE(out
, VARSIZE(hs
));
262 HS_SETCOUNT(out
, count
); /* temporary! */
266 bufd
= ptrd
= STRPTR(out
);
269 for (i
= 0; i
< count
; ++i
)
271 int len
= HSTORE_KEYLEN(es
, i
);
272 char *ptrs
= HSTORE_KEY(es
, bufs
, i
);
274 if (!(len
== keylen
&& memcmp(ptrs
, keyptr
, keylen
) == 0))
276 int vallen
= HSTORE_VALLEN(es
, i
);
278 HS_COPYITEM(ed
, bufd
, ptrd
, ptrs
, len
, vallen
,
279 HSTORE_VALISNULL(es
, i
));
284 HS_FINALIZE(out
, outcount
, bufd
, ptrd
);
286 PG_RETURN_POINTER(out
);
290 PG_FUNCTION_INFO_V1(hstore_delete_array
);
292 hstore_delete_array(PG_FUNCTION_ARGS
)
294 HStore
*hs
= PG_GETARG_HSTORE_P(0);
295 HStore
*out
= palloc(VARSIZE(hs
));
296 int hs_count
= HS_COUNT(hs
);
305 ArrayType
*key_array
= PG_GETARG_ARRAYTYPE_P(1);
307 Pairs
*key_pairs
= hstoreArrayToPairs(key_array
, &nkeys
);
309 SET_VARSIZE(out
, VARSIZE(hs
));
310 HS_SETCOUNT(out
, hs_count
); /* temporary! */
314 bufd
= pd
= STRPTR(out
);
319 /* return a copy of the input, unchanged */
320 memcpy(out
, hs
, VARSIZE(hs
));
321 HS_FIXSIZE(out
, hs_count
);
322 HS_SETCOUNT(out
, hs_count
);
323 PG_RETURN_POINTER(out
);
327 * this is in effect a merge between hs and key_pairs, both of which are
328 * already sorted by (keylen,key); we take keys from hs only
331 for (i
= j
= 0; i
< hs_count
;)
339 int skeylen
= HSTORE_KEYLEN(es
, i
);
341 if (skeylen
== key_pairs
[j
].keylen
)
342 difference
= memcmp(HSTORE_KEY(es
, ps
, i
),
344 key_pairs
[j
].keylen
);
346 difference
= (skeylen
> key_pairs
[j
].keylen
) ? 1 : -1;
351 else if (difference
== 0)
355 HS_COPYITEM(ed
, bufd
, pd
,
356 HSTORE_KEY(es
, ps
, i
), HSTORE_KEYLEN(es
, i
),
357 HSTORE_VALLEN(es
, i
), HSTORE_VALISNULL(es
, i
));
363 HS_FINALIZE(out
, outcount
, bufd
, pd
);
365 PG_RETURN_POINTER(out
);
369 PG_FUNCTION_INFO_V1(hstore_delete_hstore
);
371 hstore_delete_hstore(PG_FUNCTION_ARGS
)
373 HStore
*hs
= PG_GETARG_HSTORE_P(0);
374 HStore
*hs2
= PG_GETARG_HSTORE_P(1);
375 HStore
*out
= palloc(VARSIZE(hs
));
376 int hs_count
= HS_COUNT(hs
);
377 int hs2_count
= HS_COUNT(hs2
);
389 SET_VARSIZE(out
, VARSIZE(hs
));
390 HS_SETCOUNT(out
, hs_count
); /* temporary! */
396 bufd
= pd
= STRPTR(out
);
401 /* return a copy of the input, unchanged */
402 memcpy(out
, hs
, VARSIZE(hs
));
403 HS_FIXSIZE(out
, hs_count
);
404 HS_SETCOUNT(out
, hs_count
);
405 PG_RETURN_POINTER(out
);
409 * this is in effect a merge between hs and hs2, both of which are already
410 * sorted by (keylen,key); we take keys from hs only; for equal keys, we
411 * take the value from hs unless the values are equal
414 for (i
= j
= 0; i
< hs_count
;)
422 int skeylen
= HSTORE_KEYLEN(es
, i
);
423 int s2keylen
= HSTORE_KEYLEN(es2
, j
);
425 if (skeylen
== s2keylen
)
426 difference
= memcmp(HSTORE_KEY(es
, ps
, i
),
427 HSTORE_KEY(es2
, ps2
, j
),
430 difference
= (skeylen
> s2keylen
) ? 1 : -1;
435 else if (difference
== 0)
437 int svallen
= HSTORE_VALLEN(es
, i
);
438 int snullval
= HSTORE_VALISNULL(es
, i
);
440 if (snullval
!= HSTORE_VALISNULL(es2
, j
) ||
441 (!snullval
&& (svallen
!= HSTORE_VALLEN(es2
, j
) ||
442 memcmp(HSTORE_VAL(es
, ps
, i
),
443 HSTORE_VAL(es2
, ps2
, j
),
446 HS_COPYITEM(ed
, bufd
, pd
,
447 HSTORE_KEY(es
, ps
, i
), HSTORE_KEYLEN(es
, i
),
455 HS_COPYITEM(ed
, bufd
, pd
,
456 HSTORE_KEY(es
, ps
, i
), HSTORE_KEYLEN(es
, i
),
457 HSTORE_VALLEN(es
, i
), HSTORE_VALISNULL(es
, i
));
463 HS_FINALIZE(out
, outcount
, bufd
, pd
);
465 PG_RETURN_POINTER(out
);
469 PG_FUNCTION_INFO_V1(hstore_concat
);
471 hstore_concat(PG_FUNCTION_ARGS
)
473 HStore
*s1
= PG_GETARG_HSTORE_P(0);
474 HStore
*s2
= PG_GETARG_HSTORE_P(1);
475 HStore
*out
= palloc(VARSIZE(s1
) + VARSIZE(s2
));
485 int s1count
= HS_COUNT(s1
);
486 int s2count
= HS_COUNT(s2
);
489 SET_VARSIZE(out
, VARSIZE(s1
) + VARSIZE(s2
) - HSHRDSIZE
);
490 HS_SETCOUNT(out
, s1count
+ s2count
);
494 /* return a copy of the input, unchanged */
495 memcpy(out
, s2
, VARSIZE(s2
));
496 HS_FIXSIZE(out
, s2count
);
497 HS_SETCOUNT(out
, s2count
);
498 PG_RETURN_POINTER(out
);
503 /* return a copy of the input, unchanged */
504 memcpy(out
, s1
, VARSIZE(s1
));
505 HS_FIXSIZE(out
, s1count
);
506 HS_SETCOUNT(out
, s1count
);
507 PG_RETURN_POINTER(out
);
512 bufd
= pd
= STRPTR(out
);
518 * this is in effect a merge between s1 and s2, both of which are already
519 * sorted by (keylen,key); we take s2 for equal keys
522 for (s1idx
= s2idx
= 0; s1idx
< s1count
|| s2idx
< s2count
; ++outcount
)
526 if (s1idx
>= s1count
)
528 else if (s2idx
>= s2count
)
532 int s1keylen
= HSTORE_KEYLEN(es1
, s1idx
);
533 int s2keylen
= HSTORE_KEYLEN(es2
, s2idx
);
535 if (s1keylen
== s2keylen
)
536 difference
= memcmp(HSTORE_KEY(es1
, ps1
, s1idx
),
537 HSTORE_KEY(es2
, ps2
, s2idx
),
540 difference
= (s1keylen
> s2keylen
) ? 1 : -1;
545 HS_COPYITEM(ed
, bufd
, pd
,
546 HSTORE_KEY(es2
, ps2
, s2idx
), HSTORE_KEYLEN(es2
, s2idx
),
547 HSTORE_VALLEN(es2
, s2idx
), HSTORE_VALISNULL(es2
, s2idx
));
554 HS_COPYITEM(ed
, bufd
, pd
,
555 HSTORE_KEY(es1
, ps1
, s1idx
), HSTORE_KEYLEN(es1
, s1idx
),
556 HSTORE_VALLEN(es1
, s1idx
), HSTORE_VALISNULL(es1
, s1idx
));
561 HS_FINALIZE(out
, outcount
, bufd
, pd
);
563 PG_RETURN_POINTER(out
);
567 PG_FUNCTION_INFO_V1(hstore_slice_to_array
);
569 hstore_slice_to_array(PG_FUNCTION_ARGS
)
571 HStore
*hs
= PG_GETARG_HSTORE_P(0);
572 HEntry
*entries
= ARRPTR(hs
);
573 char *ptr
= STRPTR(hs
);
574 ArrayType
*key_array
= PG_GETARG_ARRAYTYPE_P(1);
583 deconstruct_array_builtin(key_array
, TEXTOID
, &key_datums
, &key_nulls
, &key_count
);
587 aout
= construct_empty_array(TEXTOID
);
588 PG_RETURN_POINTER(aout
);
591 out_datums
= palloc(sizeof(Datum
) * key_count
);
592 out_nulls
= palloc(sizeof(bool) * key_count
);
594 for (i
= 0; i
< key_count
; ++i
)
596 text
*key
= (text
*) DatumGetPointer(key_datums
[i
]);
602 idx
= hstoreFindKey(hs
, NULL
, VARDATA(key
), VARSIZE(key
) - VARHDRSZ
);
604 if (idx
< 0 || HSTORE_VALISNULL(entries
, idx
))
607 out_datums
[i
] = (Datum
) 0;
612 PointerGetDatum(cstring_to_text_with_len(HSTORE_VAL(entries
, ptr
, idx
),
613 HSTORE_VALLEN(entries
, idx
)));
614 out_nulls
[i
] = false;
618 aout
= construct_md_array(out_datums
, out_nulls
,
621 ARR_LBOUND(key_array
),
622 TEXTOID
, -1, false, TYPALIGN_INT
);
624 PG_RETURN_POINTER(aout
);
628 PG_FUNCTION_INFO_V1(hstore_slice_to_hstore
);
630 hstore_slice_to_hstore(PG_FUNCTION_ARGS
)
632 HStore
*hs
= PG_GETARG_HSTORE_P(0);
633 HEntry
*entries
= ARRPTR(hs
);
634 char *ptr
= STRPTR(hs
);
635 ArrayType
*key_array
= PG_GETARG_ARRAYTYPE_P(1);
638 Pairs
*key_pairs
= hstoreArrayToPairs(key_array
, &nkeys
);
647 out
= hstorePairs(NULL
, 0, 0);
648 PG_RETURN_POINTER(out
);
651 /* hstoreArrayToPairs() checked overflow */
652 out_pairs
= palloc(sizeof(Pairs
) * nkeys
);
656 * we exploit the fact that the pairs list is already sorted into strictly
657 * increasing order to narrow the hstoreFindKey search; each search can
658 * start one entry past the previous "found" entry, or at the lower bound
659 * of the last search.
662 for (i
= 0; i
< nkeys
; ++i
)
664 int idx
= hstoreFindKey(hs
, &lastidx
,
665 key_pairs
[i
].key
, key_pairs
[i
].keylen
);
669 out_pairs
[out_count
].key
= key_pairs
[i
].key
;
670 bufsiz
+= (out_pairs
[out_count
].keylen
= key_pairs
[i
].keylen
);
671 out_pairs
[out_count
].val
= HSTORE_VAL(entries
, ptr
, idx
);
672 bufsiz
+= (out_pairs
[out_count
].vallen
= HSTORE_VALLEN(entries
, idx
));
673 out_pairs
[out_count
].isnull
= HSTORE_VALISNULL(entries
, idx
);
674 out_pairs
[out_count
].needfree
= false;
680 * we don't use hstoreUniquePairs here because we know that the pairs list
681 * is already sorted and uniq'ed.
684 out
= hstorePairs(out_pairs
, out_count
, bufsiz
);
686 PG_RETURN_POINTER(out
);
690 PG_FUNCTION_INFO_V1(hstore_akeys
);
692 hstore_akeys(PG_FUNCTION_ARGS
)
694 HStore
*hs
= PG_GETARG_HSTORE_P(0);
697 HEntry
*entries
= ARRPTR(hs
);
698 char *base
= STRPTR(hs
);
699 int count
= HS_COUNT(hs
);
704 a
= construct_empty_array(TEXTOID
);
705 PG_RETURN_POINTER(a
);
708 d
= (Datum
*) palloc(sizeof(Datum
) * count
);
710 for (i
= 0; i
< count
; ++i
)
712 text
*t
= cstring_to_text_with_len(HSTORE_KEY(entries
, base
, i
),
713 HSTORE_KEYLEN(entries
, i
));
715 d
[i
] = PointerGetDatum(t
);
718 a
= construct_array_builtin(d
, count
, TEXTOID
);
720 PG_RETURN_POINTER(a
);
724 PG_FUNCTION_INFO_V1(hstore_avals
);
726 hstore_avals(PG_FUNCTION_ARGS
)
728 HStore
*hs
= PG_GETARG_HSTORE_P(0);
732 HEntry
*entries
= ARRPTR(hs
);
733 char *base
= STRPTR(hs
);
734 int count
= HS_COUNT(hs
);
740 a
= construct_empty_array(TEXTOID
);
741 PG_RETURN_POINTER(a
);
744 d
= (Datum
*) palloc(sizeof(Datum
) * count
);
745 nulls
= (bool *) palloc(sizeof(bool) * count
);
747 for (i
= 0; i
< count
; ++i
)
749 if (HSTORE_VALISNULL(entries
, i
))
756 text
*item
= cstring_to_text_with_len(HSTORE_VAL(entries
, base
, i
),
757 HSTORE_VALLEN(entries
, i
));
759 d
[i
] = PointerGetDatum(item
);
764 a
= construct_md_array(d
, nulls
, 1, &count
, &lb
,
765 TEXTOID
, -1, false, TYPALIGN_INT
);
767 PG_RETURN_POINTER(a
);
772 hstore_to_array_internal(HStore
*hs
, int ndims
)
774 HEntry
*entries
= ARRPTR(hs
);
775 char *base
= STRPTR(hs
);
776 int count
= HS_COUNT(hs
);
777 int out_size
[2] = {0, 2};
785 if (count
== 0 || ndims
== 0)
786 return construct_empty_array(TEXTOID
);
788 out_size
[0] = count
* 2 / ndims
;
789 out_datums
= palloc(sizeof(Datum
) * count
* 2);
790 out_nulls
= palloc(sizeof(bool) * count
* 2);
792 for (i
= 0; i
< count
; ++i
)
794 text
*key
= cstring_to_text_with_len(HSTORE_KEY(entries
, base
, i
),
795 HSTORE_KEYLEN(entries
, i
));
797 out_datums
[i
* 2] = PointerGetDatum(key
);
798 out_nulls
[i
* 2] = false;
800 if (HSTORE_VALISNULL(entries
, i
))
802 out_datums
[i
* 2 + 1] = (Datum
) 0;
803 out_nulls
[i
* 2 + 1] = true;
807 text
*item
= cstring_to_text_with_len(HSTORE_VAL(entries
, base
, i
),
808 HSTORE_VALLEN(entries
, i
));
810 out_datums
[i
* 2 + 1] = PointerGetDatum(item
);
811 out_nulls
[i
* 2 + 1] = false;
815 return construct_md_array(out_datums
, out_nulls
,
817 TEXTOID
, -1, false, TYPALIGN_INT
);
820 PG_FUNCTION_INFO_V1(hstore_to_array
);
822 hstore_to_array(PG_FUNCTION_ARGS
)
824 HStore
*hs
= PG_GETARG_HSTORE_P(0);
825 ArrayType
*out
= hstore_to_array_internal(hs
, 1);
827 PG_RETURN_POINTER(out
);
830 PG_FUNCTION_INFO_V1(hstore_to_matrix
);
832 hstore_to_matrix(PG_FUNCTION_ARGS
)
834 HStore
*hs
= PG_GETARG_HSTORE_P(0);
835 ArrayType
*out
= hstore_to_array_internal(hs
, 2);
837 PG_RETURN_POINTER(out
);
841 * Common initialization function for the various set-returning
842 * funcs. fcinfo is only passed if the function is to return a
843 * composite; it will be used to look up the return tupledesc.
844 * we stash a copy of the hstore in the multi-call context in
845 * case it was originally toasted. (At least I assume that's why;
846 * there was no explanatory comment in the original code. --AG)
850 setup_firstcall(FuncCallContext
*funcctx
, HStore
*hs
,
851 FunctionCallInfo fcinfo
)
853 MemoryContext oldcontext
;
856 oldcontext
= MemoryContextSwitchTo(funcctx
->multi_call_memory_ctx
);
858 st
= (HStore
*) palloc(VARSIZE(hs
));
859 memcpy(st
, hs
, VARSIZE(hs
));
861 funcctx
->user_fctx
= (void *) st
;
867 /* Build a tuple descriptor for our result type */
868 if (get_call_result_type(fcinfo
, NULL
, &tupdesc
) != TYPEFUNC_COMPOSITE
)
869 elog(ERROR
, "return type must be a row type");
871 funcctx
->tuple_desc
= BlessTupleDesc(tupdesc
);
874 MemoryContextSwitchTo(oldcontext
);
878 PG_FUNCTION_INFO_V1(hstore_skeys
);
880 hstore_skeys(PG_FUNCTION_ARGS
)
882 FuncCallContext
*funcctx
;
886 if (SRF_IS_FIRSTCALL())
888 hs
= PG_GETARG_HSTORE_P(0);
889 funcctx
= SRF_FIRSTCALL_INIT();
890 setup_firstcall(funcctx
, hs
, NULL
);
893 funcctx
= SRF_PERCALL_SETUP();
894 hs
= (HStore
*) funcctx
->user_fctx
;
895 i
= funcctx
->call_cntr
;
897 if (i
< HS_COUNT(hs
))
899 HEntry
*entries
= ARRPTR(hs
);
902 item
= cstring_to_text_with_len(HSTORE_KEY(entries
, STRPTR(hs
), i
),
903 HSTORE_KEYLEN(entries
, i
));
905 SRF_RETURN_NEXT(funcctx
, PointerGetDatum(item
));
908 SRF_RETURN_DONE(funcctx
);
912 PG_FUNCTION_INFO_V1(hstore_svals
);
914 hstore_svals(PG_FUNCTION_ARGS
)
916 FuncCallContext
*funcctx
;
920 if (SRF_IS_FIRSTCALL())
922 hs
= PG_GETARG_HSTORE_P(0);
923 funcctx
= SRF_FIRSTCALL_INIT();
924 setup_firstcall(funcctx
, hs
, NULL
);
927 funcctx
= SRF_PERCALL_SETUP();
928 hs
= (HStore
*) funcctx
->user_fctx
;
929 i
= funcctx
->call_cntr
;
931 if (i
< HS_COUNT(hs
))
933 HEntry
*entries
= ARRPTR(hs
);
935 if (HSTORE_VALISNULL(entries
, i
))
939 /* ugly ugly ugly. why no macro for this? */
940 (funcctx
)->call_cntr
++;
941 rsi
= (ReturnSetInfo
*) fcinfo
->resultinfo
;
942 rsi
->isDone
= ExprMultipleResult
;
949 item
= cstring_to_text_with_len(HSTORE_VAL(entries
, STRPTR(hs
), i
),
950 HSTORE_VALLEN(entries
, i
));
952 SRF_RETURN_NEXT(funcctx
, PointerGetDatum(item
));
956 SRF_RETURN_DONE(funcctx
);
960 PG_FUNCTION_INFO_V1(hstore_contains
);
962 hstore_contains(PG_FUNCTION_ARGS
)
964 HStore
*val
= PG_GETARG_HSTORE_P(0);
965 HStore
*tmpl
= PG_GETARG_HSTORE_P(1);
967 HEntry
*te
= ARRPTR(tmpl
);
968 char *tstr
= STRPTR(tmpl
);
969 HEntry
*ve
= ARRPTR(val
);
970 char *vstr
= STRPTR(val
);
971 int tcount
= HS_COUNT(tmpl
);
976 * we exploit the fact that keys in "tmpl" are in strictly increasing
977 * order to narrow the hstoreFindKey search; each search can start one
978 * entry past the previous "found" entry, or at the lower bound of the
982 for (i
= 0; res
&& i
< tcount
; ++i
)
984 int idx
= hstoreFindKey(val
, &lastidx
,
985 HSTORE_KEY(te
, tstr
, i
),
986 HSTORE_KEYLEN(te
, i
));
990 bool nullval
= HSTORE_VALISNULL(te
, i
);
991 int vallen
= HSTORE_VALLEN(te
, i
);
993 if (nullval
!= HSTORE_VALISNULL(ve
, idx
) ||
994 (!nullval
&& (vallen
!= HSTORE_VALLEN(ve
, idx
) ||
995 memcmp(HSTORE_VAL(te
, tstr
, i
),
996 HSTORE_VAL(ve
, vstr
, idx
),
1004 PG_RETURN_BOOL(res
);
1008 PG_FUNCTION_INFO_V1(hstore_contained
);
1010 hstore_contained(PG_FUNCTION_ARGS
)
1012 PG_RETURN_DATUM(DirectFunctionCall2(hstore_contains
,
1019 PG_FUNCTION_INFO_V1(hstore_each
);
1021 hstore_each(PG_FUNCTION_ARGS
)
1023 FuncCallContext
*funcctx
;
1027 if (SRF_IS_FIRSTCALL())
1029 hs
= PG_GETARG_HSTORE_P(0);
1030 funcctx
= SRF_FIRSTCALL_INIT();
1031 setup_firstcall(funcctx
, hs
, fcinfo
);
1034 funcctx
= SRF_PERCALL_SETUP();
1035 hs
= (HStore
*) funcctx
->user_fctx
;
1036 i
= funcctx
->call_cntr
;
1038 if (i
< HS_COUNT(hs
))
1040 HEntry
*entries
= ARRPTR(hs
);
1041 char *ptr
= STRPTR(hs
);
1044 bool nulls
[2] = {false, false};
1048 item
= cstring_to_text_with_len(HSTORE_KEY(entries
, ptr
, i
),
1049 HSTORE_KEYLEN(entries
, i
));
1050 dvalues
[0] = PointerGetDatum(item
);
1052 if (HSTORE_VALISNULL(entries
, i
))
1054 dvalues
[1] = (Datum
) 0;
1059 item
= cstring_to_text_with_len(HSTORE_VAL(entries
, ptr
, i
),
1060 HSTORE_VALLEN(entries
, i
));
1061 dvalues
[1] = PointerGetDatum(item
);
1064 tuple
= heap_form_tuple(funcctx
->tuple_desc
, dvalues
, nulls
);
1065 res
= HeapTupleGetDatum(tuple
);
1067 SRF_RETURN_NEXT(funcctx
, res
);
1070 SRF_RETURN_DONE(funcctx
);
1075 * btree sort order for hstores isn't intended to be useful; we really only
1076 * care about equality versus non-equality. we compare the entire string
1077 * buffer first, then the entry pos array.
1080 PG_FUNCTION_INFO_V1(hstore_cmp
);
1082 hstore_cmp(PG_FUNCTION_ARGS
)
1084 HStore
*hs1
= PG_GETARG_HSTORE_P(0);
1085 HStore
*hs2
= PG_GETARG_HSTORE_P(1);
1086 int hcount1
= HS_COUNT(hs1
);
1087 int hcount2
= HS_COUNT(hs2
);
1090 if (hcount1
== 0 || hcount2
== 0)
1093 * if either operand is empty, and the other is nonempty, the nonempty
1094 * one is larger. If both are empty they are equal.
1098 else if (hcount2
> 0)
1103 /* here we know both operands are nonempty */
1104 char *str1
= STRPTR(hs1
);
1105 char *str2
= STRPTR(hs2
);
1106 HEntry
*ent1
= ARRPTR(hs1
);
1107 HEntry
*ent2
= ARRPTR(hs2
);
1108 size_t len1
= HSE_ENDPOS(ent1
[2 * hcount1
- 1]);
1109 size_t len2
= HSE_ENDPOS(ent2
[2 * hcount2
- 1]);
1111 res
= memcmp(str1
, str2
, Min(len1
, len2
));
1117 else if (len1
< len2
)
1119 else if (hcount1
> hcount2
)
1121 else if (hcount2
> hcount1
)
1125 int count
= hcount1
* 2;
1128 for (i
= 0; i
< count
; ++i
)
1129 if (HSE_ENDPOS(ent1
[i
]) != HSE_ENDPOS(ent2
[i
]) ||
1130 HSE_ISNULL(ent1
[i
]) != HSE_ISNULL(ent2
[i
]))
1134 if (HSE_ENDPOS(ent1
[i
]) < HSE_ENDPOS(ent2
[i
]))
1136 else if (HSE_ENDPOS(ent1
[i
]) > HSE_ENDPOS(ent2
[i
]))
1138 else if (HSE_ISNULL(ent1
[i
]))
1140 else if (HSE_ISNULL(ent2
[i
]))
1147 res
= (res
> 0) ? 1 : -1;
1152 * this is a btree support function; this is one of the few places where
1153 * memory needs to be explicitly freed.
1155 PG_FREE_IF_COPY(hs1
, 0);
1156 PG_FREE_IF_COPY(hs2
, 1);
1157 PG_RETURN_INT32(res
);
1161 PG_FUNCTION_INFO_V1(hstore_eq
);
1163 hstore_eq(PG_FUNCTION_ARGS
)
1165 int res
= DatumGetInt32(DirectFunctionCall2(hstore_cmp
,
1167 PG_GETARG_DATUM(1)));
1169 PG_RETURN_BOOL(res
== 0);
1172 PG_FUNCTION_INFO_V1(hstore_ne
);
1174 hstore_ne(PG_FUNCTION_ARGS
)
1176 int res
= DatumGetInt32(DirectFunctionCall2(hstore_cmp
,
1178 PG_GETARG_DATUM(1)));
1180 PG_RETURN_BOOL(res
!= 0);
1183 PG_FUNCTION_INFO_V1(hstore_gt
);
1185 hstore_gt(PG_FUNCTION_ARGS
)
1187 int res
= DatumGetInt32(DirectFunctionCall2(hstore_cmp
,
1189 PG_GETARG_DATUM(1)));
1191 PG_RETURN_BOOL(res
> 0);
1194 PG_FUNCTION_INFO_V1(hstore_ge
);
1196 hstore_ge(PG_FUNCTION_ARGS
)
1198 int res
= DatumGetInt32(DirectFunctionCall2(hstore_cmp
,
1200 PG_GETARG_DATUM(1)));
1202 PG_RETURN_BOOL(res
>= 0);
1205 PG_FUNCTION_INFO_V1(hstore_lt
);
1207 hstore_lt(PG_FUNCTION_ARGS
)
1209 int res
= DatumGetInt32(DirectFunctionCall2(hstore_cmp
,
1211 PG_GETARG_DATUM(1)));
1213 PG_RETURN_BOOL(res
< 0);
1216 PG_FUNCTION_INFO_V1(hstore_le
);
1218 hstore_le(PG_FUNCTION_ARGS
)
1220 int res
= DatumGetInt32(DirectFunctionCall2(hstore_cmp
,
1222 PG_GETARG_DATUM(1)));
1224 PG_RETURN_BOOL(res
<= 0);
1228 PG_FUNCTION_INFO_V1(hstore_hash
);
1230 hstore_hash(PG_FUNCTION_ARGS
)
1232 HStore
*hs
= PG_GETARG_HSTORE_P(0);
1233 Datum hval
= hash_any((unsigned char *) VARDATA(hs
),
1234 VARSIZE(hs
) - VARHDRSZ
);
1237 * This (along with hstore_hash_extended) is the only place in the code
1238 * that cares whether the overall varlena size exactly matches the true
1239 * data size; this assertion should be maintained by all the other code,
1240 * but we make it explicit here.
1242 Assert(VARSIZE(hs
) ==
1243 (HS_COUNT(hs
) != 0 ?
1244 CALCDATASIZE(HS_COUNT(hs
),
1245 HSE_ENDPOS(ARRPTR(hs
)[2 * HS_COUNT(hs
) - 1])) :
1248 PG_FREE_IF_COPY(hs
, 0);
1249 PG_RETURN_DATUM(hval
);
1252 PG_FUNCTION_INFO_V1(hstore_hash_extended
);
1254 hstore_hash_extended(PG_FUNCTION_ARGS
)
1256 HStore
*hs
= PG_GETARG_HSTORE_P(0);
1257 uint64 seed
= PG_GETARG_INT64(1);
1260 hval
= hash_any_extended((unsigned char *) VARDATA(hs
),
1261 VARSIZE(hs
) - VARHDRSZ
,
1264 /* See comment in hstore_hash */
1265 Assert(VARSIZE(hs
) ==
1266 (HS_COUNT(hs
) != 0 ?
1267 CALCDATASIZE(HS_COUNT(hs
),
1268 HSE_ENDPOS(ARRPTR(hs
)[2 * HS_COUNT(hs
) - 1])) :
1271 PG_FREE_IF_COPY(hs
, 0);
1272 PG_RETURN_DATUM(hval
);