📄 arrayfuncs.c
字号:
{ _LOArrayRange(lowerIndx, upperIndx, len, fd, (int) ARR_DATA_PTR(newArr), array, 0, isNull); } lo_close(fd); return (char *) array; } _ArrayRange(lowerIndx, upperIndx, len, ARR_DATA_PTR(newArr), array, 0); return (char *) array;}/* * array_map() * * Map an arbitrary function to an array and return a new array with * same dimensions and the source elements transformed by fn(). */ArrayType *array_map(ArrayType *v, Oid type, char *(*fn) (), Oid retType, int nargs, ...){ ArrayType *result; void *args[4]; char **values; char *elt; int *dim; int ndim; int nitems; int i; int nbytes = 0; int inp_typlen; bool inp_typbyval; int typlen; bool typbyval; char typdelim; Oid typelem; Oid proc; char typalign; char *s; char *p; va_list ap; /* Large objects not yet supported */ if (ARR_IS_LO(v) == true) elog(ERROR, "array_map: large objects not supported"); /* Check nargs */ if ((nargs < 0) || (nargs > 4)) elog(ERROR, "array_map: invalid nargs: %d", nargs); /* Copy extra args to local variable */ va_start(ap, nargs); for (i = 0; i < nargs; i++) args[i] = (void *) va_arg(ap, char *); va_end(ap); /* Lookup source and result types. Unneeded variables are reused. */ system_cache_lookup(type, false, &inp_typlen, &inp_typbyval, &typdelim, &typelem, &proc, &typalign); system_cache_lookup(retType, false, &typlen, &typbyval, &typdelim, &typelem, &proc, &typalign); ndim = ARR_NDIM(v); dim = ARR_DIMS(v); nitems = getNitems(ndim, dim); /* Check for empty array */ if (nitems <= 0) return v; /* Allocate temporary array for new values */ values = (char **) palloc(nitems * sizeof(char *)); MemSet(values, 0, nitems * sizeof(char *)); /* Loop over source data */ s = (char *) ARR_DATA_PTR(v); for (i = 0; i < nitems; i++) { /* Get source element */ if (inp_typbyval) { switch (inp_typlen) { case 1: elt = (char *) ((int) (*(char *) s)); break; case 2: elt = (char *) ((int) (*(int16 *) s)); break; case 3: case 4: default: elt = (char *) (*(int32 *) s); break; } s += inp_typlen; } else { elt = s; if (inp_typlen > 0) s += inp_typlen; else s += INTALIGN(*(int32 *) s); } /* * Apply the given function to source elt and extra args. nargs is * the number of extra args taken by fn(). */ switch (nargs) { case 0: p = (char *) (*fn) (elt); break; case 1: p = (char *) (*fn) (elt, args[0]); break; case 2: p = (char *) (*fn) (elt, args[0], args[1]); break; case 3: p = (char *) (*fn) (elt, args[0], args[1], args[2]); break; case 4: default: p = (char *) (*fn) (elt, args[0], args[1], args[2], args[3]); break; } /* Update values and total result size */ if (typbyval) { values[i] = (char *) p; nbytes += typlen; } else { int len; len = ((typlen > 0) ? typlen : INTALIGN(*(int32 *) p)); /* Needed because _CopyArrayEls tries to pfree items */ if (p == elt) { p = (char *) palloc(len); memcpy(p, elt, len); } values[i] = (char *) p; nbytes += len; } } /* Allocate and initialize the result array */ nbytes += ARR_OVERHEAD(ndim); result = (ArrayType *) palloc(nbytes); MemSet(result, 0, nbytes); memcpy((char *) result, (char *) &nbytes, sizeof(int)); memcpy((char *) ARR_NDIM_PTR(result), (char *) &ndim, sizeof(int)); memcpy((char *) ARR_DIMS(result), ARR_DIMS(v), 2 * ndim * sizeof(int)); /* Copy new values into the result array. values is pfreed. */ _CopyArrayEls((char **) values, ARR_DATA_PTR(result), nitems, typlen, typalign, typbyval); return result;}/*----------------------------------------------------------------------------- * array_eq : * compares two arrays for equality * result : * returns 1 if the arrays are equal, 0 otherwise. *----------------------------------------------------------------------------- */intarray_eq(ArrayType *array1, ArrayType *array2){ if ((array1 == NULL) || (array2 == NULL)) return 0; if (*(int *) array1 != *(int *) array2) return 0; if (memcmp(array1, array2, *(int *) array1)) return 0; return 1;}/***************************************************************************//******************| Support Routines |*****************//***************************************************************************/static voidsystem_cache_lookup(Oid element_type, bool input, int *typlen, bool *typbyval, char *typdelim, Oid *typelem, Oid *proc, char *typalign){ HeapTuple typeTuple; Form_pg_type typeStruct; typeTuple = SearchSysCacheTuple(TYPOID, ObjectIdGetDatum(element_type), 0, 0, 0); if (!HeapTupleIsValid(typeTuple)) { elog(ERROR, "array_out: Cache lookup failed for type %u\n", element_type); return; } typeStruct = (Form_pg_type) GETSTRUCT(typeTuple); *typlen = typeStruct->typlen; *typbyval = typeStruct->typbyval; *typdelim = typeStruct->typdelim; *typelem = typeStruct->typelem; *typalign = typeStruct->typalign; if (input) *proc = typeStruct->typinput; else *proc = typeStruct->typoutput;}static Datum_ArrayCast(char *value, bool byval, int len){ if (byval) { switch (len) { case 1: return (Datum) *value; case 2: return (Datum) *(int16 *) value; case 3: case 4: return (Datum) *(int32 *) value; default: elog(ERROR, "array_ref: byval and elt len > 4!"); break; } } else return (Datum) value; return 0;}static intArrayCastAndSet(char *src, bool typbyval, int typlen, char *dest){ int inc; if (typlen > 0) { if (typbyval) { switch (typlen) { case 1: *dest = DatumGetChar(src); break; case 2: *(int16 *) dest = DatumGetInt16(src); break; case 4: *(int32 *) dest = (int32) src; break; } } else memmove(dest, src, typlen); inc = typlen; } else { memmove(dest, src, *(int32 *) src); inc = (INTALIGN(*(int32 *) src)); } return inc;}#ifdef LOARRAYstatic char *_AdvanceBy1word(char *str, char **word){ char *retstr, *space; *word = NULL; if (str == NULL) return str; while (isspace(*str)) str++; *word = str; if ((space = (char *) strchr(str, ' ')) != (char *) NULL) { retstr = space + 1; *space = '\0'; } else retstr = NULL; return retstr;}#endifstatic intSanityCheckInput(int ndim, int n, int *dim, int *lb, int *indx){ int i; /* Do Sanity check on input */ if (n != ndim) return 0; for (i = 0; i < ndim; i++) if ((lb[i] > indx[i]) || (indx[i] >= (dim[i] + lb[i]))) return 0; return 1;}static void_ArrayRange(int *st, int *endp, int bsize, char *destPtr, ArrayType *array, int from){ int n, *dim, *lb, st_pos, prod[MAXDIM]; int span[MAXDIM], dist[MAXDIM], indx[MAXDIM]; int i, j, inc; char *srcPtr; n = ARR_NDIM(array); dim = ARR_DIMS(array); lb = ARR_LBOUND(array); srcPtr = ARR_DATA_PTR(array); for (i = 0; i < n; st[i] -= lb[i], endp[i] -= lb[i], i++); mda_get_prod(n, dim, prod); st_pos = tuple2linear(n, st, prod); srcPtr = array_seek(srcPtr, bsize, st_pos); mda_get_range(n, span, st, endp); mda_get_offset_values(n, dist, prod, span); for (i = 0; i < n; indx[i++] = 0); i = j = n - 1; inc = bsize; do { srcPtr = array_seek(srcPtr, bsize, dist[j]); if (from) inc = array_read(destPtr, bsize, 1, srcPtr); else inc = array_read(srcPtr, bsize, 1, destPtr); destPtr += inc; srcPtr += inc; } while ((j = next_tuple(i + 1, indx, span)) != -1);}static int_ArrayClipCount(int *stI, int *endpI, ArrayType *array){ int n, *dim, *lb, st_pos, prod[MAXDIM]; int span[MAXDIM], dist[MAXDIM], indx[MAXDIM]; int i, j, inc, st[MAXDIM], endp[MAXDIM]; int count = 0; char *ptr; n = ARR_NDIM(array); dim = ARR_DIMS(array); lb = ARR_LBOUND(array); ptr = ARR_DATA_PTR(array); for (i = 0; i < n; st[i] = stI[i] - lb[i], endp[i] = endpI[i] - lb[i], i++); mda_get_prod(n, dim, prod); st_pos = tuple2linear(n, st, prod); ptr = array_seek(ptr, -1, st_pos); mda_get_range(n, span, st, endp); mda_get_offset_values(n, dist, prod, span); for (i = 0; i < n; indx[i++] = 0); i = j = n - 1; do { ptr = array_seek(ptr, -1, dist[j]); inc = INTALIGN(*(int32 *) ptr); ptr += inc; count += inc; } while ((j = next_tuple(i + 1, indx, span)) != -1); return count;}static char *array_seek(char *ptr, int eltsize, int nitems){ int i; if (eltsize > 0) return ptr + eltsize * nitems; for (i = 0; i < nitems; i++) ptr += INTALIGN(*(int32 *) ptr); return ptr;}static intarray_read(char *destptr, int eltsize, int nitems, char *srcptr){ int i, inc, tmp; if (eltsize > 0) { memmove(destptr, srcptr, eltsize * nitems); return eltsize * nitems; } for (i = inc = 0; i < nitems; i++) { tmp = (INTALIGN(*(int32 *) srcptr)); memmove(destptr, srcptr, tmp); srcptr += tmp; destptr += tmp; inc += tmp; } return inc;}static void_LOArrayRange(int *st, int *endp, int bsize, int srcfd, int destfd, ArrayType *array, int isSrcLO, bool *isNull){ int n, *dim, st_pos, prod[MAXDIM]; int span[MAXDIM], dist[MAXDIM], indx[MAXDIM]; int i, j, inc, tmp, *lb, offset; n = ARR_NDIM(array); dim = ARR_DIMS(array); lb = ARR_LBOUND(array); for (i = 0; i < n; st[i] -= lb[i], endp[i] -= lb[i], i++); mda_get_prod(n, dim, prod); st_pos = tuple2linear(n, st, prod); offset = st_pos * bsize; if (lo_lseek(srcfd, offset, SEEK_SET) < 0) return; mda_get_range(n, span, st, endp); mda_get_offset_values(n, dist, prod, span); for (i = 0; i < n; indx[i++] = 0); for (i = n - 1, inc = bsize; i >= 0; inc *= span[i--]) if (dist[i]) break; j = n - 1; do { offset += (dist[j] * bsize); if (lo_lseek(srcfd, offset, SEEK_SET) < 0) return; tmp = _LOtransfer((char **) &srcfd, inc, 1, (char **) &destfd, isSrcLO, 1); if (tmp < inc) return; offset += inc; } while ((j = next_tuple(i + 1, indx, span)) != -1);}static void_ReadArray(int *st, int *endp, int bsize, int srcfd, int destfd, ArrayType *array, int isDestLO, bool *isNull){ int n, *dim, st_pos, prod[MAXDIM]; int span[MAXDIM], dist[MAXDIM], indx[MAXDIM]; int i, j, inc, tmp, *lb, offset; n = ARR_NDIM(array); dim = ARR_DIMS(array); lb = ARR_LBOUND(array); for (i = 0; i < n; st[i] -= lb[i], endp[i] -= lb[i], i++); mda_get_prod(n, dim, prod); st_pos = tuple2linear(n, st, prod); offset = st_pos * bsize; if (lo_lseek(srcfd, offset, SEEK_SET) < 0) return; mda_get_range(n, span, st, endp); mda_get_offset_values(n, dist, prod, span); for (i = 0; i < n; indx[i++] = 0); for (i = n - 1, inc = bsize; i >= 0; inc *= span[i--]) if (dist[i]) break; j = n - 1; do { offset += (dist[j] * bsize); if (lo_lseek(srcfd, offset, SEEK_SET) < 0) return; tmp = _LOtransfer((char **) &destfd, inc, 1, (char **) &srcfd, 1, isDestLO); if (tmp < inc) return; offset += inc; } while ((j = next_tuple(i + 1, indx, span)) != -1);}int_LOtransfer(char **destfd, int size, int nitems, char **srcfd, int isSrcLO, int isDestLO){#define MAX_READ (512 * 1024)#define min(a, b) (a < b ? a : b) struct varlena *v = NULL; int tmp, inc, resid; inc = nitems * size; if (isSrcLO && isDestLO && inc > 0) for (tmp = 0, resid = inc; resid > 0 && (inc = min(resid, MAX_READ)) > 0; resid -= inc) {#ifdef LOARRAY v = (struct varlena *) LOread((int) *srcfd, inc); if (VARSIZE(v) - VARHDRSZ < inc) { pfree(v); return -1; } tmp += LOwrite((int) *destfd, v);#endif pfree(v); } else if (!isSrcLO && isDestLO) { tmp = lo_write((int) *destfd, *srcfd, inc); *srcfd = *srcfd + tmp; } else if (isSrcLO && !isDestLO) { tmp = lo_read((int) *srcfd, *destfd, inc); *destfd = *destfd + tmp; } else { memmove(*destfd, *srcfd, inc); tmp = inc; *srcfd += inc; *destfd += inc; } return tmp;#undef MAX_READ}char *_array_newLO(int *fd, int flag){ char *p; char saveName[NAME_LEN]; p = (char *) palloc(NAME_LEN); sprintf(p, "/Arry.%u", newoid()); strcpy(saveName, p);#ifdef LOARRAY if ((*fd = LOcreat(saveName, 0600, flag)) < 0) elog(ERROR, "Large object create failed");#endif return p;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -