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-2026, 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, 26 : * and "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 : 46 : /* Fields used in both cases: data about array's element type */ 47 : int elmlen; 48 : bool elmbyval; 49 : uint8 elmalignby; 50 : } array_iter; 51 : 52 : 53 : static inline void 54 18175994 : array_iter_setup(array_iter *it, AnyArrayType *a, 55 : int elmlen, bool elmbyval, char elmalign) 56 : { 57 18175994 : if (VARATT_IS_EXPANDED_HEADER(a)) 58 : { 59 7292 : if (a->xpn.dvalues) 60 : { 61 2730 : it->datumptr = a->xpn.dvalues; 62 2730 : it->isnullptr = a->xpn.dnulls; 63 : /* we must fill all fields to prevent compiler warnings */ 64 2730 : it->dataptr = NULL; 65 2730 : it->bitmapptr = NULL; 66 : } 67 : else 68 : { 69 : /* Work with flat array embedded in the expanded datum */ 70 4562 : it->datumptr = NULL; 71 4562 : it->isnullptr = NULL; 72 4562 : it->dataptr = ARR_DATA_PTR(a->xpn.fvalue); 73 4562 : it->bitmapptr = ARR_NULLBITMAP(a->xpn.fvalue); 74 : } 75 : } 76 : else 77 : { 78 18168702 : it->datumptr = NULL; 79 18168702 : it->isnullptr = NULL; 80 18168702 : it->dataptr = ARR_DATA_PTR((ArrayType *) a); 81 18168702 : it->bitmapptr = ARR_NULLBITMAP((ArrayType *) a); 82 : } 83 18175994 : it->bitmask = 1; 84 18175994 : it->elmlen = elmlen; 85 18175994 : it->elmbyval = elmbyval; 86 18175994 : it->elmalignby = typalign_to_alignby(elmalign); 87 18175994 : } 88 : 89 : static inline Datum 90 34092744 : array_iter_next(array_iter *it, bool *isnull, int i) 91 : { 92 : Datum ret; 93 : 94 34092744 : if (it->datumptr) 95 : { 96 183324 : ret = it->datumptr[i]; 97 183324 : *isnull = it->isnullptr ? it->isnullptr[i] : false; 98 : } 99 : else 100 : { 101 33909420 : if (it->bitmapptr && (*(it->bitmapptr) & it->bitmask) == 0) 102 : { 103 34556 : *isnull = true; 104 34556 : ret = (Datum) 0; 105 : } 106 : else 107 : { 108 33874864 : *isnull = false; 109 33874864 : ret = fetch_att(it->dataptr, it->elmbyval, it->elmlen); 110 33874864 : it->dataptr = att_addlength_pointer(it->dataptr, it->elmlen, 111 : it->dataptr); 112 33874864 : it->dataptr = (char *) att_nominal_alignby(it->dataptr, 113 : it->elmalignby); 114 : } 115 33909420 : it->bitmask <<= 1; 116 33909420 : if (it->bitmask == 0x100) 117 : { 118 199554 : if (it->bitmapptr) 119 7782 : it->bitmapptr++; 120 199554 : it->bitmask = 1; 121 : } 122 : } 123 : 124 34092744 : return ret; 125 : } 126 : 127 : #endif /* ARRAYACCESS_H */