1/*-------------------------------------------------------------------------
2 *
3 * arrayaccess.h
4 * Declarations for element-by-element access to Postgres arrays.
5 *
6 *
7 * Portions Copyright (c) 1996-2019, 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
33typedef 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
48static inline void
49array_iter_setup(array_iter *it, AnyArrayType *a)
50{
51 if (VARATT_IS_EXPANDED_HEADER(a))
52 {
53 if (a->xpn.dvalues)
54 {
55 it->datumptr = a->xpn.dvalues;
56 it->isnullptr = a->xpn.dnulls;
57 /* we must fill all fields to prevent compiler warnings */
58 it->dataptr = NULL;
59 it->bitmapptr = NULL;
60 }
61 else
62 {
63 /* Work with flat array embedded in the expanded datum */
64 it->datumptr = NULL;
65 it->isnullptr = NULL;
66 it->dataptr = ARR_DATA_PTR(a->xpn.fvalue);
67 it->bitmapptr = ARR_NULLBITMAP(a->xpn.fvalue);
68 }
69 }
70 else
71 {
72 it->datumptr = NULL;
73 it->isnullptr = NULL;
74 it->dataptr = ARR_DATA_PTR((ArrayType *) a);
75 it->bitmapptr = ARR_NULLBITMAP((ArrayType *) a);
76 }
77 it->bitmask = 1;
78}
79
80static inline Datum
81array_iter_next(array_iter *it, bool *isnull, int i,
82 int elmlen, bool elmbyval, char elmalign)
83{
84 Datum ret;
85
86 if (it->datumptr)
87 {
88 ret = it->datumptr[i];
89 *isnull = it->isnullptr ? it->isnullptr[i] : false;
90 }
91 else
92 {
93 if (it->bitmapptr && (*(it->bitmapptr) & it->bitmask) == 0)
94 {
95 *isnull = true;
96 ret = (Datum) 0;
97 }
98 else
99 {
100 *isnull = false;
101 ret = fetch_att(it->dataptr, elmbyval, elmlen);
102 it->dataptr = att_addlength_pointer(it->dataptr, elmlen,
103 it->dataptr);
104 it->dataptr = (char *) att_align_nominal(it->dataptr, elmalign);
105 }
106 it->bitmask <<= 1;
107 if (it->bitmask == 0x100)
108 {
109 if (it->bitmapptr)
110 it->bitmapptr++;
111 it->bitmask = 1;
112 }
113 }
114
115 return ret;
116}
117
118#endif /* ARRAYACCESS_H */
119