PostgreSQL Source Code git master
hstore_subs.c File Reference
#include "postgres.h"
#include "executor/execExpr.h"
#include "hstore.h"
#include "nodes/nodeFuncs.h"
#include "nodes/subscripting.h"
#include "parser/parse_coerce.h"
#include "parser/parse_expr.h"
#include "utils/builtins.h"
Include dependency graph for hstore_subs.c:

Go to the source code of this file.

Functions

static void hstore_subscript_transform (SubscriptingRef *sbsref, List *indirection, ParseState *pstate, bool isSlice, bool isAssignment)
 
static void hstore_subscript_fetch (ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 
static void hstore_subscript_assign (ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 
static void hstore_exec_setup (const SubscriptingRef *sbsref, SubscriptingRefState *sbsrefstate, SubscriptExecSteps *methods)
 
 PG_FUNCTION_INFO_V1 (hstore_subscript_handler)
 
Datum hstore_subscript_handler (PG_FUNCTION_ARGS)
 

Function Documentation

◆ hstore_exec_setup()

static void hstore_exec_setup ( const SubscriptingRef sbsref,
SubscriptingRefState sbsrefstate,
SubscriptExecSteps methods 
)
static

Definition at line 264 of file hstore_subs.c.

267{
268 /* Assert we are dealing with one subscript */
269 Assert(sbsrefstate->numlower == 0);
270 Assert(sbsrefstate->numupper == 1);
271 /* We can't check upperprovided[0] here, but it must be true */
272
273 /* Pass back pointers to appropriate step execution functions */
274 methods->sbs_check_subscripts = NULL;
277 methods->sbs_fetch_old = NULL;
278}
#define Assert(condition)
Definition: c.h:815
static void hstore_subscript_assign(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
Definition: hstore_subs.c:143
static void hstore_subscript_fetch(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
Definition: hstore_subs.c:94
ExecEvalSubroutine sbs_fetch_old
Definition: execExpr.h:811
ExecEvalBoolSubroutine sbs_check_subscripts
Definition: execExpr.h:808
ExecEvalSubroutine sbs_assign
Definition: execExpr.h:810
ExecEvalSubroutine sbs_fetch
Definition: execExpr.h:809

References Assert, hstore_subscript_assign(), hstore_subscript_fetch(), SubscriptingRefState::numlower, SubscriptingRefState::numupper, SubscriptExecSteps::sbs_assign, SubscriptExecSteps::sbs_check_subscripts, SubscriptExecSteps::sbs_fetch, and SubscriptExecSteps::sbs_fetch_old.

Referenced by hstore_subscript_handler().

◆ hstore_subscript_assign()

static void hstore_subscript_assign ( ExprState state,
ExprEvalStep op,
ExprContext econtext 
)
static

Definition at line 143 of file hstore_subs.c.

146{
147 SubscriptingRefState *sbsrefstate = op->d.sbsref.state;
148 text *key;
149 Pairs p;
150 HStore *out;
151
152 /* Check for null subscript */
153 if (sbsrefstate->upperindexnull[0])
155 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
156 errmsg("hstore subscript in assignment must not be null")));
157
158 /* OK, fetch/detoast the subscript */
159 key = DatumGetTextPP(sbsrefstate->upperindex[0]);
160
161 /* Create a Pairs entry for subscript + replacement value */
162 p.needfree = false;
163 p.key = VARDATA_ANY(key);
165
166 if (sbsrefstate->replacenull)
167 {
168 p.vallen = 0;
169 p.isnull = true;
170 }
171 else
172 {
173 text *val = DatumGetTextPP(sbsrefstate->replacevalue);
174
175 p.val = VARDATA_ANY(val);
177 p.isnull = false;
178 }
179
180 if (*op->resnull)
181 {
182 /* Just build a one-element hstore (cf. hstore_from_text) */
183 out = hstorePairs(&p, 1, p.keylen + p.vallen);
184 }
185 else
186 {
187 /*
188 * Otherwise, merge the new key into the hstore. Based on
189 * hstore_concat.
190 */
191 HStore *hs = DatumGetHStoreP(*op->resvalue);
192 int s1count = HS_COUNT(hs);
193 int outcount = 0;
194 int vsize;
195 char *ps1,
196 *bufd,
197 *pd;
198 HEntry *es1,
199 *ed;
200 int s1idx;
201 int s2idx;
202
203 /* Allocate result without considering possibility of duplicate */
204 vsize = CALCDATASIZE(s1count + 1, VARSIZE(hs) + p.keylen + p.vallen);
205 out = palloc(vsize);
206 SET_VARSIZE(out, vsize);
207 HS_SETCOUNT(out, s1count + 1);
208
209 ps1 = STRPTR(hs);
210 bufd = pd = STRPTR(out);
211 es1 = ARRPTR(hs);
212 ed = ARRPTR(out);
213
214 for (s1idx = s2idx = 0; s1idx < s1count || s2idx < 1; ++outcount)
215 {
216 int difference;
217
218 if (s1idx >= s1count)
219 difference = 1;
220 else if (s2idx >= 1)
221 difference = -1;
222 else
223 {
224 int s1keylen = HSTORE_KEYLEN(es1, s1idx);
225 int s2keylen = p.keylen;
226
227 if (s1keylen == s2keylen)
228 difference = memcmp(HSTORE_KEY(es1, ps1, s1idx),
229 p.key,
230 s1keylen);
231 else
232 difference = (s1keylen > s2keylen) ? 1 : -1;
233 }
234
235 if (difference >= 0)
236 {
237 HS_ADDITEM(ed, bufd, pd, p);
238 ++s2idx;
239 if (difference == 0)
240 ++s1idx;
241 }
242 else
243 {
244 HS_COPYITEM(ed, bufd, pd,
245 HSTORE_KEY(es1, ps1, s1idx),
246 HSTORE_KEYLEN(es1, s1idx),
247 HSTORE_VALLEN(es1, s1idx),
248 HSTORE_VALISNULL(es1, s1idx));
249 ++s1idx;
250 }
251 }
252
253 HS_FINALIZE(out, outcount, bufd, pd);
254 }
255
256 *op->resvalue = PointerGetDatum(out);
257 *op->resnull = false;
258}
#define ARRPTR(x)
Definition: cube.c:25
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
#define DatumGetTextPP(X)
Definition: fmgr.h:292
Datum difference(PG_FUNCTION_ARGS)
#define CALCDATASIZE(x, lenstr)
Definition: hstore.h:72
#define DatumGetHStoreP(d)
Definition: hstore.h:152
#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_ADDITEM(dent_, dbuf_, dptr_, pair_)
Definition: hstore.h:112
#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 HS_SETCOUNT(hsp_, c_)
Definition: hstore.h:62
#define HS_COPYITEM(dent_, dbuf_, dptr_, sptr_, klen_, vlen_, vnull_)
Definition: hstore.h:99
#define STRPTR(x)
Definition: hstore.h:76
#define hstoreCheckKeyLen
Definition: hstore_plperl.c:56
#define hstorePairs
Definition: hstore_plperl.c:55
#define hstoreCheckValLen
Definition: hstore_plperl.c:57
long val
Definition: informix.c:689
void * palloc(Size size)
Definition: mcxt.c:1317
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:327
struct SubscriptingRefState * state
Definition: execExpr.h:564
struct ExprEvalStep::@55::@84 sbsref
Datum * resvalue
Definition: execExpr.h:304
union ExprEvalStep::@55 d
bool * resnull
Definition: execExpr.h:305
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
Definition: c.h:644
#define VARDATA_ANY(PTR)
Definition: varatt.h:324
#define SET_VARSIZE(PTR, len)
Definition: varatt.h:305
#define VARSIZE(PTR)
Definition: varatt.h:279
#define VARSIZE_ANY_EXHDR(PTR)
Definition: varatt.h:317

References ARRPTR, CALCDATASIZE, ExprEvalStep::d, DatumGetHStoreP, DatumGetTextPP, difference(), ereport, errcode(), errmsg(), ERROR, HS_ADDITEM, HS_COPYITEM, HS_COUNT, HS_FINALIZE, HS_SETCOUNT, HSTORE_KEY, HSTORE_KEYLEN, HSTORE_VALISNULL, HSTORE_VALLEN, hstoreCheckKeyLen, hstoreCheckValLen, hstorePairs, Pairs::isnull, Pairs::key, sort-test::key, Pairs::keylen, Pairs::needfree, palloc(), PointerGetDatum(), SubscriptingRefState::replacenull, SubscriptingRefState::replacevalue, ExprEvalStep::resnull, ExprEvalStep::resvalue, ExprEvalStep::sbsref, SET_VARSIZE, ExprEvalStep::state, STRPTR, SubscriptingRefState::upperindex, SubscriptingRefState::upperindexnull, Pairs::val, val, Pairs::vallen, VARDATA_ANY, VARSIZE, and VARSIZE_ANY_EXHDR.

Referenced by hstore_exec_setup().

◆ hstore_subscript_fetch()

static void hstore_subscript_fetch ( ExprState state,
ExprEvalStep op,
ExprContext econtext 
)
static

Definition at line 94 of file hstore_subs.c.

97{
98 SubscriptingRefState *sbsrefstate = op->d.sbsref.state;
99 HStore *hs;
100 text *key;
101 HEntry *entries;
102 int idx;
103 text *out;
104
105 /* Should not get here if source hstore is null */
106 Assert(!(*op->resnull));
107
108 /* Check for null subscript */
109 if (sbsrefstate->upperindexnull[0])
110 {
111 *op->resnull = true;
112 return;
113 }
114
115 /* OK, fetch/detoast the hstore and subscript */
116 hs = DatumGetHStoreP(*op->resvalue);
117 key = DatumGetTextPP(sbsrefstate->upperindex[0]);
118
119 /* The rest is basically the same as hstore_fetchval() */
120 entries = ARRPTR(hs);
121 idx = hstoreFindKey(hs, NULL,
123
124 if (idx < 0 || HSTORE_VALISNULL(entries, idx))
125 {
126 *op->resnull = true;
127 return;
128 }
129
130 out = cstring_to_text_with_len(HSTORE_VAL(entries, STRPTR(hs), idx),
131 HSTORE_VALLEN(entries, idx));
132
133 *op->resvalue = PointerGetDatum(out);
134}
Datum idx(PG_FUNCTION_ARGS)
Definition: _int_op.c:259
PGDLLEXPORT int hstoreFindKey(HStore *hs, int *lowbound, char *key, int keylen)
Definition: hstore_op.c:36
#define HSTORE_VAL(arr_, str_, i_)
Definition: hstore.h:80
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:196

References ARRPTR, Assert, cstring_to_text_with_len(), ExprEvalStep::d, DatumGetHStoreP, DatumGetTextPP, HSTORE_VAL, HSTORE_VALISNULL, HSTORE_VALLEN, hstoreFindKey(), idx(), sort-test::key, PointerGetDatum(), ExprEvalStep::resnull, ExprEvalStep::resvalue, ExprEvalStep::sbsref, ExprEvalStep::state, STRPTR, SubscriptingRefState::upperindex, SubscriptingRefState::upperindexnull, VARDATA_ANY, and VARSIZE_ANY_EXHDR.

Referenced by hstore_exec_setup().

◆ hstore_subscript_handler()

Datum hstore_subscript_handler ( PG_FUNCTION_ARGS  )

Definition at line 286 of file hstore_subs.c.

287{
288 static const SubscriptRoutines sbsroutines = {
290 .exec_setup = hstore_exec_setup,
291 .fetch_strict = true, /* fetch returns NULL for NULL inputs */
292 .fetch_leakproof = true, /* fetch returns NULL for bad subscript */
293 .store_leakproof = false /* ... but assignment throws error */
294 };
295
296 PG_RETURN_POINTER(&sbsroutines);
297}
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:361
static void hstore_subscript_transform(SubscriptingRef *sbsref, List *indirection, ParseState *pstate, bool isSlice, bool isAssignment)
Definition: hstore_subs.c:42
static void hstore_exec_setup(const SubscriptingRef *sbsref, SubscriptingRefState *sbsrefstate, SubscriptExecSteps *methods)
Definition: hstore_subs.c:264
SubscriptTransform transform
Definition: subscripting.h:160

References hstore_exec_setup(), hstore_subscript_transform(), PG_RETURN_POINTER, and SubscriptRoutines::transform.

◆ hstore_subscript_transform()

static void hstore_subscript_transform ( SubscriptingRef sbsref,
List indirection,
ParseState pstate,
bool  isSlice,
bool  isAssignment 
)
static

Definition at line 42 of file hstore_subs.c.

47{
48 A_Indices *ai;
49 Node *subexpr;
50
51 /* We support only single-subscript, non-slice cases */
52 if (isSlice || list_length(indirection) != 1)
54 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
55 errmsg("hstore allows only one subscript"),
56 parser_errposition(pstate,
57 exprLocation((Node *) indirection))));
58
59 /* Transform the subscript expression to type text */
60 ai = linitial_node(A_Indices, indirection);
61 Assert(ai->uidx != NULL && ai->lidx == NULL && !ai->is_slice);
62
63 subexpr = transformExpr(pstate, ai->uidx, pstate->p_expr_kind);
64 /* If it's not text already, try to coerce */
65 subexpr = coerce_to_target_type(pstate,
66 subexpr, exprType(subexpr),
67 TEXTOID, -1,
70 -1);
71 if (subexpr == NULL)
73 (errcode(ERRCODE_DATATYPE_MISMATCH),
74 errmsg("hstore subscript must have type text"),
75 parser_errposition(pstate, exprLocation(ai->uidx))));
76
77 /* ... and store the transformed subscript into the SubscriptRef node */
78 sbsref->refupperindexpr = list_make1(subexpr);
79 sbsref->reflowerindexpr = NIL;
80
81 /* Determine the result type of the subscripting operation; always text */
82 sbsref->refrestype = TEXTOID;
83 sbsref->reftypmod = -1;
84}
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
int exprLocation(const Node *expr)
Definition: nodeFuncs.c:1388
Node * coerce_to_target_type(ParseState *pstate, Node *expr, Oid exprtype, Oid targettype, int32 targettypmod, CoercionContext ccontext, CoercionForm cformat, int location)
Definition: parse_coerce.c:78
Node * transformExpr(ParseState *pstate, Node *expr, ParseExprKind exprKind)
Definition: parse_expr.c:118
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:106
static int list_length(const List *l)
Definition: pg_list.h:152
#define linitial_node(type, l)
Definition: pg_list.h:181
#define NIL
Definition: pg_list.h:68
#define list_make1(x1)
Definition: pg_list.h:212
@ COERCE_IMPLICIT_CAST
Definition: primnodes.h:753
@ COERCION_ASSIGNMENT
Definition: primnodes.h:732
bool is_slice
Definition: parsenodes.h:470
Node * uidx
Definition: parsenodes.h:472
Node * lidx
Definition: parsenodes.h:471
Definition: nodes.h:129
ParseExprKind p_expr_kind
Definition: parse_node.h:230
List * refupperindexpr
Definition: primnodes.h:710
List * reflowerindexpr
Definition: primnodes.h:716

References Assert, COERCE_IMPLICIT_CAST, coerce_to_target_type(), COERCION_ASSIGNMENT, ereport, errcode(), errmsg(), ERROR, exprLocation(), exprType(), A_Indices::is_slice, A_Indices::lidx, linitial_node, list_length(), list_make1, NIL, ParseState::p_expr_kind, parser_errposition(), SubscriptingRef::reflowerindexpr, SubscriptingRef::refupperindexpr, transformExpr(), and A_Indices::uidx.

Referenced by hstore_subscript_handler().

◆ PG_FUNCTION_INFO_V1()

PG_FUNCTION_INFO_V1 ( hstore_subscript_handler  )