PostgreSQL Source Code  git master
hstore_io.c File Reference
#include "postgres.h"
#include <ctype.h>
#include "access/htup_details.h"
#include "catalog/pg_type.h"
#include "common/jsonapi.h"
#include "funcapi.h"
#include "hstore.h"
#include "lib/stringinfo.h"
#include "libpq/pqformat.h"
#include "utils/builtins.h"
#include "utils/json.h"
#include "utils/jsonb.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/typcache.h"
Include dependency graph for hstore_io.c:

Go to the source code of this file.

Data Structures

struct  HSParser
 
struct  ColumnIOData
 
struct  RecordIOData
 

Macros

#define RESIZEPRSBUF
 
#define GV_WAITVAL   0
 
#define GV_INVAL   1
 
#define GV_INESCVAL   2
 
#define GV_WAITESCIN   3
 
#define GV_WAITESCESCIN   4
 
#define WKEY   0
 
#define WVAL   1
 
#define WEQ   2
 
#define WGT   3
 
#define WDEL   4
 

Typedefs

typedef struct ColumnIOData ColumnIOData
 
typedef struct RecordIOData RecordIOData
 

Functions

 HSTORE_POLLUTE (hstore_from_text, tconvert)
 
static bool get_val (HSParser *state, bool ignoreeq, bool *escaped)
 
static void parse_hstore (HSParser *state)
 
static int comparePairs (const void *a, const void *b)
 
int hstoreUniquePairs (Pairs *a, int32 l, int32 *buflen)
 
size_t hstoreCheckKeyLen (size_t len)
 
size_t hstoreCheckValLen (size_t len)
 
HStorehstorePairs (Pairs *pairs, int32 pcount, int32 buflen)
 
 PG_FUNCTION_INFO_V1 (hstore_in)
 
Datum hstore_in (PG_FUNCTION_ARGS)
 
 PG_FUNCTION_INFO_V1 (hstore_recv)
 
Datum hstore_recv (PG_FUNCTION_ARGS)
 
 PG_FUNCTION_INFO_V1 (hstore_from_text)
 
Datum hstore_from_text (PG_FUNCTION_ARGS)
 
 PG_FUNCTION_INFO_V1 (hstore_from_arrays)
 
Datum hstore_from_arrays (PG_FUNCTION_ARGS)
 
 PG_FUNCTION_INFO_V1 (hstore_from_array)
 
Datum hstore_from_array (PG_FUNCTION_ARGS)
 
 PG_FUNCTION_INFO_V1 (hstore_from_record)
 
Datum hstore_from_record (PG_FUNCTION_ARGS)
 
 PG_FUNCTION_INFO_V1 (hstore_populate_record)
 
Datum hstore_populate_record (PG_FUNCTION_ARGS)
 
static char * cpw (char *dst, char *src, int len)
 
 PG_FUNCTION_INFO_V1 (hstore_out)
 
Datum hstore_out (PG_FUNCTION_ARGS)
 
 PG_FUNCTION_INFO_V1 (hstore_send)
 
Datum hstore_send (PG_FUNCTION_ARGS)
 
 PG_FUNCTION_INFO_V1 (hstore_to_json_loose)
 
Datum hstore_to_json_loose (PG_FUNCTION_ARGS)
 
 PG_FUNCTION_INFO_V1 (hstore_to_json)
 
Datum hstore_to_json (PG_FUNCTION_ARGS)
 
 PG_FUNCTION_INFO_V1 (hstore_to_jsonb)
 
Datum hstore_to_jsonb (PG_FUNCTION_ARGS)
 
 PG_FUNCTION_INFO_V1 (hstore_to_jsonb_loose)
 
Datum hstore_to_jsonb_loose (PG_FUNCTION_ARGS)
 

Variables

 PG_MODULE_MAGIC
 

Macro Definition Documentation

◆ GV_INESCVAL

#define GV_INESCVAL   2

Definition at line 55 of file hstore_io.c.

◆ GV_INVAL

#define GV_INVAL   1

Definition at line 54 of file hstore_io.c.

◆ GV_WAITESCESCIN

#define GV_WAITESCESCIN   4

Definition at line 57 of file hstore_io.c.

◆ GV_WAITESCIN

#define GV_WAITESCIN   3

Definition at line 56 of file hstore_io.c.

◆ GV_WAITVAL

#define GV_WAITVAL   0

Definition at line 53 of file hstore_io.c.

◆ RESIZEPRSBUF

#define RESIZEPRSBUF
Value:
do { \
if ( state->cur - state->word + 1 >= state->wordlen ) \
{ \
int32 clen = state->cur - state->word; \
state->wordlen *= 2; \
state->word = (char*)repalloc( (void*)state->word, state->wordlen ); \
state->cur = state->word + clen; \
} \
} while (0)
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1188
Definition: regguts.h:318

Definition at line 41 of file hstore_io.c.

◆ WDEL

#define WDEL   4

Definition at line 180 of file hstore_io.c.

◆ WEQ

#define WEQ   2

Definition at line 178 of file hstore_io.c.

◆ WGT

#define WGT   3

Definition at line 179 of file hstore_io.c.

◆ WKEY

#define WKEY   0

Definition at line 176 of file hstore_io.c.

◆ WVAL

#define WVAL   1

Definition at line 177 of file hstore_io.c.

Typedef Documentation

◆ ColumnIOData

typedef struct ColumnIOData ColumnIOData

◆ RecordIOData

typedef struct RecordIOData RecordIOData

Function Documentation

◆ comparePairs()

static int comparePairs ( const void *  a,
const void *  b 
)
static

Definition at line 289 of file hstore_io.c.

290 {
291  const Pairs *pa = a;
292  const Pairs *pb = b;
293 
294  if (pa->keylen == pb->keylen)
295  {
296  int res = memcmp(pa->key, pb->key, pa->keylen);
297 
298  if (res)
299  return res;
300 
301  /* guarantee that needfree will be later */
302  if (pb->needfree == pa->needfree)
303  return 0;
304  else if (pa->needfree)
305  return 1;
306  else
307  return -1;
308  }
309  return (pa->keylen > pb->keylen) ? 1 : -1;
310 }
int b
Definition: isn.c:70
int a
Definition: isn.c:69
Definition: hstore.h:162
size_t keylen
Definition: hstore.h:165
char * key
Definition: hstore.h:163
bool needfree
Definition: hstore.h:168

References a, b, Pairs::key, Pairs::keylen, Pairs::needfree, and res.

Referenced by hstoreUniquePairs().

◆ cpw()

static char* cpw ( char *  dst,
char *  src,
int  len 
)
static

Definition at line 1146 of file hstore_io.c.

1147 {
1148  char *ptr = src;
1149 
1150  while (ptr - src < len)
1151  {
1152  if (*ptr == '"' || *ptr == '\\')
1153  *dst++ = '\\';
1154  *dst++ = *ptr++;
1155  }
1156  return dst;
1157 }
const void size_t len

References len.

Referenced by hstore_out().

◆ get_val()

static bool get_val ( HSParser state,
bool  ignoreeq,
bool escaped 
)
static

Definition at line 60 of file hstore_io.c.

61 {
62  int st = GV_WAITVAL;
63 
64  state->wordlen = 32;
65  state->cur = state->word = palloc(state->wordlen);
66  *escaped = false;
67 
68  while (1)
69  {
70  if (st == GV_WAITVAL)
71  {
72  if (*(state->ptr) == '"')
73  {
74  *escaped = true;
75  st = GV_INESCVAL;
76  }
77  else if (*(state->ptr) == '\0')
78  {
79  return false;
80  }
81  else if (*(state->ptr) == '=' && !ignoreeq)
82  {
83  elog(ERROR, "Syntax error near \"%.*s\" at position %d",
84  pg_mblen(state->ptr), state->ptr,
85  (int32) (state->ptr - state->begin));
86  }
87  else if (*(state->ptr) == '\\')
88  {
89  st = GV_WAITESCIN;
90  }
91  else if (!isspace((unsigned char) *(state->ptr)))
92  {
93  *(state->cur) = *(state->ptr);
94  state->cur++;
95  st = GV_INVAL;
96  }
97  }
98  else if (st == GV_INVAL)
99  {
100  if (*(state->ptr) == '\\')
101  {
102  st = GV_WAITESCIN;
103  }
104  else if (*(state->ptr) == '=' && !ignoreeq)
105  {
106  state->ptr--;
107  return true;
108  }
109  else if (*(state->ptr) == ',' && ignoreeq)
110  {
111  state->ptr--;
112  return true;
113  }
114  else if (isspace((unsigned char) *(state->ptr)))
115  {
116  return true;
117  }
118  else if (*(state->ptr) == '\0')
119  {
120  state->ptr--;
121  return true;
122  }
123  else
124  {
125  RESIZEPRSBUF;
126  *(state->cur) = *(state->ptr);
127  state->cur++;
128  }
129  }
130  else if (st == GV_INESCVAL)
131  {
132  if (*(state->ptr) == '\\')
133  {
134  st = GV_WAITESCESCIN;
135  }
136  else if (*(state->ptr) == '"')
137  {
138  return true;
139  }
140  else if (*(state->ptr) == '\0')
141  {
142  elog(ERROR, "Unexpected end of string");
143  }
144  else
145  {
146  RESIZEPRSBUF;
147  *(state->cur) = *(state->ptr);
148  state->cur++;
149  }
150  }
151  else if (st == GV_WAITESCIN)
152  {
153  if (*(state->ptr) == '\0')
154  elog(ERROR, "Unexpected end of string");
155  RESIZEPRSBUF;
156  *(state->cur) = *(state->ptr);
157  state->cur++;
158  st = GV_INVAL;
159  }
160  else if (st == GV_WAITESCESCIN)
161  {
162  if (*(state->ptr) == '\0')
163  elog(ERROR, "Unexpected end of string");
164  RESIZEPRSBUF;
165  *(state->cur) = *(state->ptr);
166  state->cur++;
167  st = GV_INESCVAL;
168  }
169  else
170  elog(ERROR, "Unknown state %d at position line %d in file '%s'", st, __LINE__, __FILE__);
171 
172  state->ptr++;
173  }
174 }
signed int int32
Definition: c.h:440
#define ERROR
Definition: elog.h:33
#define GV_INVAL
Definition: hstore_io.c:54
#define GV_WAITESCESCIN
Definition: hstore_io.c:57
#define GV_INESCVAL
Definition: hstore_io.c:55
#define RESIZEPRSBUF
Definition: hstore_io.c:41
#define GV_WAITVAL
Definition: hstore_io.c:53
#define GV_WAITESCIN
Definition: hstore_io.c:56
int pg_mblen(const char *mbstr)
Definition: mbutils.c:966
void * palloc(Size size)
Definition: mcxt.c:1068

References elog(), ERROR, GV_INESCVAL, GV_INVAL, GV_WAITESCESCIN, GV_WAITESCIN, GV_WAITVAL, palloc(), pg_mblen(), and RESIZEPRSBUF.

Referenced by parse_hstore().

◆ hstore_from_array()

Datum hstore_from_array ( PG_FUNCTION_ARGS  )

Definition at line 654 of file hstore_io.c.

655 {
656  ArrayType *in_array = PG_GETARG_ARRAYTYPE_P(0);
657  int ndims = ARR_NDIM(in_array);
658  int count;
659  int32 buflen;
660  HStore *out;
661  Pairs *pairs;
662  Datum *in_datums;
663  bool *in_nulls;
664  int in_count;
665  int i;
666 
667  Assert(ARR_ELEMTYPE(in_array) == TEXTOID);
668 
669  switch (ndims)
670  {
671  case 0:
672  out = hstorePairs(NULL, 0, 0);
673  PG_RETURN_POINTER(out);
674 
675  case 1:
676  if ((ARR_DIMS(in_array)[0]) % 2)
677  ereport(ERROR,
678  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
679  errmsg("array must have even number of elements")));
680  break;
681 
682  case 2:
683  if ((ARR_DIMS(in_array)[1]) != 2)
684  ereport(ERROR,
685  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
686  errmsg("array must have two columns")));
687  break;
688 
689  default:
690  ereport(ERROR,
691  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
692  errmsg("wrong number of array subscripts")));
693  }
694 
695  deconstruct_array_builtin(in_array, TEXTOID, &in_datums, &in_nulls, &in_count);
696 
697  count = in_count / 2;
698 
699  /* see discussion in hstoreArrayToPairs() */
700  if (count > MaxAllocSize / sizeof(Pairs))
701  ereport(ERROR,
702  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
703  errmsg("number of pairs (%d) exceeds the maximum allowed (%d)",
704  count, (int) (MaxAllocSize / sizeof(Pairs)))));
705 
706  pairs = palloc(count * sizeof(Pairs));
707 
708  for (i = 0; i < count; ++i)
709  {
710  if (in_nulls[i * 2])
711  ereport(ERROR,
712  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
713  errmsg("null value not allowed for hstore key")));
714 
715  if (in_nulls[i * 2 + 1])
716  {
717  pairs[i].key = VARDATA(in_datums[i * 2]);
718  pairs[i].val = NULL;
719  pairs[i].keylen =
720  hstoreCheckKeyLen(VARSIZE(in_datums[i * 2]) - VARHDRSZ);
721  pairs[i].vallen = 4;
722  pairs[i].isnull = true;
723  pairs[i].needfree = false;
724  }
725  else
726  {
727  pairs[i].key = VARDATA(in_datums[i * 2]);
728  pairs[i].val = VARDATA(in_datums[i * 2 + 1]);
729  pairs[i].keylen =
730  hstoreCheckKeyLen(VARSIZE(in_datums[i * 2]) - VARHDRSZ);
731  pairs[i].vallen =
732  hstoreCheckValLen(VARSIZE(in_datums[i * 2 + 1]) - VARHDRSZ);
733  pairs[i].isnull = false;
734  pairs[i].needfree = false;
735  }
736  }
737 
738  count = hstoreUniquePairs(pairs, count, &buflen);
739 
740  out = hstorePairs(pairs, count, buflen);
741 
742  PG_RETURN_POINTER(out);
743 }
#define ARR_NDIM(a)
Definition: array.h:283
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:256
#define ARR_ELEMTYPE(a)
Definition: array.h:285
#define ARR_DIMS(a)
Definition: array.h:287
void deconstruct_array_builtin(ArrayType *array, Oid elmtype, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3643
#define VARHDRSZ
Definition: c.h:638
int errcode(int sqlerrcode)
Definition: elog.c:693
int errmsg(const char *fmt,...)
Definition: elog.c:904
#define ereport(elevel,...)
Definition: elog.h:143
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:361
HStore * hstorePairs(Pairs *pairs, int32 pcount, int32 buflen)
Definition: hstore_io.c:388
size_t hstoreCheckValLen(size_t len)
Definition: hstore_io.c:377
size_t hstoreCheckKeyLen(size_t len)
Definition: hstore_io.c:367
int hstoreUniquePairs(Pairs *a, int32 l, int32 *buflen)
Definition: hstore_io.c:319
int i
Definition: isn.c:73
Assert(fmt[strlen(fmt) - 1] !='\n')
#define MaxAllocSize
Definition: memutils.h:40
uintptr_t Datum
Definition: postgres.h:411
#define VARDATA(PTR)
Definition: postgres.h:315
#define VARSIZE(PTR)
Definition: postgres.h:316
Definition: hstore.h:45
char * val
Definition: hstore.h:164
bool isnull
Definition: hstore.h:167
size_t vallen
Definition: hstore.h:166

References ARR_DIMS, ARR_ELEMTYPE, ARR_NDIM, Assert(), deconstruct_array_builtin(), ereport, errcode(), errmsg(), ERROR, hstoreCheckKeyLen(), hstoreCheckValLen(), hstorePairs(), hstoreUniquePairs(), i, Pairs::isnull, Pairs::key, Pairs::keylen, MaxAllocSize, Pairs::needfree, palloc(), PG_GETARG_ARRAYTYPE_P, PG_RETURN_POINTER, Pairs::val, Pairs::vallen, VARDATA, VARHDRSZ, and VARSIZE.

◆ hstore_from_arrays()

Datum hstore_from_arrays ( PG_FUNCTION_ARGS  )

Definition at line 538 of file hstore_io.c.

539 {
540  int32 buflen;
541  HStore *out;
542  Pairs *pairs;
543  Datum *key_datums;
544  bool *key_nulls;
545  int key_count;
546  Datum *value_datums;
547  bool *value_nulls;
548  int value_count;
549  ArrayType *key_array;
550  ArrayType *value_array;
551  int i;
552 
553  if (PG_ARGISNULL(0))
554  PG_RETURN_NULL();
555 
556  key_array = PG_GETARG_ARRAYTYPE_P(0);
557 
558  Assert(ARR_ELEMTYPE(key_array) == TEXTOID);
559 
560  /*
561  * must check >1 rather than != 1 because empty arrays have 0 dimensions,
562  * not 1
563  */
564 
565  if (ARR_NDIM(key_array) > 1)
566  ereport(ERROR,
567  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
568  errmsg("wrong number of array subscripts")));
569 
570  deconstruct_array_builtin(key_array, TEXTOID, &key_datums, &key_nulls, &key_count);
571 
572  /* see discussion in hstoreArrayToPairs() */
573  if (key_count > MaxAllocSize / sizeof(Pairs))
574  ereport(ERROR,
575  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
576  errmsg("number of pairs (%d) exceeds the maximum allowed (%d)",
577  key_count, (int) (MaxAllocSize / sizeof(Pairs)))));
578 
579  /* value_array might be NULL */
580 
581  if (PG_ARGISNULL(1))
582  {
583  value_array = NULL;
584  value_count = key_count;
585  value_datums = NULL;
586  value_nulls = NULL;
587  }
588  else
589  {
590  value_array = PG_GETARG_ARRAYTYPE_P(1);
591 
592  Assert(ARR_ELEMTYPE(value_array) == TEXTOID);
593 
594  if (ARR_NDIM(value_array) > 1)
595  ereport(ERROR,
596  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
597  errmsg("wrong number of array subscripts")));
598 
599  if ((ARR_NDIM(key_array) > 0 || ARR_NDIM(value_array) > 0) &&
600  (ARR_NDIM(key_array) != ARR_NDIM(value_array) ||
601  ARR_DIMS(key_array)[0] != ARR_DIMS(value_array)[0] ||
602  ARR_LBOUND(key_array)[0] != ARR_LBOUND(value_array)[0]))
603  ereport(ERROR,
604  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
605  errmsg("arrays must have same bounds")));
606 
607  deconstruct_array_builtin(value_array, TEXTOID, &value_datums, &value_nulls, &value_count);
608 
609  Assert(key_count == value_count);
610  }
611 
612  pairs = palloc(key_count * sizeof(Pairs));
613 
614  for (i = 0; i < key_count; ++i)
615  {
616  if (key_nulls[i])
617  ereport(ERROR,
618  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
619  errmsg("null value not allowed for hstore key")));
620 
621  if (!value_nulls || value_nulls[i])
622  {
623  pairs[i].key = VARDATA(key_datums[i]);
624  pairs[i].val = NULL;
625  pairs[i].keylen =
626  hstoreCheckKeyLen(VARSIZE(key_datums[i]) - VARHDRSZ);
627  pairs[i].vallen = 4;
628  pairs[i].isnull = true;
629  pairs[i].needfree = false;
630  }
631  else
632  {
633  pairs[i].key = VARDATA(key_datums[i]);
634  pairs[i].val = VARDATA(value_datums[i]);
635  pairs[i].keylen =
636  hstoreCheckKeyLen(VARSIZE(key_datums[i]) - VARHDRSZ);
637  pairs[i].vallen =
638  hstoreCheckValLen(VARSIZE(value_datums[i]) - VARHDRSZ);
639  pairs[i].isnull = false;
640  pairs[i].needfree = false;
641  }
642  }
643 
644  key_count = hstoreUniquePairs(pairs, key_count, &buflen);
645 
646  out = hstorePairs(pairs, key_count, buflen);
647 
648  PG_RETURN_POINTER(out);
649 }
#define ARR_LBOUND(a)
Definition: array.h:289
#define PG_ARGISNULL(n)
Definition: fmgr.h:209
#define PG_RETURN_NULL()
Definition: fmgr.h:345

References ARR_DIMS, ARR_ELEMTYPE, ARR_LBOUND, ARR_NDIM, Assert(), deconstruct_array_builtin(), ereport, errcode(), errmsg(), ERROR, hstoreCheckKeyLen(), hstoreCheckValLen(), hstorePairs(), hstoreUniquePairs(), i, Pairs::isnull, Pairs::key, Pairs::keylen, MaxAllocSize, Pairs::needfree, palloc(), PG_ARGISNULL, PG_GETARG_ARRAYTYPE_P, PG_RETURN_NULL, PG_RETURN_POINTER, Pairs::val, Pairs::vallen, VARDATA, VARHDRSZ, and VARSIZE.

◆ hstore_from_record()

Datum hstore_from_record ( PG_FUNCTION_ARGS  )

Definition at line 770 of file hstore_io.c.

771 {
772  HeapTupleHeader rec;
773  int32 buflen;
774  HStore *out;
775  Pairs *pairs;
776  Oid tupType;
777  int32 tupTypmod;
778  TupleDesc tupdesc;
779  HeapTupleData tuple;
780  RecordIOData *my_extra;
781  int ncolumns;
782  int i,
783  j;
784  Datum *values;
785  bool *nulls;
786 
787  if (PG_ARGISNULL(0))
788  {
789  Oid argtype = get_fn_expr_argtype(fcinfo->flinfo, 0);
790 
791  /*
792  * We have no tuple to look at, so the only source of type info is the
793  * argtype --- which might be domain over composite, but we don't care
794  * here, since we have no need to be concerned about domain
795  * constraints. The lookup_rowtype_tupdesc_domain call below will
796  * error out if we don't have a known composite type oid here.
797  */
798  tupType = argtype;
799  tupTypmod = -1;
800 
801  rec = NULL;
802  }
803  else
804  {
805  rec = PG_GETARG_HEAPTUPLEHEADER(0);
806 
807  /*
808  * Extract type info from the tuple itself -- this will work even for
809  * anonymous record types.
810  */
811  tupType = HeapTupleHeaderGetTypeId(rec);
812  tupTypmod = HeapTupleHeaderGetTypMod(rec);
813  }
814 
815  tupdesc = lookup_rowtype_tupdesc_domain(tupType, tupTypmod, false);
816  ncolumns = tupdesc->natts;
817 
818  /*
819  * We arrange to look up the needed I/O info just once per series of
820  * calls, assuming the record type doesn't change underneath us.
821  */
822  my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra;
823  if (my_extra == NULL ||
824  my_extra->ncolumns != ncolumns)
825  {
826  fcinfo->flinfo->fn_extra =
827  MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
828  offsetof(RecordIOData, columns) +
829  ncolumns * sizeof(ColumnIOData));
830  my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra;
831  my_extra->record_type = InvalidOid;
832  my_extra->record_typmod = 0;
833  }
834 
835  if (my_extra->record_type != tupType ||
836  my_extra->record_typmod != tupTypmod)
837  {
838  MemSet(my_extra, 0,
839  offsetof(RecordIOData, columns) +
840  ncolumns * sizeof(ColumnIOData));
841  my_extra->record_type = tupType;
842  my_extra->record_typmod = tupTypmod;
843  my_extra->ncolumns = ncolumns;
844  }
845 
846  Assert(ncolumns <= MaxTupleAttributeNumber); /* thus, no overflow */
847  pairs = palloc(ncolumns * sizeof(Pairs));
848 
849  if (rec)
850  {
851  /* Build a temporary HeapTuple control structure */
853  ItemPointerSetInvalid(&(tuple.t_self));
854  tuple.t_tableOid = InvalidOid;
855  tuple.t_data = rec;
856 
857  values = (Datum *) palloc(ncolumns * sizeof(Datum));
858  nulls = (bool *) palloc(ncolumns * sizeof(bool));
859 
860  /* Break down the tuple into fields */
861  heap_deform_tuple(&tuple, tupdesc, values, nulls);
862  }
863  else
864  {
865  values = NULL;
866  nulls = NULL;
867  }
868 
869  for (i = 0, j = 0; i < ncolumns; ++i)
870  {
871  ColumnIOData *column_info = &my_extra->columns[i];
872  Form_pg_attribute att = TupleDescAttr(tupdesc, i);
873  Oid column_type = att->atttypid;
874  char *value;
875 
876  /* Ignore dropped columns in datatype */
877  if (att->attisdropped)
878  continue;
879 
880  pairs[j].key = NameStr(att->attname);
881  pairs[j].keylen = hstoreCheckKeyLen(strlen(NameStr(att->attname)));
882 
883  if (!nulls || nulls[i])
884  {
885  pairs[j].val = NULL;
886  pairs[j].vallen = 4;
887  pairs[j].isnull = true;
888  pairs[j].needfree = false;
889  ++j;
890  continue;
891  }
892 
893  /*
894  * Convert the column value to text
895  */
896  if (column_info->column_type != column_type)
897  {
898  bool typIsVarlena;
899 
900  getTypeOutputInfo(column_type,
901  &column_info->typiofunc,
902  &typIsVarlena);
903  fmgr_info_cxt(column_info->typiofunc, &column_info->proc,
904  fcinfo->flinfo->fn_mcxt);
905  column_info->column_type = column_type;
906  }
907 
908  value = OutputFunctionCall(&column_info->proc, values[i]);
909 
910  pairs[j].val = value;
911  pairs[j].vallen = hstoreCheckValLen(strlen(value));
912  pairs[j].isnull = false;
913  pairs[j].needfree = false;
914  ++j;
915  }
916 
917  ncolumns = hstoreUniquePairs(pairs, j, &buflen);
918 
919  out = hstorePairs(pairs, ncolumns, buflen);
920 
921  ReleaseTupleDesc(tupdesc);
922 
923  PG_RETURN_POINTER(out);
924 }
static Datum values[MAXATTR]
Definition: bootstrap.c:156
#define NameStr(name)
Definition: c.h:692
#define offsetof(type, field)
Definition: c.h:738
#define MemSet(start, val, len)
Definition: c.h:1019
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:136
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
Definition: fmgr.c:1786
char * OutputFunctionCall(FmgrInfo *flinfo, Datum val)
Definition: fmgr.c:1559
#define PG_GETARG_HEAPTUPLEHEADER(n)
Definition: fmgr.h:312
void heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *values, bool *isnull)
Definition: heaptuple.c:1249
#define HeapTupleHeaderGetTypMod(tup)
Definition: htup_details.h:462
#define HeapTupleHeaderGetTypeId(tup)
Definition: htup_details.h:452
#define MaxTupleAttributeNumber
Definition: htup_details.h:33
#define HeapTupleHeaderGetDatumLength(tup)
Definition: htup_details.h:446
static struct @151 value
int j
Definition: isn.c:74
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:77
#define ItemPointerSetInvalid(pointer)
Definition: itemptr.h:172
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2864
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:863
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:207
#define InvalidOid
Definition: postgres_ext.h:36
unsigned int Oid
Definition: postgres_ext.h:31
FmgrInfo proc
Definition: hstore_io.c:755
Oid column_type
Definition: hstore_io.c:752
MemoryContext fn_mcxt
Definition: fmgr.h:65
ItemPointerData t_self
Definition: htup.h:65
uint32 t_len
Definition: htup.h:64
HeapTupleHeader t_data
Definition: htup.h:68
Oid t_tableOid
Definition: htup.h:66
ColumnIOData columns[FLEXIBLE_ARRAY_MEMBER]
Definition: hstore_io.c:765
Oid record_type
Definition: hstore_io.c:760
int32 record_typmod
Definition: hstore_io.c:761
#define ReleaseTupleDesc(tupdesc)
Definition: tupdesc.h:122
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
TupleDesc lookup_rowtype_tupdesc_domain(Oid type_id, int32 typmod, bool noError)
Definition: typcache.c:1886

References Assert(), ColumnIOData::column_type, RecordIOData::columns, fmgr_info_cxt(), FmgrInfo::fn_mcxt, get_fn_expr_argtype(), getTypeOutputInfo(), heap_deform_tuple(), HeapTupleHeaderGetDatumLength, HeapTupleHeaderGetTypeId, HeapTupleHeaderGetTypMod, hstoreCheckKeyLen(), hstoreCheckValLen(), hstorePairs(), hstoreUniquePairs(), i, if(), InvalidOid, Pairs::isnull, ItemPointerSetInvalid, j, Pairs::key, Pairs::keylen, lookup_rowtype_tupdesc_domain(), MaxTupleAttributeNumber, MemoryContextAlloc(), MemSet, NameStr, TupleDescData::natts, RecordIOData::ncolumns, Pairs::needfree, offsetof, OutputFunctionCall(), palloc(), PG_ARGISNULL, PG_GETARG_HEAPTUPLEHEADER, PG_RETURN_POINTER, ColumnIOData::proc, RecordIOData::record_type, RecordIOData::record_typmod, ReleaseTupleDesc, HeapTupleData::t_data, HeapTupleData::t_len, HeapTupleData::t_self, HeapTupleData::t_tableOid, TupleDescAttr, ColumnIOData::typiofunc, Pairs::val, Pairs::vallen, value, and values.

◆ hstore_from_text()

Datum hstore_from_text ( PG_FUNCTION_ARGS  )

Definition at line 502 of file hstore_io.c.

503 {
504  text *key;
505  text *val = NULL;
506  Pairs p;
507  HStore *out;
508 
509  if (PG_ARGISNULL(0))
510  PG_RETURN_NULL();
511 
512  p.needfree = false;
513  key = PG_GETARG_TEXT_PP(0);
514  p.key = VARDATA_ANY(key);
516 
517  if (PG_ARGISNULL(1))
518  {
519  p.vallen = 0;
520  p.isnull = true;
521  }
522  else
523  {
524  val = PG_GETARG_TEXT_PP(1);
525  p.val = VARDATA_ANY(val);
527  p.isnull = false;
528  }
529 
530  out = hstorePairs(&p, 1, p.keylen + p.vallen);
531 
532  PG_RETURN_POINTER(out);
533 }
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:309
long val
Definition: informix.c:664
#define VARDATA_ANY(PTR)
Definition: postgres.h:361
#define VARSIZE_ANY_EXHDR(PTR)
Definition: postgres.h:354
Definition: c.h:633

References hstoreCheckKeyLen(), hstoreCheckValLen(), hstorePairs(), Pairs::isnull, Pairs::key, sort-test::key, Pairs::keylen, Pairs::needfree, PG_ARGISNULL, PG_GETARG_TEXT_PP, PG_RETURN_NULL, PG_RETURN_POINTER, Pairs::val, val, Pairs::vallen, VARDATA_ANY, and VARSIZE_ANY_EXHDR.

◆ hstore_in()

Datum hstore_in ( PG_FUNCTION_ARGS  )

Definition at line 419 of file hstore_io.c.

420 {
421  HSParser state;
422  int32 buflen;
423  HStore *out;
424 
425  state.begin = PG_GETARG_CSTRING(0);
426 
428 
429  state.pcur = hstoreUniquePairs(state.pairs, state.pcur, &buflen);
430 
431  out = hstorePairs(state.pairs, state.pcur, buflen);
432 
433  PG_RETURN_POINTER(out);
434 }
#define PG_GETARG_CSTRING(n)
Definition: fmgr.h:277
static void parse_hstore(HSParser *state)
Definition: hstore_io.c:184

References hstorePairs(), hstoreUniquePairs(), parse_hstore(), PG_GETARG_CSTRING, and PG_RETURN_POINTER.

◆ hstore_out()

Datum hstore_out ( PG_FUNCTION_ARGS  )

Definition at line 1161 of file hstore_io.c.

1162 {
1163  HStore *in = PG_GETARG_HSTORE_P(0);
1164  int buflen,
1165  i;
1166  int count = HS_COUNT(in);
1167  char *out,
1168  *ptr;
1169  char *base = STRPTR(in);
1170  HEntry *entries = ARRPTR(in);
1171 
1172  if (count == 0)
1174 
1175  buflen = 0;
1176 
1177  /*
1178  * this loop overestimates due to pessimistic assumptions about escaping,
1179  * so very large hstore values can't be output. this could be fixed, but
1180  * many other data types probably have the same issue. This replaced code
1181  * that used the original varlena size for calculations, which was wrong
1182  * in some subtle ways.
1183  */
1184 
1185  for (i = 0; i < count; i++)
1186  {
1187  /* include "" and => and comma-space */
1188  buflen += 6 + 2 * HSTORE_KEYLEN(entries, i);
1189  /* include "" only if nonnull */
1190  buflen += 2 + (HSTORE_VALISNULL(entries, i)
1191  ? 2
1192  : 2 * HSTORE_VALLEN(entries, i));
1193  }
1194 
1195  out = ptr = palloc(buflen);
1196 
1197  for (i = 0; i < count; i++)
1198  {
1199  *ptr++ = '"';
1200  ptr = cpw(ptr, HSTORE_KEY(entries, base, i), HSTORE_KEYLEN(entries, i));
1201  *ptr++ = '"';
1202  *ptr++ = '=';
1203  *ptr++ = '>';
1204  if (HSTORE_VALISNULL(entries, i))
1205  {
1206  *ptr++ = 'N';
1207  *ptr++ = 'U';
1208  *ptr++ = 'L';
1209  *ptr++ = 'L';
1210  }
1211  else
1212  {
1213  *ptr++ = '"';
1214  ptr = cpw(ptr, HSTORE_VAL(entries, base, i), HSTORE_VALLEN(entries, i));
1215  *ptr++ = '"';
1216  }
1217 
1218  if (i + 1 != count)
1219  {
1220  *ptr++ = ',';
1221  *ptr++ = ' ';
1222  }
1223  }
1224  *ptr = '\0';
1225 
1226  PG_RETURN_CSTRING(out);
1227 }
#define ARRPTR(x)
Definition: cube.c:25
#define PG_RETURN_CSTRING(x)
Definition: fmgr.h:362
#define HS_COUNT(hsp_)
Definition: hstore.h:61
#define HSTORE_KEY(arr_, str_, i_)
Definition: hstore.h:79
#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 HSTORE_KEYLEN(arr_, i_)
Definition: hstore.h:81
#define HSTORE_VAL(arr_, str_, i_)
Definition: hstore.h:80
#define STRPTR(x)
Definition: hstore.h:76
static char * cpw(char *dst, char *src, int len)
Definition: hstore_io.c:1146
char * pstrdup(const char *in)
Definition: mcxt.c:1305
Definition: hstore.h:19

References ARRPTR, cpw(), HS_COUNT, HSTORE_KEY, HSTORE_KEYLEN, HSTORE_VAL, HSTORE_VALISNULL, HSTORE_VALLEN, i, palloc(), PG_GETARG_HSTORE_P, PG_RETURN_CSTRING, pstrdup(), and STRPTR.

◆ HSTORE_POLLUTE()

HSTORE_POLLUTE ( hstore_from_text  ,
tconvert   
)

◆ hstore_populate_record()

Datum hstore_populate_record ( PG_FUNCTION_ARGS  )

Definition at line 929 of file hstore_io.c.

930 {
931  Oid argtype = get_fn_expr_argtype(fcinfo->flinfo, 0);
932  HStore *hs;
933  HEntry *entries;
934  char *ptr;
935  HeapTupleHeader rec;
936  Oid tupType;
937  int32 tupTypmod;
938  TupleDesc tupdesc;
939  HeapTupleData tuple;
940  HeapTuple rettuple;
941  RecordIOData *my_extra;
942  int ncolumns;
943  int i;
944  Datum *values;
945  bool *nulls;
946 
947  if (!type_is_rowtype(argtype))
948  ereport(ERROR,
949  (errcode(ERRCODE_DATATYPE_MISMATCH),
950  errmsg("first argument must be a rowtype")));
951 
952  if (PG_ARGISNULL(0))
953  {
954  if (PG_ARGISNULL(1))
955  PG_RETURN_NULL();
956 
957  rec = NULL;
958 
959  /*
960  * We have no tuple to look at, so the only source of type info is the
961  * argtype. The lookup_rowtype_tupdesc_domain call below will error
962  * out if we don't have a known composite type oid here.
963  */
964  tupType = argtype;
965  tupTypmod = -1;
966  }
967  else
968  {
969  rec = PG_GETARG_HEAPTUPLEHEADER(0);
970 
971  if (PG_ARGISNULL(1))
972  PG_RETURN_POINTER(rec);
973 
974  /*
975  * Extract type info from the tuple itself -- this will work even for
976  * anonymous record types.
977  */
978  tupType = HeapTupleHeaderGetTypeId(rec);
979  tupTypmod = HeapTupleHeaderGetTypMod(rec);
980  }
981 
982  hs = PG_GETARG_HSTORE_P(1);
983  entries = ARRPTR(hs);
984  ptr = STRPTR(hs);
985 
986  /*
987  * if the input hstore is empty, we can only skip the rest if we were
988  * passed in a non-null record, since otherwise there may be issues with
989  * domain nulls.
990  */
991 
992  if (HS_COUNT(hs) == 0 && rec)
993  PG_RETURN_POINTER(rec);
994 
995  /*
996  * Lookup the input record's tupdesc. For the moment, we don't worry
997  * about whether it is a domain over composite.
998  */
999  tupdesc = lookup_rowtype_tupdesc_domain(tupType, tupTypmod, false);
1000  ncolumns = tupdesc->natts;
1001 
1002  if (rec)
1003  {
1004  /* Build a temporary HeapTuple control structure */
1005  tuple.t_len = HeapTupleHeaderGetDatumLength(rec);
1006  ItemPointerSetInvalid(&(tuple.t_self));
1007  tuple.t_tableOid = InvalidOid;
1008  tuple.t_data = rec;
1009  }
1010 
1011  /*
1012  * We arrange to look up the needed I/O info just once per series of
1013  * calls, assuming the record type doesn't change underneath us.
1014  */
1015  my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra;
1016  if (my_extra == NULL ||
1017  my_extra->ncolumns != ncolumns)
1018  {
1019  fcinfo->flinfo->fn_extra =
1020  MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
1021  offsetof(RecordIOData, columns) +
1022  ncolumns * sizeof(ColumnIOData));
1023  my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra;
1024  my_extra->record_type = InvalidOid;
1025  my_extra->record_typmod = 0;
1026  my_extra->domain_info = NULL;
1027  }
1028 
1029  if (my_extra->record_type != tupType ||
1030  my_extra->record_typmod != tupTypmod)
1031  {
1032  MemSet(my_extra, 0,
1033  offsetof(RecordIOData, columns) +
1034  ncolumns * sizeof(ColumnIOData));
1035  my_extra->record_type = tupType;
1036  my_extra->record_typmod = tupTypmod;
1037  my_extra->ncolumns = ncolumns;
1038  }
1039 
1040  values = (Datum *) palloc(ncolumns * sizeof(Datum));
1041  nulls = (bool *) palloc(ncolumns * sizeof(bool));
1042 
1043  if (rec)
1044  {
1045  /* Break down the tuple into fields */
1046  heap_deform_tuple(&tuple, tupdesc, values, nulls);
1047  }
1048  else
1049  {
1050  for (i = 0; i < ncolumns; ++i)
1051  {
1052  values[i] = (Datum) 0;
1053  nulls[i] = true;
1054  }
1055  }
1056 
1057  for (i = 0; i < ncolumns; ++i)
1058  {
1059  ColumnIOData *column_info = &my_extra->columns[i];
1060  Form_pg_attribute att = TupleDescAttr(tupdesc, i);
1061  Oid column_type = att->atttypid;
1062  char *value;
1063  int idx;
1064  int vallen;
1065 
1066  /* Ignore dropped columns in datatype */
1067  if (att->attisdropped)
1068  {
1069  nulls[i] = true;
1070  continue;
1071  }
1072 
1073  idx = hstoreFindKey(hs, 0,
1074  NameStr(att->attname),
1075  strlen(NameStr(att->attname)));
1076 
1077  /*
1078  * we can't just skip here if the key wasn't found since we might have
1079  * a domain to deal with. If we were passed in a non-null record
1080  * datum, we assume that the existing values are valid (if they're
1081  * not, then it's not our fault), but if we were passed in a null,
1082  * then every field which we don't populate needs to be run through
1083  * the input function just in case it's a domain type.
1084  */
1085  if (idx < 0 && rec)
1086  continue;
1087 
1088  /*
1089  * Prepare to convert the column value from text
1090  */
1091  if (column_info->column_type != column_type)
1092  {
1093  getTypeInputInfo(column_type,
1094  &column_info->typiofunc,
1095  &column_info->typioparam);
1096  fmgr_info_cxt(column_info->typiofunc, &column_info->proc,
1097  fcinfo->flinfo->fn_mcxt);
1098  column_info->column_type = column_type;
1099  }
1100 
1101  if (idx < 0 || HSTORE_VALISNULL(entries, idx))
1102  {
1103  /*
1104  * need InputFunctionCall to happen even for nulls, so that domain
1105  * checks are done
1106  */
1107  values[i] = InputFunctionCall(&column_info->proc, NULL,
1108  column_info->typioparam,
1109  att->atttypmod);
1110  nulls[i] = true;
1111  }
1112  else
1113  {
1114  vallen = HSTORE_VALLEN(entries, idx);
1115  value = palloc(1 + vallen);
1116  memcpy(value, HSTORE_VAL(entries, ptr, idx), vallen);
1117  value[vallen] = 0;
1118 
1119  values[i] = InputFunctionCall(&column_info->proc, value,
1120  column_info->typioparam,
1121  att->atttypmod);
1122  nulls[i] = false;
1123  }
1124  }
1125 
1126  rettuple = heap_form_tuple(tupdesc, values, nulls);
1127 
1128  /*
1129  * If the target type is domain over composite, all we know at this point
1130  * is that we've made a valid value of the base composite type. Must
1131  * check domain constraints before deciding we're done.
1132  */
1133  if (argtype != tupdesc->tdtypeid)
1134  domain_check(HeapTupleGetDatum(rettuple), false,
1135  argtype,
1136  &my_extra->domain_info,
1137  fcinfo->flinfo->fn_mcxt);
1138 
1139  ReleaseTupleDesc(tupdesc);
1140 
1142 }
Datum idx(PG_FUNCTION_ARGS)
Definition: _int_op.c:259
void domain_check(Datum value, bool isnull, Oid domainType, void **extra, MemoryContext mcxt)
Definition: domains.c:327
Datum InputFunctionCall(FmgrInfo *flinfo, char *str, Oid typioparam, int32 typmod)
Definition: fmgr.c:1515
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:353
#define HeapTupleGetDatum(tuple)
Definition: funcapi.h:220
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
int hstoreFindKey(HStore *hs, int *lowbound, char *key, int keylen)
Definition: hstore_op.c:36
bool type_is_rowtype(Oid typid)
Definition: lsyscache.c:2612
void getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
Definition: lsyscache.c:2831
Oid typioparam
Definition: hstore_io.c:754
void * domain_info
Definition: hstore_io.c:763
Oid tdtypeid
Definition: tupdesc.h:82

References ARRPTR, ColumnIOData::column_type, RecordIOData::columns, domain_check(), RecordIOData::domain_info, ereport, errcode(), errmsg(), ERROR, fmgr_info_cxt(), FmgrInfo::fn_mcxt, get_fn_expr_argtype(), getTypeInputInfo(), heap_deform_tuple(), heap_form_tuple(), HeapTupleGetDatum, HeapTupleHeaderGetDatumLength, HeapTupleHeaderGetTypeId, HeapTupleHeaderGetTypMod, HS_COUNT, HSTORE_VAL, HSTORE_VALISNULL, HSTORE_VALLEN, hstoreFindKey(), i, idx(), if(), InputFunctionCall(), InvalidOid, ItemPointerSetInvalid, lookup_rowtype_tupdesc_domain(), MemoryContextAlloc(), MemSet, NameStr, TupleDescData::natts, RecordIOData::ncolumns, offsetof, palloc(), PG_ARGISNULL, PG_GETARG_HEAPTUPLEHEADER, PG_GETARG_HSTORE_P, PG_RETURN_DATUM, PG_RETURN_NULL, PG_RETURN_POINTER, ColumnIOData::proc, RecordIOData::record_type, RecordIOData::record_typmod, ReleaseTupleDesc, STRPTR, HeapTupleData::t_data, HeapTupleData::t_len, HeapTupleData::t_self, HeapTupleData::t_tableOid, TupleDescData::tdtypeid, TupleDescAttr, type_is_rowtype(), ColumnIOData::typiofunc, ColumnIOData::typioparam, value, and values.

◆ hstore_recv()

Datum hstore_recv ( PG_FUNCTION_ARGS  )

Definition at line 439 of file hstore_io.c.

440 {
441  int32 buflen;
442  HStore *out;
443  Pairs *pairs;
444  int32 i;
445  int32 pcount;
447 
448  pcount = pq_getmsgint(buf, 4);
449 
450  if (pcount == 0)
451  {
452  out = hstorePairs(NULL, 0, 0);
453  PG_RETURN_POINTER(out);
454  }
455 
456  if (pcount < 0 || pcount > MaxAllocSize / sizeof(Pairs))
457  ereport(ERROR,
458  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
459  errmsg("number of pairs (%d) exceeds the maximum allowed (%d)",
460  pcount, (int) (MaxAllocSize / sizeof(Pairs)))));
461  pairs = palloc(pcount * sizeof(Pairs));
462 
463  for (i = 0; i < pcount; ++i)
464  {
465  int rawlen = pq_getmsgint(buf, 4);
466  int len;
467 
468  if (rawlen < 0)
469  ereport(ERROR,
470  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
471  errmsg("null value not allowed for hstore key")));
472 
473  pairs[i].key = pq_getmsgtext(buf, rawlen, &len);
474  pairs[i].keylen = hstoreCheckKeyLen(len);
475  pairs[i].needfree = true;
476 
477  rawlen = pq_getmsgint(buf, 4);
478  if (rawlen < 0)
479  {
480  pairs[i].val = NULL;
481  pairs[i].vallen = 0;
482  pairs[i].isnull = true;
483  }
484  else
485  {
486  pairs[i].val = pq_getmsgtext(buf, rawlen, &len);
487  pairs[i].vallen = hstoreCheckValLen(len);
488  pairs[i].isnull = false;
489  }
490  }
491 
492  pcount = hstoreUniquePairs(pairs, pcount, &buflen);
493 
494  out = hstorePairs(pairs, pcount, buflen);
495 
496  PG_RETURN_POINTER(out);
497 }
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276
static char * buf
Definition: pg_test_fsync.c:67
unsigned int pq_getmsgint(StringInfo msg, int b)
Definition: pqformat.c:417
char * pq_getmsgtext(StringInfo msg, int rawbytes, int *nbytes)
Definition: pqformat.c:548
StringInfoData * StringInfo
Definition: stringinfo.h:44

References buf, ereport, errcode(), errmsg(), ERROR, hstoreCheckKeyLen(), hstoreCheckValLen(), hstorePairs(), hstoreUniquePairs(), i, Pairs::isnull, Pairs::key, Pairs::keylen, len, MaxAllocSize, Pairs::needfree, palloc(), PG_GETARG_POINTER, PG_RETURN_POINTER, pq_getmsgint(), pq_getmsgtext(), Pairs::val, and Pairs::vallen.

◆ hstore_send()

Datum hstore_send ( PG_FUNCTION_ARGS  )

Definition at line 1232 of file hstore_io.c.

1233 {
1234  HStore *in = PG_GETARG_HSTORE_P(0);
1235  int i;
1236  int count = HS_COUNT(in);
1237  char *base = STRPTR(in);
1238  HEntry *entries = ARRPTR(in);
1240 
1241  pq_begintypsend(&buf);
1242 
1243  pq_sendint32(&buf, count);
1244 
1245  for (i = 0; i < count; i++)
1246  {
1247  int32 keylen = HSTORE_KEYLEN(entries, i);
1248 
1249  pq_sendint32(&buf, keylen);
1250  pq_sendtext(&buf, HSTORE_KEY(entries, base, i), keylen);
1251  if (HSTORE_VALISNULL(entries, i))
1252  {
1253  pq_sendint32(&buf, -1);
1254  }
1255  else
1256  {
1257  int32 vallen = HSTORE_VALLEN(entries, i);
1258 
1259  pq_sendint32(&buf, vallen);
1260  pq_sendtext(&buf, HSTORE_VAL(entries, base, i), vallen);
1261  }
1262  }
1263 
1265 }
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:371
void pq_sendtext(StringInfo buf, const char *str, int slen)
Definition: pqformat.c:174
void pq_begintypsend(StringInfo buf)
Definition: pqformat.c:328
bytea * pq_endtypsend(StringInfo buf)
Definition: pqformat.c:348
static void pq_sendint32(StringInfo buf, uint32 i)
Definition: pqformat.h:145

References ARRPTR, buf, HS_COUNT, HSTORE_KEY, HSTORE_KEYLEN, HSTORE_VAL, HSTORE_VALISNULL, HSTORE_VALLEN, i, PG_GETARG_HSTORE_P, PG_RETURN_BYTEA_P, pq_begintypsend(), pq_endtypsend(), pq_sendint32(), pq_sendtext(), and STRPTR.

◆ hstore_to_json()

Datum hstore_to_json ( PG_FUNCTION_ARGS  )

Definition at line 1333 of file hstore_io.c.

1334 {
1335  HStore *in = PG_GETARG_HSTORE_P(0);
1336  int i;
1337  int count = HS_COUNT(in);
1338  char *base = STRPTR(in);
1339  HEntry *entries = ARRPTR(in);
1340  StringInfoData tmp,
1341  dst;
1342 
1343  if (count == 0)
1345 
1346  initStringInfo(&tmp);
1347  initStringInfo(&dst);
1348 
1349  appendStringInfoChar(&dst, '{');
1350 
1351  for (i = 0; i < count; i++)
1352  {
1353  resetStringInfo(&tmp);
1354  appendBinaryStringInfo(&tmp, HSTORE_KEY(entries, base, i),
1355  HSTORE_KEYLEN(entries, i));
1356  escape_json(&dst, tmp.data);
1357  appendStringInfoString(&dst, ": ");
1358  if (HSTORE_VALISNULL(entries, i))
1359  appendStringInfoString(&dst, "null");
1360  else
1361  {
1362  resetStringInfo(&tmp);
1363  appendBinaryStringInfo(&tmp, HSTORE_VAL(entries, base, i),
1364  HSTORE_VALLEN(entries, i));
1365  escape_json(&dst, tmp.data);
1366  }
1367 
1368  if (i + 1 != count)
1369  appendStringInfoString(&dst, ", ");
1370  }
1371  appendStringInfoChar(&dst, '}');
1372 
1374 }
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:372
void escape_json(StringInfo buf, const char *str)
Definition: json.c:1580
void resetStringInfo(StringInfo str)
Definition: stringinfo.c:75
void appendBinaryStringInfo(StringInfo str, const char *data, int datalen)
Definition: stringinfo.c:227
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:200
text * cstring_to_text(const char *s)
Definition: varlena.c:188

References appendBinaryStringInfo(), appendStringInfoChar(), appendStringInfoString(), ARRPTR, cstring_to_text(), cstring_to_text_with_len(), StringInfoData::data, escape_json(), HS_COUNT, HSTORE_KEY, HSTORE_KEYLEN, HSTORE_VAL, HSTORE_VALISNULL, HSTORE_VALLEN, i, initStringInfo(), PG_GETARG_HSTORE_P, PG_RETURN_TEXT_P, resetStringInfo(), and STRPTR.

◆ hstore_to_json_loose()

Datum hstore_to_json_loose ( PG_FUNCTION_ARGS  )

Definition at line 1278 of file hstore_io.c.

1279 {
1280  HStore *in = PG_GETARG_HSTORE_P(0);
1281  int i;
1282  int count = HS_COUNT(in);
1283  char *base = STRPTR(in);
1284  HEntry *entries = ARRPTR(in);
1285  StringInfoData tmp,
1286  dst;
1287 
1288  if (count == 0)
1290 
1291  initStringInfo(&tmp);
1292  initStringInfo(&dst);
1293 
1294  appendStringInfoChar(&dst, '{');
1295 
1296  for (i = 0; i < count; i++)
1297  {
1298  resetStringInfo(&tmp);
1299  appendBinaryStringInfo(&tmp, HSTORE_KEY(entries, base, i),
1300  HSTORE_KEYLEN(entries, i));
1301  escape_json(&dst, tmp.data);
1302  appendStringInfoString(&dst, ": ");
1303  if (HSTORE_VALISNULL(entries, i))
1304  appendStringInfoString(&dst, "null");
1305  /* guess that values of 't' or 'f' are booleans */
1306  else if (HSTORE_VALLEN(entries, i) == 1 &&
1307  *(HSTORE_VAL(entries, base, i)) == 't')
1308  appendStringInfoString(&dst, "true");
1309  else if (HSTORE_VALLEN(entries, i) == 1 &&
1310  *(HSTORE_VAL(entries, base, i)) == 'f')
1311  appendStringInfoString(&dst, "false");
1312  else
1313  {
1314  resetStringInfo(&tmp);
1315  appendBinaryStringInfo(&tmp, HSTORE_VAL(entries, base, i),
1316  HSTORE_VALLEN(entries, i));
1317  if (IsValidJsonNumber(tmp.data, tmp.len))
1318  appendBinaryStringInfo(&dst, tmp.data, tmp.len);
1319  else
1320  escape_json(&dst, tmp.data);
1321  }
1322 
1323  if (i + 1 != count)
1324  appendStringInfoString(&dst, ", ");
1325  }
1326  appendStringInfoChar(&dst, '}');
1327 
1329 }
bool IsValidJsonNumber(const char *str, int len)
Definition: jsonapi.c:104

References appendBinaryStringInfo(), appendStringInfoChar(), appendStringInfoString(), ARRPTR, cstring_to_text(), cstring_to_text_with_len(), StringInfoData::data, escape_json(), HS_COUNT, HSTORE_KEY, HSTORE_KEYLEN, HSTORE_VAL, HSTORE_VALISNULL, HSTORE_VALLEN, i, initStringInfo(), IsValidJsonNumber(), StringInfoData::len, PG_GETARG_HSTORE_P, PG_RETURN_TEXT_P, resetStringInfo(), and STRPTR.

◆ hstore_to_jsonb()

Datum hstore_to_jsonb ( PG_FUNCTION_ARGS  )

Definition at line 1378 of file hstore_io.c.

1379 {
1380  HStore *in = PG_GETARG_HSTORE_P(0);
1381  int i;
1382  int count = HS_COUNT(in);
1383  char *base = STRPTR(in);
1384  HEntry *entries = ARRPTR(in);
1385  JsonbParseState *state = NULL;
1386  JsonbValue *res;
1387 
1388  (void) pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
1389 
1390  for (i = 0; i < count; i++)
1391  {
1392  JsonbValue key,
1393  val;
1394 
1395  key.type = jbvString;
1396  key.val.string.len = HSTORE_KEYLEN(entries, i);
1397  key.val.string.val = HSTORE_KEY(entries, base, i);
1398 
1399  (void) pushJsonbValue(&state, WJB_KEY, &key);
1400 
1401  if (HSTORE_VALISNULL(entries, i))
1402  {
1403  val.type = jbvNull;
1404  }
1405  else
1406  {
1407  val.type = jbvString;
1408  val.val.string.len = HSTORE_VALLEN(entries, i);
1409  val.val.string.val = HSTORE_VAL(entries, base, i);
1410  }
1411  (void) pushJsonbValue(&state, WJB_VALUE, &val);
1412  }
1413 
1415 
1417 }
@ jbvNull
Definition: jsonb.h:236
@ jbvString
Definition: jsonb.h:237
@ WJB_KEY
Definition: jsonb.h:23
@ WJB_VALUE
Definition: jsonb.h:24
@ WJB_END_OBJECT
Definition: jsonb.h:29
@ WJB_BEGIN_OBJECT
Definition: jsonb.h:28
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:94
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:568

References ARRPTR, HS_COUNT, HSTORE_KEY, HSTORE_KEYLEN, HSTORE_VAL, HSTORE_VALISNULL, HSTORE_VALLEN, i, jbvNull, jbvString, JsonbValueToJsonb(), sort-test::key, PG_GETARG_HSTORE_P, PG_RETURN_POINTER, pushJsonbValue(), res, STRPTR, val, WJB_BEGIN_OBJECT, WJB_END_OBJECT, WJB_KEY, and WJB_VALUE.

◆ hstore_to_jsonb_loose()

Datum hstore_to_jsonb_loose ( PG_FUNCTION_ARGS  )

Definition at line 1421 of file hstore_io.c.

1422 {
1423  HStore *in = PG_GETARG_HSTORE_P(0);
1424  int i;
1425  int count = HS_COUNT(in);
1426  char *base = STRPTR(in);
1427  HEntry *entries = ARRPTR(in);
1428  JsonbParseState *state = NULL;
1429  JsonbValue *res;
1430  StringInfoData tmp;
1431 
1432  initStringInfo(&tmp);
1433 
1434  (void) pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
1435 
1436  for (i = 0; i < count; i++)
1437  {
1438  JsonbValue key,
1439  val;
1440 
1441  key.type = jbvString;
1442  key.val.string.len = HSTORE_KEYLEN(entries, i);
1443  key.val.string.val = HSTORE_KEY(entries, base, i);
1444 
1445  (void) pushJsonbValue(&state, WJB_KEY, &key);
1446 
1447  if (HSTORE_VALISNULL(entries, i))
1448  {
1449  val.type = jbvNull;
1450  }
1451  /* guess that values of 't' or 'f' are booleans */
1452  else if (HSTORE_VALLEN(entries, i) == 1 &&
1453  *(HSTORE_VAL(entries, base, i)) == 't')
1454  {
1455  val.type = jbvBool;
1456  val.val.boolean = true;
1457  }
1458  else if (HSTORE_VALLEN(entries, i) == 1 &&
1459  *(HSTORE_VAL(entries, base, i)) == 'f')
1460  {
1461  val.type = jbvBool;
1462  val.val.boolean = false;
1463  }
1464  else
1465  {
1466  resetStringInfo(&tmp);
1467  appendBinaryStringInfo(&tmp, HSTORE_VAL(entries, base, i),
1468  HSTORE_VALLEN(entries, i));
1469  if (IsValidJsonNumber(tmp.data, tmp.len))
1470  {
1471  Datum numd;
1472 
1473  val.type = jbvNumeric;
1475  CStringGetDatum(tmp.data),
1477  Int32GetDatum(-1));
1478  val.val.numeric = DatumGetNumeric(numd);
1479  }
1480  else
1481  {
1482  val.type = jbvString;
1483  val.val.string.len = HSTORE_VALLEN(entries, i);
1484  val.val.string.val = HSTORE_VAL(entries, base, i);
1485  }
1486  }
1487  (void) pushJsonbValue(&state, WJB_VALUE, &val);
1488  }
1489 
1491 
1493 }
Datum numeric_in(PG_FUNCTION_ARGS)
Definition: numeric.c:617
#define DirectFunctionCall3(func, arg1, arg2, arg3)
Definition: fmgr.h:635
@ jbvNumeric
Definition: jsonb.h:238
@ jbvBool
Definition: jsonb.h:239
#define DatumGetNumeric(X)
Definition: numeric.h:59
#define CStringGetDatum(X)
Definition: postgres.h:622
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define Int32GetDatum(X)
Definition: postgres.h:523

References appendBinaryStringInfo(), ARRPTR, CStringGetDatum, StringInfoData::data, DatumGetNumeric, DirectFunctionCall3, HS_COUNT, HSTORE_KEY, HSTORE_KEYLEN, HSTORE_VAL, HSTORE_VALISNULL, HSTORE_VALLEN, i, initStringInfo(), Int32GetDatum, InvalidOid, IsValidJsonNumber(), jbvBool, jbvNull, jbvNumeric, jbvString, JsonbValueToJsonb(), sort-test::key, StringInfoData::len, numeric_in(), ObjectIdGetDatum, PG_GETARG_HSTORE_P, PG_RETURN_POINTER, pushJsonbValue(), res, resetStringInfo(), STRPTR, val, WJB_BEGIN_OBJECT, WJB_END_OBJECT, WJB_KEY, and WJB_VALUE.

◆ hstoreCheckKeyLen()

size_t hstoreCheckKeyLen ( size_t  len)

Definition at line 367 of file hstore_io.c.

368 {
369  if (len > HSTORE_MAX_KEY_LEN)
370  ereport(ERROR,
371  (errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
372  errmsg("string too long for hstore key")));
373  return len;
374 }
#define HSTORE_MAX_KEY_LEN
Definition: hstore.h:41

References ereport, errcode(), errmsg(), ERROR, HSTORE_MAX_KEY_LEN, and len.

Referenced by hstore_from_array(), hstore_from_arrays(), hstore_from_record(), hstore_from_text(), hstore_recv(), and parse_hstore().

◆ hstoreCheckValLen()

size_t hstoreCheckValLen ( size_t  len)

Definition at line 377 of file hstore_io.c.

378 {
380  ereport(ERROR,
381  (errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
382  errmsg("string too long for hstore value")));
383  return len;
384 }
#define HSTORE_MAX_VALUE_LEN
Definition: hstore.h:42

References ereport, errcode(), errmsg(), ERROR, HSTORE_MAX_VALUE_LEN, and len.

Referenced by hstore_from_array(), hstore_from_arrays(), hstore_from_record(), hstore_from_text(), hstore_recv(), and parse_hstore().

◆ hstorePairs()

HStore* hstorePairs ( Pairs pairs,
int32  pcount,
int32  buflen 
)

Definition at line 388 of file hstore_io.c.

389 {
390  HStore *out;
391  HEntry *entry;
392  char *ptr;
393  char *buf;
394  int32 len;
395  int32 i;
396 
397  len = CALCDATASIZE(pcount, buflen);
398  out = palloc(len);
399  SET_VARSIZE(out, len);
400  HS_SETCOUNT(out, pcount);
401 
402  if (pcount == 0)
403  return out;
404 
405  entry = ARRPTR(out);
406  buf = ptr = STRPTR(out);
407 
408  for (i = 0; i < pcount; i++)
409  HS_ADDITEM(entry, buf, ptr, pairs[i]);
410 
411  HS_FINALIZE(out, pcount, buf, ptr);
412 
413  return out;
414 }
#define CALCDATASIZE(x, lenstr)
Definition: hstore.h:72
#define HS_FINALIZE(hsp_, count_, buf_, ptr_)
Definition: hstore.h:129
#define HS_ADDITEM(dent_, dbuf_, dptr_, pair_)
Definition: hstore.h:112
#define HS_SETCOUNT(hsp_, c_)
Definition: hstore.h:62
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:342

References ARRPTR, buf, CALCDATASIZE, HS_ADDITEM, HS_FINALIZE, HS_SETCOUNT, i, len, palloc(), SET_VARSIZE, and STRPTR.

Referenced by hstore_from_array(), hstore_from_arrays(), hstore_from_record(), hstore_from_text(), hstore_in(), and hstore_recv().

◆ hstoreUniquePairs()

int hstoreUniquePairs ( Pairs a,
int32  l,
int32 buflen 
)

Definition at line 319 of file hstore_io.c.

320 {
321  Pairs *ptr,
322  *res;
323 
324  *buflen = 0;
325  if (l < 2)
326  {
327  if (l == 1)
328  *buflen = a->keylen + ((a->isnull) ? 0 : a->vallen);
329  return l;
330  }
331 
332  qsort((void *) a, l, sizeof(Pairs), comparePairs);
333 
334  /*
335  * We can't use qunique here because we have some clean-up code to run on
336  * removed elements.
337  */
338  ptr = a + 1;
339  res = a;
340  while (ptr - a < l)
341  {
342  if (ptr->keylen == res->keylen &&
343  memcmp(ptr->key, res->key, res->keylen) == 0)
344  {
345  if (ptr->needfree)
346  {
347  pfree(ptr->key);
348  pfree(ptr->val);
349  }
350  }
351  else
352  {
353  *buflen += res->keylen + ((res->isnull) ? 0 : res->vallen);
354  res++;
355  if (res != ptr)
356  memcpy(res, ptr, sizeof(Pairs));
357  }
358 
359  ptr++;
360  }
361 
362  *buflen += res->keylen + ((res->isnull) ? 0 : res->vallen);
363  return res + 1 - a;
364 }
static int comparePairs(const void *a, const void *b)
Definition: hstore_io.c:289
void pfree(void *pointer)
Definition: mcxt.c:1175
#define qsort(a, b, c, d)
Definition: port.h:495

References a, comparePairs(), Pairs::key, Pairs::keylen, Pairs::needfree, pfree(), qsort, res, and Pairs::val.

Referenced by hstore_from_array(), hstore_from_arrays(), hstore_from_record(), hstore_in(), and hstore_recv().

◆ parse_hstore()

static void parse_hstore ( HSParser state)
static

Definition at line 184 of file hstore_io.c.

185 {
186  int st = WKEY;
187  bool escaped = false;
188 
189  state->plen = 16;
190  state->pairs = (Pairs *) palloc(sizeof(Pairs) * state->plen);
191  state->pcur = 0;
192  state->ptr = state->begin;
193  state->word = NULL;
194 
195  while (1)
196  {
197  if (st == WKEY)
198  {
199  if (!get_val(state, false, &escaped))
200  return;
201  if (state->pcur >= state->plen)
202  {
203  state->plen *= 2;
204  state->pairs = (Pairs *) repalloc(state->pairs, sizeof(Pairs) * state->plen);
205  }
206  state->pairs[state->pcur].key = state->word;
207  state->pairs[state->pcur].keylen = hstoreCheckKeyLen(state->cur - state->word);
208  state->pairs[state->pcur].val = NULL;
209  state->word = NULL;
210  st = WEQ;
211  }
212  else if (st == WEQ)
213  {
214  if (*(state->ptr) == '=')
215  {
216  st = WGT;
217  }
218  else if (*(state->ptr) == '\0')
219  {
220  elog(ERROR, "Unexpected end of string");
221  }
222  else if (!isspace((unsigned char) *(state->ptr)))
223  {
224  elog(ERROR, "Syntax error near \"%.*s\" at position %d",
225  pg_mblen(state->ptr), state->ptr,
226  (int32) (state->ptr - state->begin));
227  }
228  }
229  else if (st == WGT)
230  {
231  if (*(state->ptr) == '>')
232  {
233  st = WVAL;
234  }
235  else if (*(state->ptr) == '\0')
236  {
237  elog(ERROR, "Unexpected end of string");
238  }
239  else
240  {
241  elog(ERROR, "Syntax error near \"%.*s\" at position %d",
242  pg_mblen(state->ptr), state->ptr,
243  (int32) (state->ptr - state->begin));
244  }
245  }
246  else if (st == WVAL)
247  {
248  if (!get_val(state, true, &escaped))
249  elog(ERROR, "Unexpected end of string");
250  state->pairs[state->pcur].val = state->word;
251  state->pairs[state->pcur].vallen = hstoreCheckValLen(state->cur - state->word);
252  state->pairs[state->pcur].isnull = false;
253  state->pairs[state->pcur].needfree = true;
254  if (state->cur - state->word == 4 && !escaped)
255  {
256  state->word[4] = '\0';
257  if (0 == pg_strcasecmp(state->word, "null"))
258  state->pairs[state->pcur].isnull = true;
259  }
260  state->word = NULL;
261  state->pcur++;
262  st = WDEL;
263  }
264  else if (st == WDEL)
265  {
266  if (*(state->ptr) == ',')
267  {
268  st = WKEY;
269  }
270  else if (*(state->ptr) == '\0')
271  {
272  return;
273  }
274  else if (!isspace((unsigned char) *(state->ptr)))
275  {
276  elog(ERROR, "Syntax error near \"%.*s\" at position %d",
277  pg_mblen(state->ptr), state->ptr,
278  (int32) (state->ptr - state->begin));
279  }
280  }
281  else
282  elog(ERROR, "Unknown state %d at line %d in file '%s'", st, __LINE__, __FILE__);
283 
284  state->ptr++;
285  }
286 }
#define WDEL
Definition: hstore_io.c:180
static bool get_val(HSParser *state, bool ignoreeq, bool *escaped)
Definition: hstore_io.c:60
#define WKEY
Definition: hstore_io.c:176
#define WGT
Definition: hstore_io.c:179
#define WVAL
Definition: hstore_io.c:177
#define WEQ
Definition: hstore_io.c:178
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36

References elog(), ERROR, get_val(), hstoreCheckKeyLen(), hstoreCheckValLen(), palloc(), pg_mblen(), pg_strcasecmp(), repalloc(), WDEL, WEQ, WGT, WKEY, and WVAL.

Referenced by hstore_in().

◆ PG_FUNCTION_INFO_V1() [1/13]

PG_FUNCTION_INFO_V1 ( hstore_from_array  )

◆ PG_FUNCTION_INFO_V1() [2/13]

PG_FUNCTION_INFO_V1 ( hstore_from_arrays  )

◆ PG_FUNCTION_INFO_V1() [3/13]

PG_FUNCTION_INFO_V1 ( hstore_from_record  )

◆ PG_FUNCTION_INFO_V1() [4/13]

PG_FUNCTION_INFO_V1 ( hstore_from_text  )

◆ PG_FUNCTION_INFO_V1() [5/13]

PG_FUNCTION_INFO_V1 ( hstore_in  )

◆ PG_FUNCTION_INFO_V1() [6/13]

PG_FUNCTION_INFO_V1 ( hstore_out  )

◆ PG_FUNCTION_INFO_V1() [7/13]

PG_FUNCTION_INFO_V1 ( hstore_populate_record  )

◆ PG_FUNCTION_INFO_V1() [8/13]

PG_FUNCTION_INFO_V1 ( hstore_recv  )

◆ PG_FUNCTION_INFO_V1() [9/13]

PG_FUNCTION_INFO_V1 ( hstore_send  )

◆ PG_FUNCTION_INFO_V1() [10/13]

PG_FUNCTION_INFO_V1 ( hstore_to_json  )

◆ PG_FUNCTION_INFO_V1() [11/13]

PG_FUNCTION_INFO_V1 ( hstore_to_json_loose  )

◆ PG_FUNCTION_INFO_V1() [12/13]

PG_FUNCTION_INFO_V1 ( hstore_to_jsonb  )

◆ PG_FUNCTION_INFO_V1() [13/13]

PG_FUNCTION_INFO_V1 ( hstore_to_jsonb_loose  )

Variable Documentation

◆ PG_MODULE_MAGIC

PG_MODULE_MAGIC

Definition at line 22 of file hstore_io.c.