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