PostgreSQL Source Code git master
Loading...
Searching...
No Matches
hstore_subs.c File Reference
#include "postgres.h"
#include "catalog/pg_type_d.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 265 of file hstore_subs.c.

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

References Assert, fb(), hstore_subscript_assign(), hstore_subscript_fetch(), 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 144 of file hstore_subs.c.

147{
149 text *key;
150 Pairs p;
151 HStore *out;
152
153 /* Check for null subscript */
154 if (sbsrefstate->upperindexnull[0])
157 errmsg("hstore subscript in assignment must not be null")));
158
159 /* OK, fetch/detoast the subscript */
160 key = DatumGetTextPP(sbsrefstate->upperindex[0]);
161
162 /* Create a Pairs entry for subscript + replacement value */
163 p.needfree = false;
164 p.key = VARDATA_ANY(key);
166
167 if (sbsrefstate->replacenull)
168 {
169 p.vallen = 0;
170 p.isnull = true;
171 }
172 else
173 {
174 text *val = DatumGetTextPP(sbsrefstate->replacevalue);
175
176 p.val = VARDATA_ANY(val);
178 p.isnull = false;
179 }
180
181 if (*op->resnull)
182 {
183 /* Just build a one-element hstore (cf. hstore_from_text) */
184 out = hstorePairs(&p, 1, p.keylen + p.vallen);
185 }
186 else
187 {
188 /*
189 * Otherwise, merge the new key into the hstore. Based on
190 * hstore_concat.
191 */
193 int s1count = HS_COUNT(hs);
194 int outcount = 0;
195 int vsize;
196 char *ps1,
197 *bufd,
198 *pd;
199 HEntry *es1,
200 *ed;
201 int s1idx;
202 int s2idx;
203
204 /* Allocate result without considering possibility of duplicate */
206 out = palloc(vsize);
207 SET_VARSIZE(out, vsize);
208 HS_SETCOUNT(out, s1count + 1);
209
210 ps1 = STRPTR(hs);
211 bufd = pd = STRPTR(out);
212 es1 = ARRPTR(hs);
213 ed = ARRPTR(out);
214
215 for (s1idx = s2idx = 0; s1idx < s1count || s2idx < 1; ++outcount)
216 {
217 int difference;
218
219 if (s1idx >= s1count)
220 difference = 1;
221 else if (s2idx >= 1)
222 difference = -1;
223 else
224 {
226 int s2keylen = p.keylen;
227
228 if (s1keylen == s2keylen)
230 p.key,
231 s1keylen);
232 else
233 difference = (s1keylen > s2keylen) ? 1 : -1;
234 }
235
236 if (difference >= 0)
237 {
238 HS_ADDITEM(ed, bufd, pd, p);
239 ++s2idx;
240 if (difference == 0)
241 ++s1idx;
242 }
243 else
244 {
245 HS_COPYITEM(ed, bufd, pd,
250 ++s1idx;
251 }
252 }
253
254 HS_FINALIZE(out, outcount, bufd, pd);
255 }
256
257 *op->resvalue = PointerGetDatum(out);
258 *op->resnull = false;
259}
#define ARRPTR(x)
Definition cube.c:28
int errcode(int sqlerrcode)
Definition elog.c:874
#define ERROR
Definition elog.h:39
#define ereport(elevel,...)
Definition elog.h:150
#define DatumGetTextPP(X)
Definition fmgr.h:293
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
#define hstorePairs
#define hstoreCheckValLen
long val
Definition informix.c:689
void * palloc(Size size)
Definition mcxt.c:1387
static char * errmsg
static Datum PointerGetDatum(const void *X)
Definition postgres.h:342
union ExprEvalStep::@61 d
struct SubscriptingRefState * state
Definition execExpr.h:570
struct ExprEvalStep::@61::@90 sbsref
Datum * resvalue
Definition execExpr.h:310
bool * resnull
Definition execExpr.h:311
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:778
static Size VARSIZE_ANY_EXHDR(const void *PTR)
Definition varatt.h:472
static Size VARSIZE(const void *PTR)
Definition varatt.h:298
static char * VARDATA_ANY(const void *PTR)
Definition varatt.h:486
static void SET_VARSIZE(void *PTR, Size len)
Definition varatt.h:432

References ARRPTR, CALCDATASIZE, ExprEvalStep::d, DatumGetHStoreP, DatumGetTextPP, difference(), ereport, errcode(), errmsg, ERROR, fb(), 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, Pairs::keylen, Pairs::needfree, palloc(), PointerGetDatum(), ExprEvalStep::resnull, ExprEvalStep::resvalue, ExprEvalStep::sbsref, SET_VARSIZE(), ExprEvalStep::state, STRPTR, 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 95 of file hstore_subs.c.

98{
100 HStore *hs;
101 text *key;
102 HEntry *entries;
103 int idx;
104 text *out;
105
106 /* Should not get here if source hstore is null */
107 Assert(!(*op->resnull));
108
109 /* Check for null subscript */
110 if (sbsrefstate->upperindexnull[0])
111 {
112 *op->resnull = true;
113 return;
114 }
115
116 /* OK, fetch/detoast the hstore and subscript */
118 key = DatumGetTextPP(sbsrefstate->upperindex[0]);
119
120 /* The rest is basically the same as hstore_fetchval() */
121 entries = ARRPTR(hs);
123 VARDATA_ANY(key), VARSIZE_ANY_EXHDR(key));
124
125 if (idx < 0 || HSTORE_VALISNULL(entries, idx))
126 {
127 *op->resnull = true;
128 return;
129 }
130
132 HSTORE_VALLEN(entries, idx));
133
134 *op->resvalue = PointerGetDatum(out);
135}
Datum idx(PG_FUNCTION_ARGS)
Definition _int_op.c:262
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, fb(), HSTORE_VAL, HSTORE_VALISNULL, HSTORE_VALLEN, hstoreFindKey(), idx(), PointerGetDatum(), ExprEvalStep::resnull, ExprEvalStep::resvalue, ExprEvalStep::sbsref, ExprEvalStep::state, STRPTR, VARDATA_ANY(), and VARSIZE_ANY_EXHDR().

Referenced by hstore_exec_setup().

◆ hstore_subscript_handler()

Datum hstore_subscript_handler ( PG_FUNCTION_ARGS  )

Definition at line 287 of file hstore_subs.c.

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

References fb(), 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 43 of file hstore_subs.c.

48{
50 Node *subexpr;
51
52 /* We support only single-subscript, non-slice cases */
53 if (isSlice || list_length(indirection) != 1)
56 errmsg("hstore allows only one subscript"),
57 parser_errposition(pstate,
58 exprLocation((Node *) indirection))));
59
60 /* Transform the subscript expression to type text */
61 ai = linitial_node(A_Indices, indirection);
62 Assert(ai->uidx != NULL && ai->lidx == NULL && !ai->is_slice);
63
64 subexpr = transformExpr(pstate, ai->uidx, pstate->p_expr_kind);
65 /* If it's not text already, try to coerce */
66 subexpr = coerce_to_target_type(pstate,
67 subexpr, exprType(subexpr),
68 TEXTOID, -1,
71 -1);
72 if (subexpr == NULL)
75 errmsg("hstore subscript must have type text"),
76 parser_errposition(pstate, exprLocation(ai->uidx))));
77
78 /* ... and store the transformed subscript into the SubscriptingRef node */
79 sbsref->refupperindexpr = list_make1(subexpr);
80 sbsref->reflowerindexpr = NIL;
81
82 /* Determine the result type of the subscripting operation; always text */
83 sbsref->refrestype = TEXTOID;
84 sbsref->reftypmod = -1;
85}
Oid exprType(const Node *expr)
Definition nodeFuncs.c:42
int exprLocation(const Node *expr)
Definition nodeFuncs.c:1392
Node * coerce_to_target_type(ParseState *pstate, Node *expr, Oid exprtype, Oid targettype, int32 targettypmod, CoercionContext ccontext, CoercionForm cformat, int location)
Node * transformExpr(ParseState *pstate, Node *expr, ParseExprKind exprKind)
Definition parse_expr.c:121
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:244
@ COERCE_IMPLICIT_CAST
Definition primnodes.h:769
@ COERCION_ASSIGNMENT
Definition primnodes.h:748
Definition nodes.h:135
ParseExprKind p_expr_kind
Definition parse_node.h:228
List * refupperindexpr
Definition primnodes.h:726
List * reflowerindexpr
Definition primnodes.h:732

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

Referenced by hstore_subscript_handler().

◆ PG_FUNCTION_INFO_V1()

PG_FUNCTION_INFO_V1 ( hstore_subscript_handler  )