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 */
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  */
35 int
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 
72 Pairs *
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(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;
116  j++;
117  }
118  }
119 
120  *npairs = hstoreUniquePairs(key_pairs, j, &bufsiz);
121 
122  return key_pairs;
123 }
124 
125 
127 Datum
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,
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 
148 Datum
150 {
151  HStore *hs = PG_GETARG_HSTORE_P(0);
152  text *key = PG_GETARG_TEXT_PP(1);
153  int idx = hstoreFindKey(hs, NULL,
155 
156  PG_RETURN_BOOL(idx >= 0);
157 }
158 
159 
161 Datum
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 
191 }
192 
193 
195 Datum
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 
225 }
226 
227 
229 Datum
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,
237  bool res = (idx >= 0 && !HSTORE_VALISNULL(entries, idx));
238 
240 }
241 
242 
244 Datum
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 
291 Datum
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 
370 Datum
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 
470 Datum
472 {
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 
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 
568 Datum
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] =
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 
629 Datum
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 
691 Datum
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);
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 
721 }
722 
723 
725 Datum
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);
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 
768 }
769 
770 
771 static ArrayType *
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 
821 Datum
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 
831 Datum
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 
849 static void
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 = (void *) 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 
879 Datum
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 
913 Datum
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 
961 Datum
963 {
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 
1005 }
1006 
1007 
1009 Datum
1011 {
1013  PG_GETARG_DATUM(1),
1014  PG_GETARG_DATUM(0)
1015  ));
1016 }
1017 
1018 
1020 Datum
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 
1081 Datum
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);
1158 }
1159 
1160 
1162 Datum
1164 {
1166  PG_GETARG_DATUM(0),
1167  PG_GETARG_DATUM(1)));
1168 
1169  PG_RETURN_BOOL(res == 0);
1170 }
1171 
1173 Datum
1175 {
1177  PG_GETARG_DATUM(0),
1178  PG_GETARG_DATUM(1)));
1179 
1180  PG_RETURN_BOOL(res != 0);
1181 }
1182 
1184 Datum
1186 {
1188  PG_GETARG_DATUM(0),
1189  PG_GETARG_DATUM(1)));
1190 
1191  PG_RETURN_BOOL(res > 0);
1192 }
1193 
1195 Datum
1197 {
1199  PG_GETARG_DATUM(0),
1200  PG_GETARG_DATUM(1)));
1201 
1202  PG_RETURN_BOOL(res >= 0);
1203 }
1204 
1206 Datum
1208 {
1210  PG_GETARG_DATUM(0),
1211  PG_GETARG_DATUM(1)));
1212 
1213  PG_RETURN_BOOL(res < 0);
1214 }
1215 
1217 Datum
1219 {
1221  PG_GETARG_DATUM(0),
1222  PG_GETARG_DATUM(1)));
1223 
1224  PG_RETURN_BOOL(res <= 0);
1225 }
1226 
1227 
1229 Datum
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 
1253 Datum
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:259
#define ARR_NDIM(a)
Definition: array.h:283
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:256
#define ARR_DIMS(a)
Definition: array.h:287
#define ARR_LBOUND(a)
Definition: array.h:289
ArrayType * construct_array_builtin(Datum *elems, int nelems, Oid elmtype)
Definition: arrayfuncs.c:3363
ArrayType * construct_empty_array(Oid elmtype)
Definition: arrayfuncs.c:3551
void deconstruct_array_builtin(ArrayType *array, Oid elmtype, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3668
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:3465
#define Min(x, y)
Definition: c.h:937
#define VARHDRSZ
Definition: c.h:628
#define ARRPTR(x)
Definition: cube.c:25
int errcode(int sqlerrcode)
Definition: elog.c:858
int errmsg(const char *fmt,...)
Definition: elog.c:1069
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:2071
@ ExprMultipleResult
Definition: execnodes.h:296
#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:644
#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:303
#define SRF_PERCALL_SETUP()
Definition: funcapi.h:307
@ TYPEFUNC_COMPOSITE
Definition: funcapi.h:149
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition: funcapi.h:309
#define SRF_FIRSTCALL_INIT()
Definition: funcapi.h:305
static Datum HeapTupleGetDatum(const HeapTupleData *tuple)
Definition: funcapi.h:230
#define SRF_RETURN_DONE(_funcctx)
Definition: funcapi.h:327
Datum difference(PG_FUNCTION_ARGS)
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
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
#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
Pairs * hstoreArrayToPairs(ArrayType *a, int *npairs)
Definition: hstore_op.c:73
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
static ArrayType * hstore_to_array_internal(HStore *hs, int ndims)
Definition: hstore_op.c:772
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
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
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:54
#define hstorePairs
Definition: hstore_plperl.c:55
long val
Definition: informix.c:664
int a
Definition: isn.c:69
int j
Definition: isn.c:74
int i
Definition: isn.c:73
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:77
Assert(fmt[strlen(fmt) - 1] !='\n')
void * palloc(Size size)
Definition: mcxt.c:1199
#define MaxAllocSize
Definition: memutils.h:40
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:135
const void size_t len
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:670
uintptr_t Datum
Definition: postgres.h:412
#define VARDATA(PTR)
Definition: postgres.h:316
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:660
#define VARDATA_ANY(PTR)
Definition: postgres.h:362
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:343
#define VARSIZE(PTR)
Definition: postgres.h:317
static int32 DatumGetInt32(Datum X)
Definition: postgres.h:550
#define VARSIZE_ANY_EXHDR(PTR)
Definition: postgres.h:355
char * s1
char * s2
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:329
Definition: c.h:623
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:201