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-2024, 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 17157004 : array_iter_setup(array_iter *it, AnyArrayType *a) 50 : { 51 17157004 : if (VARATT_IS_EXPANDED_HEADER(a)) 52 : { 53 7272 : 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 4542 : it->datumptr = NULL; 65 4542 : it->isnullptr = NULL; 66 4542 : it->dataptr = ARR_DATA_PTR(a->xpn.fvalue); 67 4542 : it->bitmapptr = ARR_NULLBITMAP(a->xpn.fvalue); 68 : } 69 : } 70 : else 71 : { 72 17149732 : it->datumptr = NULL; 73 17149732 : it->isnullptr = NULL; 74 17149732 : it->dataptr = ARR_DATA_PTR((ArrayType *) a); 75 17149732 : it->bitmapptr = ARR_NULLBITMAP((ArrayType *) a); 76 : } 77 17157004 : it->bitmask = 1; 78 17157004 : } 79 : 80 : static inline Datum 81 31732022 : array_iter_next(array_iter *it, bool *isnull, int i, 82 : int elmlen, bool elmbyval, char elmalign) 83 : { 84 : Datum ret; 85 : 86 31732022 : if (it->datumptr) 87 : { 88 183324 : ret = it->datumptr[i]; 89 183324 : *isnull = it->isnullptr ? it->isnullptr[i] : false; 90 : } 91 : else 92 : { 93 31548698 : if (it->bitmapptr && (*(it->bitmapptr) & it->bitmask) == 0) 94 : { 95 34106 : *isnull = true; 96 34106 : ret = (Datum) 0; 97 : } 98 : else 99 : { 100 31514592 : *isnull = false; 101 31514592 : ret = fetch_att(it->dataptr, elmbyval, elmlen); 102 31514592 : it->dataptr = att_addlength_pointer(it->dataptr, elmlen, 103 : it->dataptr); 104 31514592 : it->dataptr = (char *) att_align_nominal(it->dataptr, elmalign); 105 : } 106 31548698 : it->bitmask <<= 1; 107 31548698 : if (it->bitmask == 0x100) 108 : { 109 128432 : if (it->bitmapptr) 110 7722 : it->bitmapptr++; 111 128432 : it->bitmask = 1; 112 : } 113 : } 114 : 115 31732022 : return ret; 116 : } 117 : 118 : #endif /* ARRAYACCESS_H */