PostgreSQL Source Code: contrib/hstore/hstore_op.c Source File

PostgreSQL Source Code git master
hstore_op.c
Go to the documentation of this file.
1/*
2 * contrib/hstore/hstore_op.c
3 */
4#include "postgres.h"
5
6#include "access/htup_details.h"
7#include "catalog/pg_type.h"
8#include "common/hashfn.h"
9#include "funcapi.h"
10#include "hstore.h"
11#include "utils/builtins.h"
12#include "utils/memutils.h"
13
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);
27
28
29/*
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.
34 */
35int
36 hstoreFindKey(HStore *hs, int *lowbound, char *key, int keylen)
37{
38 HEntry *entries = ARRPTR(hs);
39 int stopLow = lowbound ? *lowbound : 0;
40 int stopHigh = HS_COUNT(hs);
41 int stopMiddle;
42 char *base = STRPTR(hs);
43
44 while (stopLow < stopHigh)
45 {
46 int difference;
47
48 stopMiddle = stopLow + (stopHigh - stopLow) / 2;
49
50 if (HSTORE_KEYLEN(entries, stopMiddle) == keylen)
51 difference = memcmp(HSTORE_KEY(entries, base, stopMiddle), key, keylen);
52 else
53 difference = (HSTORE_KEYLEN(entries, stopMiddle) > keylen) ? 1 : -1;
54
55 if (difference == 0)
56 {
57 if (lowbound)
58 *lowbound = stopMiddle + 1;
59 return stopMiddle;
60 }
61 else if (difference < 0)
62 stopLow = stopMiddle + 1;
63 else
64 stopHigh = stopMiddle;
65 }
66
67 if (lowbound)
68 *lowbound = stopLow;
69 return -1;
70}
71
72Pairs *
73 hstoreArrayToPairs(ArrayType *a, int *npairs)
74{
75 Datum *key_datums;
76 bool *key_nulls;
77 int key_count;
78 Pairs *key_pairs;
79 int bufsiz;
80 int i,
81 j;
82
83 deconstruct_array_builtin(a, TEXTOID, &key_datums, &key_nulls, &key_count);
84
85 if (key_count == 0)
86 {
87 *npairs = 0;
88 return NULL;
89 }
90
91 /*
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.
97 */
98 if (key_count > MaxAllocSize / sizeof(Pairs))
99 ereport(ERROR,
100 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
101 errmsg("number of pairs (%d) exceeds the maximum allowed (%d)",
102 key_count, (int) (MaxAllocSize / sizeof(Pairs)))));
103
104 key_pairs = palloc(sizeof(Pairs) * key_count);
105
106 for (i = 0, j = 0; i < key_count; i++)
107 {
108 if (!key_nulls[i])
109 {
110 key_pairs[j].key = VARDATA(DatumGetPointer(key_datums[i]));
111 key_pairs[j].keylen = VARSIZE(DatumGetPointer(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;
116 j++;
117 }
118 }
119
120 *npairs = hstoreUniquePairs(key_pairs, j, &bufsiz);
121
122 return key_pairs;
123}
124
125
126 PG_FUNCTION_INFO_V1(hstore_fetchval);
127Datum
128 hstore_fetchval(PG_FUNCTION_ARGS)
129{
130 HStore *hs = PG_GETARG_HSTORE_P(0);
131 text *key = PG_GETARG_TEXT_PP(1);
132 HEntry *entries = ARRPTR(hs);
133 text *out;
134 int idx = hstoreFindKey(hs, NULL,
135 VARDATA_ANY(key), VARSIZE_ANY_EXHDR(key));
136
137 if (idx < 0 || HSTORE_VALISNULL(entries, idx))
138 PG_RETURN_NULL();
139
140 out = cstring_to_text_with_len(HSTORE_VAL(entries, STRPTR(hs), idx),
141 HSTORE_VALLEN(entries, idx));
142
143 PG_RETURN_TEXT_P(out);
144}
145
146
147 PG_FUNCTION_INFO_V1(hstore_exists);
148Datum
149 hstore_exists(PG_FUNCTION_ARGS)
150{
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));
155
156 PG_RETURN_BOOL(idx >= 0);
157}
158
159
160 PG_FUNCTION_INFO_V1(hstore_exists_any);
161Datum
162 hstore_exists_any(PG_FUNCTION_ARGS)
163{
164 HStore *hs = PG_GETARG_HSTORE_P(0);
165 ArrayType *keys = PG_GETARG_ARRAYTYPE_P(1);
166 int nkeys;
167 Pairs *key_pairs = hstoreArrayToPairs(keys, &nkeys);
168 int i;
169 int lowbound = 0;
170 bool res = false;
171
172 /*
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.
177 */
178 for (i = 0; i < nkeys; i++)
179 {
180 int idx = hstoreFindKey(hs, &lowbound,
181 key_pairs[i].key, key_pairs[i].keylen);
182
183 if (idx >= 0)
184 {
185 res = true;
186 break;
187 }
188 }
189
190 PG_RETURN_BOOL(res);
191}
192
193
194 PG_FUNCTION_INFO_V1(hstore_exists_all);
195Datum
196 hstore_exists_all(PG_FUNCTION_ARGS)
197{
198 HStore *hs = PG_GETARG_HSTORE_P(0);
199 ArrayType *keys = PG_GETARG_ARRAYTYPE_P(1);
200 int nkeys;
201 Pairs *key_pairs = hstoreArrayToPairs(keys, &nkeys);
202 int i;
203 int lowbound = 0;
204 bool res = true;
205
206 /*
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.
211 */
212 for (i = 0; i < nkeys; i++)
213 {
214 int idx = hstoreFindKey(hs, &lowbound,
215 key_pairs[i].key, key_pairs[i].keylen);
216
217 if (idx < 0)
218 {
219 res = false;
220 break;
221 }
222 }
223
224 PG_RETURN_BOOL(res);
225}
226
227
228 PG_FUNCTION_INFO_V1(hstore_defined);
229Datum
230 hstore_defined(PG_FUNCTION_ARGS)
231{
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));
238
239 PG_RETURN_BOOL(res);
240}
241
242
243 PG_FUNCTION_INFO_V1(hstore_delete);
244Datum
245 hstore_delete(PG_FUNCTION_ARGS)
246{
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));
252 char *bufs,
253 *bufd,
254 *ptrd;
255 HEntry *es,
256 *ed;
257 int i;
258 int count = HS_COUNT(hs);
259 int outcount = 0;
260
261 SET_VARSIZE(out, VARSIZE(hs));
262 HS_SETCOUNT(out, count); /* temporary! */
263
264 bufs = STRPTR(hs);
265 es = ARRPTR(hs);
266 bufd = ptrd = STRPTR(out);
267 ed = ARRPTR(out);
268
269 for (i = 0; i < count; ++i)
270 {
271 int len = HSTORE_KEYLEN(es, i);
272 char *ptrs = HSTORE_KEY(es, bufs, i);
273
274 if (!(len == keylen && memcmp(ptrs, keyptr, keylen) == 0))
275 {
276 int vallen = HSTORE_VALLEN(es, i);
277
278 HS_COPYITEM(ed, bufd, ptrd, ptrs, len, vallen,
279 HSTORE_VALISNULL(es, i));
280 ++outcount;
281 }
282 }
283
284 HS_FINALIZE(out, outcount, bufd, ptrd);
285
286 PG_RETURN_POINTER(out);
287}
288
289
290 PG_FUNCTION_INFO_V1(hstore_delete_array);
291Datum
292 hstore_delete_array(PG_FUNCTION_ARGS)
293{
294 HStore *hs = PG_GETARG_HSTORE_P(0);
295 HStore *out = palloc(VARSIZE(hs));
296 int hs_count = HS_COUNT(hs);
297 char *ps,
298 *bufd,
299 *pd;
300 HEntry *es,
301 *ed;
302 int i,
303 j;
304 int outcount = 0;
305 ArrayType *key_array = PG_GETARG_ARRAYTYPE_P(1);
306 int nkeys;
307 Pairs *key_pairs = hstoreArrayToPairs(key_array, &nkeys);
308
309 SET_VARSIZE(out, VARSIZE(hs));
310 HS_SETCOUNT(out, hs_count); /* temporary! */
311
312 ps = STRPTR(hs);
313 es = ARRPTR(hs);
314 bufd = pd = STRPTR(out);
315 ed = ARRPTR(out);
316
317 if (nkeys == 0)
318 {
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);
324 }
325
326 /*
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
329 */
330
331 for (i = j = 0; i < hs_count;)
332 {
333 int difference;
334
335 if (j >= nkeys)
336 difference = -1;
337 else
338 {
339 int skeylen = HSTORE_KEYLEN(es, i);
340
341 if (skeylen == key_pairs[j].keylen)
342 difference = memcmp(HSTORE_KEY(es, ps, i),
343 key_pairs[j].key,
344 key_pairs[j].keylen);
345 else
346 difference = (skeylen > key_pairs[j].keylen) ? 1 : -1;
347 }
348
349 if (difference > 0)
350 ++j;
351 else if (difference == 0)
352 ++i, ++j;
353 else
354 {
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));
358 ++outcount;
359 ++i;
360 }
361 }
362
363 HS_FINALIZE(out, outcount, bufd, pd);
364
365 PG_RETURN_POINTER(out);
366}
367
368
369 PG_FUNCTION_INFO_V1(hstore_delete_hstore);
370Datum
371 hstore_delete_hstore(PG_FUNCTION_ARGS)
372{
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);
378 char *ps,
379 *ps2,
380 *bufd,
381 *pd;
382 HEntry *es,
383 *es2,
384 *ed;
385 int i,
386 j;
387 int outcount = 0;
388
389 SET_VARSIZE(out, VARSIZE(hs));
390 HS_SETCOUNT(out, hs_count); /* temporary! */
391
392 ps = STRPTR(hs);
393 es = ARRPTR(hs);
394 ps2 = STRPTR(hs2);
395 es2 = ARRPTR(hs2);
396 bufd = pd = STRPTR(out);
397 ed = ARRPTR(out);
398
399 if (hs2_count == 0)
400 {
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);
406 }
407
408 /*
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
412 */
413
414 for (i = j = 0; i < hs_count;)
415 {
416 int difference;
417
418 if (j >= hs2_count)
419 difference = -1;
420 else
421 {
422 int skeylen = HSTORE_KEYLEN(es, i);
423 int s2keylen = HSTORE_KEYLEN(es2, j);
424
425 if (skeylen == s2keylen)
426 difference = memcmp(HSTORE_KEY(es, ps, i),
427 HSTORE_KEY(es2, ps2, j),
428 skeylen);
429 else
430 difference = (skeylen > s2keylen) ? 1 : -1;
431 }
432
433 if (difference > 0)
434 ++j;
435 else if (difference == 0)
436 {
437 int svallen = HSTORE_VALLEN(es, i);
438 int snullval = HSTORE_VALISNULL(es, i);
439
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),
444 svallen) != 0)))
445 {
446 HS_COPYITEM(ed, bufd, pd,
447 HSTORE_KEY(es, ps, i), HSTORE_KEYLEN(es, i),
448 svallen, snullval);
449 ++outcount;
450 }
451 ++i, ++j;
452 }
453 else
454 {
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));
458 ++outcount;
459 ++i;
460 }
461 }
462
463 HS_FINALIZE(out, outcount, bufd, pd);
464
465 PG_RETURN_POINTER(out);
466}
467
468
469 PG_FUNCTION_INFO_V1(hstore_concat);
470Datum
471 hstore_concat(PG_FUNCTION_ARGS)
472{
473 HStore *s1 = PG_GETARG_HSTORE_P(0);
474 HStore *s2 = PG_GETARG_HSTORE_P(1);
475 HStore *out = palloc(VARSIZE(s1) + VARSIZE(s2));
476 char *ps1,
477 *ps2,
478 *bufd,
479 *pd;
480 HEntry *es1,
481 *es2,
482 *ed;
483 int s1idx;
484 int s2idx;
485 int s1count = HS_COUNT(s1);
486 int s2count = HS_COUNT(s2);
487 int outcount = 0;
488
489 SET_VARSIZE(out, VARSIZE(s1) + VARSIZE(s2) - HSHRDSIZE);
490 HS_SETCOUNT(out, s1count + s2count);
491
492 if (s1count == 0)
493 {
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);
499 }
500
501 if (s2count == 0)
502 {
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);
508 }
509
510 ps1 = STRPTR(s1);
511 ps2 = STRPTR(s2);
512 bufd = pd = STRPTR(out);
513 es1 = ARRPTR(s1);
514 es2 = ARRPTR(s2);
515 ed = ARRPTR(out);
516
517 /*
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
520 */
521
522 for (s1idx = s2idx = 0; s1idx < s1count || s2idx < s2count; ++outcount)
523 {
524 int difference;
525
526 if (s1idx >= s1count)
527 difference = 1;
528 else if (s2idx >= s2count)
529 difference = -1;
530 else
531 {
532 int s1keylen = HSTORE_KEYLEN(es1, s1idx);
533 int s2keylen = HSTORE_KEYLEN(es2, s2idx);
534
535 if (s1keylen == s2keylen)
536 difference = memcmp(HSTORE_KEY(es1, ps1, s1idx),
537 HSTORE_KEY(es2, ps2, s2idx),
538 s1keylen);
539 else
540 difference = (s1keylen > s2keylen) ? 1 : -1;
541 }
542
543 if (difference >= 0)
544 {
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));
548 ++s2idx;
549 if (difference == 0)
550 ++s1idx;
551 }
552 else
553 {
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));
557 ++s1idx;
558 }
559 }
560
561 HS_FINALIZE(out, outcount, bufd, pd);
562
563 PG_RETURN_POINTER(out);
564}
565
566
567 PG_FUNCTION_INFO_V1(hstore_slice_to_array);
568Datum
569 hstore_slice_to_array(PG_FUNCTION_ARGS)
570{
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);
575 ArrayType *aout;
576 Datum *key_datums;
577 bool *key_nulls;
578 Datum *out_datums;
579 bool *out_nulls;
580 int key_count;
581 int i;
582
583 deconstruct_array_builtin(key_array, TEXTOID, &key_datums, &key_nulls, &key_count);
584
585 if (key_count == 0)
586 {
587 aout = construct_empty_array(TEXTOID);
588 PG_RETURN_POINTER(aout);
589 }
590
591 out_datums = palloc(sizeof(Datum) * key_count);
592 out_nulls = palloc(sizeof(bool) * key_count);
593
594 for (i = 0; i < key_count; ++i)
595 {
596 text *key = (text *) DatumGetPointer(key_datums[i]);
597 int idx;
598
599 if (key_nulls[i])
600 idx = -1;
601 else
602 idx = hstoreFindKey(hs, NULL, VARDATA(key), VARSIZE(key) - VARHDRSZ);
603
604 if (idx < 0 || HSTORE_VALISNULL(entries, idx))
605 {
606 out_nulls[i] = true;
607 out_datums[i] = (Datum) 0;
608 }
609 else
610 {
611 out_datums[i] =
612 PointerGetDatum(cstring_to_text_with_len(HSTORE_VAL(entries, ptr, idx),
613 HSTORE_VALLEN(entries, idx)));
614 out_nulls[i] = false;
615 }
616 }
617
618 aout = construct_md_array(out_datums, out_nulls,
619 ARR_NDIM(key_array),
620 ARR_DIMS(key_array),
621 ARR_LBOUND(key_array),
622 TEXTOID, -1, false, TYPALIGN_INT);
623
624 PG_RETURN_POINTER(aout);
625}
626
627
628 PG_FUNCTION_INFO_V1(hstore_slice_to_hstore);
629Datum
630 hstore_slice_to_hstore(PG_FUNCTION_ARGS)
631{
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);
636 HStore *out;
637 int nkeys;
638 Pairs *key_pairs = hstoreArrayToPairs(key_array, &nkeys);
639 Pairs *out_pairs;
640 int bufsiz;
641 int lastidx = 0;
642 int i;
643 int out_count = 0;
644
645 if (nkeys == 0)
646 {
647 out = hstorePairs(NULL, 0, 0);
648 PG_RETURN_POINTER(out);
649 }
650
651 /* hstoreArrayToPairs() checked overflow */
652 out_pairs = palloc(sizeof(Pairs) * nkeys);
653 bufsiz = 0;
654
655 /*
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.
660 */
661
662 for (i = 0; i < nkeys; ++i)
663 {
664 int idx = hstoreFindKey(hs, &lastidx,
665 key_pairs[i].key, key_pairs[i].keylen);
666
667 if (idx >= 0)
668 {
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;
675 ++out_count;
676 }
677 }
678
679 /*
680 * we don't use hstoreUniquePairs here because we know that the pairs list
681 * is already sorted and uniq'ed.
682 */
683
684 out = hstorePairs(out_pairs, out_count, bufsiz);
685
686 PG_RETURN_POINTER(out);
687}
688
689
690 PG_FUNCTION_INFO_V1(hstore_akeys);
691Datum
692 hstore_akeys(PG_FUNCTION_ARGS)
693{
694 HStore *hs = PG_GETARG_HSTORE_P(0);
695 Datum *d;
696 ArrayType *a;
697 HEntry *entries = ARRPTR(hs);
698 char *base = STRPTR(hs);
699 int count = HS_COUNT(hs);
700 int i;
701
702 if (count == 0)
703 {
704 a = construct_empty_array(TEXTOID);
705 PG_RETURN_POINTER(a);
706 }
707
708 d = (Datum *) palloc(sizeof(Datum) * count);
709
710 for (i = 0; i < count; ++i)
711 {
712 text *t = cstring_to_text_with_len(HSTORE_KEY(entries, base, i),
713 HSTORE_KEYLEN(entries, i));
714
715 d[i] = PointerGetDatum(t);
716 }
717
718 a = construct_array_builtin(d, count, TEXTOID);
719
720 PG_RETURN_POINTER(a);
721}
722
723
724 PG_FUNCTION_INFO_V1(hstore_avals);
725Datum
726 hstore_avals(PG_FUNCTION_ARGS)
727{
728 HStore *hs = PG_GETARG_HSTORE_P(0);
729 Datum *d;
730 bool *nulls;
731 ArrayType *a;
732 HEntry *entries = ARRPTR(hs);
733 char *base = STRPTR(hs);
734 int count = HS_COUNT(hs);
735 int lb = 1;
736 int i;
737
738 if (count == 0)
739 {
740 a = construct_empty_array(TEXTOID);
741 PG_RETURN_POINTER(a);
742 }
743
744 d = (Datum *) palloc(sizeof(Datum) * count);
745 nulls = (bool *) palloc(sizeof(bool) * count);
746
747 for (i = 0; i < count; ++i)
748 {
749 if (HSTORE_VALISNULL(entries, i))
750 {
751 d[i] = (Datum) 0;
752 nulls[i] = true;
753 }
754 else
755 {
756 text *item = cstring_to_text_with_len(HSTORE_VAL(entries, base, i),
757 HSTORE_VALLEN(entries, i));
758
759 d[i] = PointerGetDatum(item);
760 nulls[i] = false;
761 }
762 }
763
764 a = construct_md_array(d, nulls, 1, &count, &lb,
765 TEXTOID, -1, false, TYPALIGN_INT);
766
767 PG_RETURN_POINTER(a);
768}
769
770
771static ArrayType *
772 hstore_to_array_internal(HStore *hs, int ndims)
773{
774 HEntry *entries = ARRPTR(hs);
775 char *base = STRPTR(hs);
776 int count = HS_COUNT(hs);
777 int out_size[2] = {0, 2};
778 int lb[2] = {1, 1};
779 Datum *out_datums;
780 bool *out_nulls;
781 int i;
782
783 Assert(ndims < 3);
784
785 if (count == 0 || ndims == 0)
786 return construct_empty_array(TEXTOID);
787
788 out_size[0] = count * 2 / ndims;
789 out_datums = palloc(sizeof(Datum) * count * 2);
790 out_nulls = palloc(sizeof(bool) * count * 2);
791
792 for (i = 0; i < count; ++i)
793 {
794 text *key = cstring_to_text_with_len(HSTORE_KEY(entries, base, i),
795 HSTORE_KEYLEN(entries, i));
796
797 out_datums[i * 2] = PointerGetDatum(key);
798 out_nulls[i * 2] = false;
799
800 if (HSTORE_VALISNULL(entries, i))
801 {
802 out_datums[i * 2 + 1] = (Datum) 0;
803 out_nulls[i * 2 + 1] = true;
804 }
805 else
806 {
807 text *item = cstring_to_text_with_len(HSTORE_VAL(entries, base, i),
808 HSTORE_VALLEN(entries, i));
809
810 out_datums[i * 2 + 1] = PointerGetDatum(item);
811 out_nulls[i * 2 + 1] = false;
812 }
813 }
814
815 return construct_md_array(out_datums, out_nulls,
816 ndims, out_size, lb,
817 TEXTOID, -1, false, TYPALIGN_INT);
818}
819
820 PG_FUNCTION_INFO_V1(hstore_to_array);
821Datum
822 hstore_to_array(PG_FUNCTION_ARGS)
823{
824 HStore *hs = PG_GETARG_HSTORE_P(0);
825 ArrayType *out = hstore_to_array_internal(hs, 1);
826
827 PG_RETURN_POINTER(out);
828}
829
830 PG_FUNCTION_INFO_V1(hstore_to_matrix);
831Datum
832 hstore_to_matrix(PG_FUNCTION_ARGS)
833{
834 HStore *hs = PG_GETARG_HSTORE_P(0);
835 ArrayType *out = hstore_to_array_internal(hs, 2);
836
837 PG_RETURN_POINTER(out);
838}
839
840/*
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)
847 */
848
849static void
850 setup_firstcall(FuncCallContext *funcctx, HStore *hs,
851 FunctionCallInfo fcinfo)
852{
853 MemoryContext oldcontext;
854 HStore *st;
855
856 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
857
858 st = (HStore *) palloc(VARSIZE(hs));
859 memcpy(st, hs, VARSIZE(hs));
860
861 funcctx->user_fctx = st;
862
863 if (fcinfo)
864 {
865 TupleDesc tupdesc;
866
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");
870
871 funcctx->tuple_desc = BlessTupleDesc(tupdesc);
872 }
873
874 MemoryContextSwitchTo(oldcontext);
875}
876
877
878 PG_FUNCTION_INFO_V1(hstore_skeys);
879Datum
880 hstore_skeys(PG_FUNCTION_ARGS)
881{
882 FuncCallContext *funcctx;
883 HStore *hs;
884 int i;
885
886 if (SRF_IS_FIRSTCALL())
887 {
888 hs = PG_GETARG_HSTORE_P(0);
889 funcctx = SRF_FIRSTCALL_INIT();
890 setup_firstcall(funcctx, hs, NULL);
891 }
892
893 funcctx = SRF_PERCALL_SETUP();
894 hs = (HStore *) funcctx->user_fctx;
895 i = funcctx->call_cntr;
896
897 if (i < HS_COUNT(hs))
898 {
899 HEntry *entries = ARRPTR(hs);
900 text *item;
901
902 item = cstring_to_text_with_len(HSTORE_KEY(entries, STRPTR(hs), i),
903 HSTORE_KEYLEN(entries, i));
904
905 SRF_RETURN_NEXT(funcctx, PointerGetDatum(item));
906 }
907
908 SRF_RETURN_DONE(funcctx);
909}
910
911
912 PG_FUNCTION_INFO_V1(hstore_svals);
913Datum
914 hstore_svals(PG_FUNCTION_ARGS)
915{
916 FuncCallContext *funcctx;
917 HStore *hs;
918 int i;
919
920 if (SRF_IS_FIRSTCALL())
921 {
922 hs = PG_GETARG_HSTORE_P(0);
923 funcctx = SRF_FIRSTCALL_INIT();
924 setup_firstcall(funcctx, hs, NULL);
925 }
926
927 funcctx = SRF_PERCALL_SETUP();
928 hs = (HStore *) funcctx->user_fctx;
929 i = funcctx->call_cntr;
930
931 if (i < HS_COUNT(hs))
932 {
933 HEntry *entries = ARRPTR(hs);
934
935 if (HSTORE_VALISNULL(entries, i))
936 {
937 ReturnSetInfo *rsi;
938
939 /* ugly ugly ugly. why no macro for this? */
940 (funcctx)->call_cntr++;
941 rsi = (ReturnSetInfo *) fcinfo->resultinfo;
942 rsi->isDone = ExprMultipleResult;
943 PG_RETURN_NULL();
944 }
945 else
946 {
947 text *item;
948
949 item = cstring_to_text_with_len(HSTORE_VAL(entries, STRPTR(hs), i),
950 HSTORE_VALLEN(entries, i));
951
952 SRF_RETURN_NEXT(funcctx, PointerGetDatum(item));
953 }
954 }
955
956 SRF_RETURN_DONE(funcctx);
957}
958
959
960 PG_FUNCTION_INFO_V1(hstore_contains);
961Datum
962 hstore_contains(PG_FUNCTION_ARGS)
963{
964 HStore *val = PG_GETARG_HSTORE_P(0);
965 HStore *tmpl = PG_GETARG_HSTORE_P(1);
966 bool res = true;
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);
972 int lastidx = 0;
973 int i;
974
975 /*
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
979 * search
980 */
981
982 for (i = 0; res && i < tcount; ++i)
983 {
984 int idx = hstoreFindKey(val, &lastidx,
985 HSTORE_KEY(te, tstr, i),
986 HSTORE_KEYLEN(te, i));
987
988 if (idx >= 0)
989 {
990 bool nullval = HSTORE_VALISNULL(te, i);
991 int vallen = HSTORE_VALLEN(te, i);
992
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),
997 vallen) != 0)))
998 res = false;
999 }
1000 else
1001 res = false;
1002 }
1003
1004 PG_RETURN_BOOL(res);
1005}
1006
1007
1008 PG_FUNCTION_INFO_V1(hstore_contained);
1009Datum
1010 hstore_contained(PG_FUNCTION_ARGS)
1011{
1012 PG_RETURN_DATUM(DirectFunctionCall2(hstore_contains,
1013 PG_GETARG_DATUM(1),
1014 PG_GETARG_DATUM(0)
1015 ));
1016}
1017
1018
1019 PG_FUNCTION_INFO_V1(hstore_each);
1020Datum
1021 hstore_each(PG_FUNCTION_ARGS)
1022{
1023 FuncCallContext *funcctx;
1024 HStore *hs;
1025 int i;
1026
1027 if (SRF_IS_FIRSTCALL())
1028 {
1029 hs = PG_GETARG_HSTORE_P(0);
1030 funcctx = SRF_FIRSTCALL_INIT();
1031 setup_firstcall(funcctx, hs, fcinfo);
1032 }
1033
1034 funcctx = SRF_PERCALL_SETUP();
1035 hs = (HStore *) funcctx->user_fctx;
1036 i = funcctx->call_cntr;
1037
1038 if (i < HS_COUNT(hs))
1039 {
1040 HEntry *entries = ARRPTR(hs);
1041 char *ptr = STRPTR(hs);
1042 Datum res,
1043 dvalues[2];
1044 bool nulls[2] = {false, false};
1045 text *item;
1046 HeapTuple tuple;
1047
1048 item = cstring_to_text_with_len(HSTORE_KEY(entries, ptr, i),
1049 HSTORE_KEYLEN(entries, i));
1050 dvalues[0] = PointerGetDatum(item);
1051
1052 if (HSTORE_VALISNULL(entries, i))
1053 {
1054 dvalues[1] = (Datum) 0;
1055 nulls[1] = true;
1056 }
1057 else
1058 {
1059 item = cstring_to_text_with_len(HSTORE_VAL(entries, ptr, i),
1060 HSTORE_VALLEN(entries, i));
1061 dvalues[1] = PointerGetDatum(item);
1062 }
1063
1064 tuple = heap_form_tuple(funcctx->tuple_desc, dvalues, nulls);
1065 res = HeapTupleGetDatum(tuple);
1066
1067 SRF_RETURN_NEXT(funcctx, res);
1068 }
1069
1070 SRF_RETURN_DONE(funcctx);
1071}
1072
1073
1074/*
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.
1078 */
1079
1080 PG_FUNCTION_INFO_V1(hstore_cmp);
1081Datum
1082 hstore_cmp(PG_FUNCTION_ARGS)
1083{
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);
1088 int res = 0;
1089
1090 if (hcount1 == 0 || hcount2 == 0)
1091 {
1092 /*
1093 * if either operand is empty, and the other is nonempty, the nonempty
1094 * one is larger. If both are empty they are equal.
1095 */
1096 if (hcount1 > 0)
1097 res = 1;
1098 else if (hcount2 > 0)
1099 res = -1;
1100 }
1101 else
1102 {
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]);
1110
1111 res = memcmp(str1, str2, Min(len1, len2));
1112
1113 if (res == 0)
1114 {
1115 if (len1 > len2)
1116 res = 1;
1117 else if (len1 < len2)
1118 res = -1;
1119 else if (hcount1 > hcount2)
1120 res = 1;
1121 else if (hcount2 > hcount1)
1122 res = -1;
1123 else
1124 {
1125 int count = hcount1 * 2;
1126 int i;
1127
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]))
1131 break;
1132 if (i < count)
1133 {
1134 if (HSE_ENDPOS(ent1[i]) < HSE_ENDPOS(ent2[i]))
1135 res = -1;
1136 else if (HSE_ENDPOS(ent1[i]) > HSE_ENDPOS(ent2[i]))
1137 res = 1;
1138 else if (HSE_ISNULL(ent1[i]))
1139 res = 1;
1140 else if (HSE_ISNULL(ent2[i]))
1141 res = -1;
1142 }
1143 }
1144 }
1145 else
1146 {
1147 res = (res > 0) ? 1 : -1;
1148 }
1149 }
1150
1151 /*
1152 * this is a btree support function; this is one of the few places where
1153 * memory needs to be explicitly freed.
1154 */
1155 PG_FREE_IF_COPY(hs1, 0);
1156 PG_FREE_IF_COPY(hs2, 1);
1157 PG_RETURN_INT32(res);
1158}
1159
1160
1161 PG_FUNCTION_INFO_V1(hstore_eq);
1162Datum
1163 hstore_eq(PG_FUNCTION_ARGS)
1164{
1165 int res = DatumGetInt32(DirectFunctionCall2(hstore_cmp,
1166 PG_GETARG_DATUM(0),
1167 PG_GETARG_DATUM(1)));
1168
1169 PG_RETURN_BOOL(res == 0);
1170}
1171
1172 PG_FUNCTION_INFO_V1(hstore_ne);
1173Datum
1174 hstore_ne(PG_FUNCTION_ARGS)
1175{
1176 int res = DatumGetInt32(DirectFunctionCall2(hstore_cmp,
1177 PG_GETARG_DATUM(0),
1178 PG_GETARG_DATUM(1)));
1179
1180 PG_RETURN_BOOL(res != 0);
1181}
1182
1183 PG_FUNCTION_INFO_V1(hstore_gt);
1184Datum
1185 hstore_gt(PG_FUNCTION_ARGS)
1186{
1187 int res = DatumGetInt32(DirectFunctionCall2(hstore_cmp,
1188 PG_GETARG_DATUM(0),
1189 PG_GETARG_DATUM(1)));
1190
1191 PG_RETURN_BOOL(res > 0);
1192}
1193
1194 PG_FUNCTION_INFO_V1(hstore_ge);
1195Datum
1196 hstore_ge(PG_FUNCTION_ARGS)
1197{
1198 int res = DatumGetInt32(DirectFunctionCall2(hstore_cmp,
1199 PG_GETARG_DATUM(0),
1200 PG_GETARG_DATUM(1)));
1201
1202 PG_RETURN_BOOL(res >= 0);
1203}
1204
1205 PG_FUNCTION_INFO_V1(hstore_lt);
1206Datum
1207 hstore_lt(PG_FUNCTION_ARGS)
1208{
1209 int res = DatumGetInt32(DirectFunctionCall2(hstore_cmp,
1210 PG_GETARG_DATUM(0),
1211 PG_GETARG_DATUM(1)));
1212
1213 PG_RETURN_BOOL(res < 0);
1214}
1215
1216 PG_FUNCTION_INFO_V1(hstore_le);
1217Datum
1218 hstore_le(PG_FUNCTION_ARGS)
1219{
1220 int res = DatumGetInt32(DirectFunctionCall2(hstore_cmp,
1221 PG_GETARG_DATUM(0),
1222 PG_GETARG_DATUM(1)));
1223
1224 PG_RETURN_BOOL(res <= 0);
1225}
1226
1227
1228 PG_FUNCTION_INFO_V1(hstore_hash);
1229Datum
1230 hstore_hash(PG_FUNCTION_ARGS)
1231{
1232 HStore *hs = PG_GETARG_HSTORE_P(0);
1233 Datum hval = hash_any((unsigned char *) VARDATA(hs),
1234 VARSIZE(hs) - VARHDRSZ);
1235
1236 /*
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.
1241 */
1242 Assert(VARSIZE(hs) ==
1243 (HS_COUNT(hs) != 0 ?
1244 CALCDATASIZE(HS_COUNT(hs),
1245 HSE_ENDPOS(ARRPTR(hs)[2 * HS_COUNT(hs) - 1])) :
1246 HSHRDSIZE));
1247
1248 PG_FREE_IF_COPY(hs, 0);
1249 PG_RETURN_DATUM(hval);
1250}
1251
1252 PG_FUNCTION_INFO_V1(hstore_hash_extended);
1253Datum
1254 hstore_hash_extended(PG_FUNCTION_ARGS)
1255{
1256 HStore *hs = PG_GETARG_HSTORE_P(0);
1257 uint64 seed = PG_GETARG_INT64(1);
1258 Datum hval;
1259
1260 hval = hash_any_extended((unsigned char *) VARDATA(hs),
1261 VARSIZE(hs) - VARHDRSZ,
1262 seed);
1263
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])) :
1269 HSHRDSIZE));
1270
1271 PG_FREE_IF_COPY(hs, 0);
1272 PG_RETURN_DATUM(hval);
1273}
Datum idx(PG_FUNCTION_ARGS)
Definition: _int_op.c:262
#define ARR_NDIM(a)
Definition: array.h:290
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:263
#define ARR_DIMS(a)
Definition: array.h:294
#define ARR_LBOUND(a)
Definition: array.h:296
ArrayType * construct_empty_array(Oid elmtype)
Definition: arrayfuncs.c:3581
void deconstruct_array_builtin(ArrayType *array, Oid elmtype, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3698
ArrayType * construct_md_array(Datum *elems, bool *nulls, int ndims, int *dims, int *lbs, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
Definition: arrayfuncs.c:3495
ArrayType * construct_array_builtin(Datum *elems, int nelems, Oid elmtype)
Definition: arrayfuncs.c:3382
#define Min(x, y)
Definition: c.h:1003
#define VARHDRSZ
Definition: c.h:697
uint64_t uint64
Definition: c.h:539
#define ARRPTR(x)
Definition: cube.c:28
int errcode(int sqlerrcode)
Definition: elog.c:854
int errmsg(const char *fmt,...)
Definition: elog.c:1071
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:226
#define ereport(elevel,...)
Definition: elog.h:150
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:2260
@ ExprMultipleResult
Definition: execnodes.h:328
#define MaxAllocSize
Definition: fe_memutils.h:22
#define PG_FREE_IF_COPY(ptr, n)
Definition: fmgr.h:260
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:309
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:684
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:268
#define PG_RETURN_NULL()
Definition: fmgr.h:345
#define PG_GETARG_INT64(n)
Definition: fmgr.h:283
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:372
#define PG_RETURN_INT32(x)
Definition: fmgr.h:354
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:353
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:361
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359
TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo, Oid *resultTypeId, TupleDesc *resultTupleDesc)
Definition: funcapi.c:276
#define SRF_IS_FIRSTCALL()
Definition: funcapi.h:304
#define SRF_PERCALL_SETUP()
Definition: funcapi.h:308
@ TYPEFUNC_COMPOSITE
Definition: funcapi.h:149
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition: funcapi.h:310
#define SRF_FIRSTCALL_INIT()
Definition: funcapi.h:306
static Datum HeapTupleGetDatum(const HeapTupleData *tuple)
Definition: funcapi.h:230
#define SRF_RETURN_DONE(_funcctx)
Definition: funcapi.h:328
Datum difference(PG_FUNCTION_ARGS)
Definition: fuzzystrmatch.c:778
static Datum hash_any_extended(const unsigned char *k, int keylen, uint64 seed)
Definition: hashfn.h:37
static Datum hash_any(const unsigned char *k, int keylen)
Definition: hashfn.h:31
Assert(PointerIsAligned(start, uint64))
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
Definition: heaptuple.c:1117
#define CALCDATASIZE(x, lenstr)
Definition: hstore.h:72
#define HS_COUNT(hsp_)
Definition: hstore.h:61
#define HS_FINALIZE(hsp_, count_, buf_, ptr_)
Definition: hstore.h:129
#define HSTORE_KEY(arr_, str_, i_)
Definition: hstore.h:79
#define HS_FIXSIZE(hsp_, count_)
Definition: hstore.h:143
#define PG_GETARG_HSTORE_P(x)
Definition: hstore.h:154
#define HSTORE_VALISNULL(arr_, i_)
Definition: hstore.h:83
#define HSTORE_VALLEN(arr_, i_)
Definition: hstore.h:82
#define HSE_ISNULL(he_)
Definition: hstore.h:29
#define HSTORE_KEYLEN(arr_, i_)
Definition: hstore.h:81
#define HS_SETCOUNT(hsp_, c_)
Definition: hstore.h:62
#define HS_COPYITEM(dent_, dbuf_, dptr_, sptr_, klen_, vlen_, vnull_)
Definition: hstore.h:99
#define HSTORE_VAL(arr_, str_, i_)
Definition: hstore.h:80
#define STRPTR(x)
Definition: hstore.h:76
#define HSHRDSIZE
Definition: hstore.h:71
#define HSE_ENDPOS(he_)
Definition: hstore.h:30
Datum hstore_contained(PG_FUNCTION_ARGS)
Definition: hstore_op.c:1010
Datum hstore_cmp(PG_FUNCTION_ARGS)
Definition: hstore_op.c:1082
Datum hstore_slice_to_array(PG_FUNCTION_ARGS)
Definition: hstore_op.c:569
Datum hstore_slice_to_hstore(PG_FUNCTION_ARGS)
Definition: hstore_op.c:630
Datum hstore_concat(PG_FUNCTION_ARGS)
Definition: hstore_op.c:471
Datum hstore_ne(PG_FUNCTION_ARGS)
Definition: hstore_op.c:1174
Datum hstore_contains(PG_FUNCTION_ARGS)
Definition: hstore_op.c:962
Datum hstore_hash(PG_FUNCTION_ARGS)
Definition: hstore_op.c:1230
Datum hstore_lt(PG_FUNCTION_ARGS)
Definition: hstore_op.c:1207
Datum hstore_each(PG_FUNCTION_ARGS)
Definition: hstore_op.c:1021
Datum hstore_eq(PG_FUNCTION_ARGS)
Definition: hstore_op.c:1163
Datum hstore_delete(PG_FUNCTION_ARGS)
Definition: hstore_op.c:245
Datum hstore_delete_hstore(PG_FUNCTION_ARGS)
Definition: hstore_op.c:371
HSTORE_POLLUTE(hstore_fetchval, fetchval)
Datum hstore_le(PG_FUNCTION_ARGS)
Definition: hstore_op.c:1218
Datum hstore_ge(PG_FUNCTION_ARGS)
Definition: hstore_op.c:1196
Datum hstore_to_matrix(PG_FUNCTION_ARGS)
Definition: hstore_op.c:832
Datum hstore_svals(PG_FUNCTION_ARGS)
Definition: hstore_op.c:914
Datum hstore_avals(PG_FUNCTION_ARGS)
Definition: hstore_op.c:726
Datum hstore_akeys(PG_FUNCTION_ARGS)
Definition: hstore_op.c:692
Datum hstore_fetchval(PG_FUNCTION_ARGS)
Definition: hstore_op.c:128
Datum hstore_delete_array(PG_FUNCTION_ARGS)
Definition: hstore_op.c:292
Datum hstore_skeys(PG_FUNCTION_ARGS)
Definition: hstore_op.c:880
static ArrayType * hstore_to_array_internal(HStore *hs, int ndims)
Definition: hstore_op.c:772
PG_FUNCTION_INFO_V1(hstore_fetchval)
int hstoreFindKey(HStore *hs, int *lowbound, char *key, int keylen)
Definition: hstore_op.c:36
Datum hstore_hash_extended(PG_FUNCTION_ARGS)
Definition: hstore_op.c:1254
Datum hstore_exists_any(PG_FUNCTION_ARGS)
Definition: hstore_op.c:162
Pairs * hstoreArrayToPairs(ArrayType *a, int *npairs)
Definition: hstore_op.c:73
Datum hstore_exists_all(PG_FUNCTION_ARGS)
Definition: hstore_op.c:196
Datum hstore_gt(PG_FUNCTION_ARGS)
Definition: hstore_op.c:1185
Datum hstore_defined(PG_FUNCTION_ARGS)
Definition: hstore_op.c:230
Datum hstore_to_array(PG_FUNCTION_ARGS)
Definition: hstore_op.c:822
Datum hstore_exists(PG_FUNCTION_ARGS)
Definition: hstore_op.c:149
static void setup_firstcall(FuncCallContext *funcctx, HStore *hs, FunctionCallInfo fcinfo)
Definition: hstore_op.c:850
#define hstoreUniquePairs
Definition: hstore_plperl.c:57
#define hstorePairs
Definition: hstore_plperl.c:58
struct parser_state ps
long val
Definition: informix.c:689
a
int a
Definition: isn.c:73
j
int j
Definition: isn.c:78
i
int i
Definition: isn.c:77
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:81
void * palloc(Size size)
Definition: mcxt.c:1365
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
const void size_t len
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:332
uint64_t Datum
Definition: postgres.h:70
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:322
static int32 DatumGetInt32(Datum X)
Definition: postgres.h:212
char * s1
char * s2
Definition: array.h:93
void * user_fctx
Definition: funcapi.h:82
uint64 call_cntr
Definition: funcapi.h:65
MemoryContext multi_call_memory_ctx
Definition: funcapi.h:101
TupleDesc tuple_desc
Definition: funcapi.h:112
Definition: hstore.h:19
Definition: hstore.h:45
Definition: hstore.h:162
char * val
Definition: hstore.h:164
bool isnull
Definition: hstore.h:167
size_t keylen
Definition: hstore.h:165
char * key
Definition: hstore.h:163
bool needfree
Definition: hstore.h:168
size_t vallen
Definition: hstore.h:166
ExprDoneCond isDone
Definition: execnodes.h:361
Definition: c.h:692
static Size VARSIZE_ANY_EXHDR(const void *PTR)
Definition: varatt.h:472
static Size VARSIZE(const void *PTR)
Definition: varatt.h:298
static char * VARDATA(const void *PTR)
Definition: varatt.h:305
static char * VARDATA_ANY(const void *PTR)
Definition: varatt.h:486
static void SET_VARSIZE(void *PTR, Size len)
Definition: varatt.h:432
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:193

AltStyle によって変換されたページ (->オリジナル) /