Age Owner TLA Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * arrayaccess.h
4 : * Declarations for element-by-element access to Postgres arrays.
5 : *
6 : *
7 : * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
8 : * Portions Copyright (c) 1994, Regents of the University of California
9 : *
10 : * src/include/utils/arrayaccess.h
11 : *
12 : *-------------------------------------------------------------------------
13 : */
14 : #ifndef ARRAYACCESS_H
15 : #define ARRAYACCESS_H
16 :
17 : #include "access/tupmacs.h"
18 : #include "utils/array.h"
19 :
20 :
21 : /*
22 : * Functions for iterating through elements of a flat or expanded array.
23 : * These require a state struct "array_iter iter".
24 : *
25 : * Use "array_iter_setup(&iter, arrayptr);" to prepare to iterate, and
26 : * "datumvar = array_iter_next(&iter, &isnullvar, index, ...);" to fetch
27 : * the next element into datumvar/isnullvar.
28 : * "index" must be the zero-origin element number; we make caller provide
29 : * this since caller is generally counting the elements anyway. Despite
30 : * that, these functions can only fetch elements sequentially.
31 : */
32 :
33 : typedef struct array_iter
34 : {
35 : /* datumptr being NULL or not tells if we have flat or expanded array */
36 :
37 : /* Fields used when we have an expanded array */
38 : Datum *datumptr; /* Pointer to Datum array */
39 : bool *isnullptr; /* Pointer to isnull array */
40 :
41 : /* Fields used when we have a flat array */
42 : char *dataptr; /* Current spot in the data area */
43 : bits8 *bitmapptr; /* Current byte of the nulls bitmap, or NULL */
44 : int bitmask; /* mask for current bit in nulls bitmap */
45 : } array_iter;
46 :
47 :
48 : static inline void
2887 tgl 49 CBC 11968372 : array_iter_setup(array_iter *it, AnyArrayType *a)
50 : {
51 11968372 : if (VARATT_IS_EXPANDED_HEADER(a))
52 : {
53 3624 : if (a->xpn.dvalues)
54 : {
55 1359 : it->datumptr = a->xpn.dvalues;
56 1359 : it->isnullptr = a->xpn.dnulls;
57 : /* we must fill all fields to prevent compiler warnings */
58 1359 : it->dataptr = NULL;
59 1359 : it->bitmapptr = NULL;
60 : }
61 : else
62 : {
63 : /* Work with flat array embedded in the expanded datum */
64 2265 : it->datumptr = NULL;
65 2265 : it->isnullptr = NULL;
66 2265 : it->dataptr = ARR_DATA_PTR(a->xpn.fvalue);
67 2265 : it->bitmapptr = ARR_NULLBITMAP(a->xpn.fvalue);
68 : }
69 : }
70 : else
71 : {
72 11964748 : it->datumptr = NULL;
73 11964748 : it->isnullptr = NULL;
1379 noah 74 11964748 : it->dataptr = ARR_DATA_PTR((ArrayType *) a);
75 11964748 : it->bitmapptr = ARR_NULLBITMAP((ArrayType *) a);
76 : }
2887 tgl 77 11968372 : it->bitmask = 1;
78 11968372 : }
79 :
80 : static inline Datum
81 21961854 : array_iter_next(array_iter *it, bool *isnull, int i,
82 : int elmlen, bool elmbyval, char elmalign)
83 : {
84 : Datum ret;
85 :
86 21961854 : if (it->datumptr)
87 : {
88 91638 : ret = it->datumptr[i];
89 91638 : *isnull = it->isnullptr ? it->isnullptr[i] : false;
90 : }
91 : else
92 : {
93 21870216 : if (it->bitmapptr && (*(it->bitmapptr) & it->bitmask) == 0)
94 : {
95 17128 : *isnull = true;
96 17128 : ret = (Datum) 0;
97 : }
98 : else
99 : {
100 21853088 : *isnull = false;
101 21853088 : ret = fetch_att(it->dataptr, elmbyval, elmlen);
102 21853088 : it->dataptr = att_addlength_pointer(it->dataptr, elmlen,
103 : it->dataptr);
104 21853088 : it->dataptr = (char *) att_align_nominal(it->dataptr, elmalign);
105 : }
106 21870216 : it->bitmask <<= 1;
107 21870216 : if (it->bitmask == 0x100)
108 : {
109 96277 : if (it->bitmapptr)
110 3861 : it->bitmapptr++;
111 96277 : it->bitmask = 1;
112 : }
113 : }
114 :
115 21961854 : return ret;
116 : }
117 :
118 : #endif /* ARRAYACCESS_H */
|