📄 arrayfuncs.c
字号:
nbytes = strlen(ARR_DATA_PTR(v)) + VARHDRSZ + *(int *) p; save_p = (char *) palloc(nbytes); strcpy(save_p, p + sizeof(int)); strcat(save_p, ASSGN); strcat(save_p, ARR_DATA_PTR(v)); pfree(p); return save_p; } system_cache_lookup(element_type, false, &typlen, &typbyval, &typdelim, &typelem, &typoutput, &typalign); fmgr_info(typoutput, &outputproc); sprintf(delim, "%c", typdelim); ndim = ARR_NDIM(v); dim = ARR_DIMS(v); nitems = getNitems(ndim, dim); if (nitems == 0) { char *emptyArray = palloc(3); emptyArray[0] = '{'; emptyArray[1] = '}'; emptyArray[2] = '\0'; return emptyArray; } p = ARR_DATA_PTR(v); overall_length = 1; /* [TRH] don't forget to count \0 at end. */ values = (char **) palloc(nitems * sizeof(char *)); for (i = 0; i < nitems; i++) { if (typbyval) { switch (typlen) { case 1: values[i] = (*fmgr_faddr(&outputproc)) (*p, typelem); break; case 2: values[i] = (*fmgr_faddr(&outputproc)) (*(int16 *) p, typelem); break; case 3: case 4: values[i] = (*fmgr_faddr(&outputproc)) (*(int32 *) p, typelem); break; } p += typlen; } else { values[i] = (*fmgr_faddr(&outputproc)) (p, typelem); if (typlen > 0) p += typlen; else p += INTALIGN(*(int32 *) p); /* * For the pair of double quotes */ overall_length += 2; } for (tmp = values[i]; *tmp; tmp++) { overall_length += 1;#ifndef TCL_ARRAYS if (*tmp == '"') overall_length += 1;#endif } overall_length += 1; } /* * count total number of curly braces in output string */ for (i = j = 0, k = 1; i < ndim; k *= dim[i++], j += k); p = (char *) palloc(overall_length + 2 * j); retval = p; strcpy(p, "{"); for (i = 0; i < ndim; indx[i++] = 0); j = 0; k = 0; do { for (i = j; i < ndim - 1; i++) strcat(p, "{"); /* * Surround anything that is not passed by value in double quotes. * See above for more details. */ if (!typbyval) { strcat(p, "\"");#ifndef TCL_ARRAYS l = strlen(p); for (tmp = values[k]; *tmp; tmp++) { if (*tmp == '"') p[l++] = '\\'; p[l++] = *tmp; } p[l] = '\0';#else strcat(p, values[k]);#endif strcat(p, "\""); } else strcat(p, values[k]); pfree(values[k++]); for (i = ndim - 1; i >= 0; i--) { indx[i] = (indx[i] + 1) % dim[i]; if (indx[i]) { strcat(p, delim); break; } else strcat(p, "}"); } j = i; } while (j != -1); pfree(values); return retval;}/*----------------------------------------------------------------------------- * array_dims : * returns the dimension of the array pointed to by "v" *---------------------------------------------------------------------------- */char *array_dims(ArrayType *v, bool *isNull){ char *p, *save_p; int nbytes, i; int *dimv, *lb; if (v == (ArrayType *) NULL) RETURN_NULL; nbytes = ARR_NDIM(v) * 33; /* * 33 since we assume 15 digits per number + ':' +'[]' */ save_p = p = (char *) palloc(nbytes + VARHDRSZ); MemSet(save_p, 0, nbytes + VARHDRSZ); dimv = ARR_DIMS(v); lb = ARR_LBOUND(v); p += VARHDRSZ; for (i = 0; i < ARR_NDIM(v); i++) { sprintf(p, "[%d:%d]", lb[i], dimv[i] + lb[i] - 1); p += strlen(p); } nbytes = strlen(save_p + VARHDRSZ) + VARHDRSZ; memmove(save_p, &nbytes, VARHDRSZ); return save_p;}/*--------------------------------------------------------------------------- * array_ref : * This routing takes an array pointer and an index array and returns * a pointer to the referred element if element is passed by * reference otherwise returns the value of the referred element. *--------------------------------------------------------------------------- */Datumarray_ref(ArrayType *array, int n, int *indx, int reftype, int elmlen, int arraylen, bool *isNull){ int i, ndim, *dim, *lb, offset, nbytes; struct varlena *v = NULL; char *retval = NULL; if (array == (ArrayType *) NULL) RETURN_NULL; if (arraylen > 0) { /* * fixed length arrays -- these are assumed to be 1-d */ if (indx[0] * elmlen > arraylen) elog(ERROR, "array_ref: array bound exceeded"); retval = (char *) array + indx[0] * elmlen; return _ArrayCast(retval, reftype, elmlen); } dim = ARR_DIMS(array); lb = ARR_LBOUND(array); ndim = ARR_NDIM(array); nbytes = (*(int32 *) array) - ARR_OVERHEAD(ndim); if (!SanityCheckInput(ndim, n, dim, lb, indx)) RETURN_NULL; offset = GetOffset(n, dim, lb, indx); if (ARR_IS_LO(array)) { char *lo_name; int fd = 0; /* We are assuming fixed element lengths here */ offset *= elmlen; lo_name = (char *) ARR_DATA_PTR(array);#ifdef LOARRAY if ((fd = LOopen(lo_name, ARR_IS_INV(array) ? INV_READ : O_RDONLY)) < 0) RETURN_NULL;#endif if (ARR_IS_CHUNKED(array)) v = _ReadChunkArray1El(indx, elmlen, fd, array, isNull); else { if (lo_lseek(fd, offset, SEEK_SET) < 0) RETURN_NULL;#ifdef LOARRAY v = (struct varlena *) LOread(fd, elmlen);#endif } if (*isNull) RETURN_NULL; if (VARSIZE(v) - VARHDRSZ < elmlen) RETURN_NULL; lo_close(fd); retval = (char *) _ArrayCast((char *) VARDATA(v), reftype, elmlen); if (reftype == 0) { /* not by value */ char *tempdata = palloc(elmlen); memmove(tempdata, retval, elmlen); retval = tempdata; } pfree(v); return (Datum) retval; } if (elmlen > 0) { offset = offset * elmlen; /* off the end of the array */ if (nbytes - offset < 1) RETURN_NULL; retval = ARR_DATA_PTR(array) + offset; return _ArrayCast(retval, reftype, elmlen); } else { bool done = false; char *temp; int bytes = nbytes; temp = ARR_DATA_PTR(array); i = 0; while (bytes > 0 && !done) { if (i == offset) { retval = temp; done = true; } bytes -= INTALIGN(*(int32 *) temp); temp += INTALIGN(*(int32 *) temp); i++; } if (!done) RETURN_NULL; return (Datum) retval; }}/*----------------------------------------------------------------------------- * array_clip : * This routine takes an array and a range of indices (upperIndex and * lowerIndx), creates a new array structure for the referred elements * and returns a pointer to it. *----------------------------------------------------------------------------- */Datumarray_clip(ArrayType *array, int n, int *upperIndx, int *lowerIndx, int reftype, int len, bool *isNull){ int i, ndim, *dim, *lb, nbytes; ArrayType *newArr; int bytes, span[MAXDIM]; /* timer_start(); */ if (array == (ArrayType *) NULL) RETURN_NULL; dim = ARR_DIMS(array); lb = ARR_LBOUND(array); ndim = ARR_NDIM(array); nbytes = (*(int32 *) array) - ARR_OVERHEAD(ndim); if (!SanityCheckInput(ndim, n, dim, lb, upperIndx)) RETURN_NULL; if (!SanityCheckInput(ndim, n, dim, lb, lowerIndx)) RETURN_NULL; for (i = 0; i < n; i++) if (lowerIndx[i] > upperIndx[i]) elog(ERROR, "lowerIndex cannot be larger than upperIndx"); mda_get_range(n, span, lowerIndx, upperIndx); if (ARR_IS_LO(array)) {#ifdef LOARRAY char *lo_name;#endif char *newname = NULL; int fd = 0, newfd = 0, isDestLO = true, rsize; if (len < 0) elog(ERROR, "array_clip: array of variable length objects not supported");#ifdef LOARRAY lo_name = (char *) ARR_DATA_PTR(array); if ((fd = LOopen(lo_name, ARR_IS_INV(array) ? INV_READ : O_RDONLY)) < 0) RETURN_NULL; newname = _array_newLO(&newfd, Unix);#endif bytes = strlen(newname) + 1 + ARR_OVERHEAD(n); newArr = (ArrayType *) palloc(bytes); memmove(newArr, array, sizeof(ArrayType)); memmove(newArr, &bytes, sizeof(int)); memmove(ARR_DIMS(newArr), span, n * sizeof(int)); memmove(ARR_LBOUND(newArr), lowerIndx, n * sizeof(int)); strcpy(ARR_DATA_PTR(newArr), newname); rsize = compute_size(lowerIndx, upperIndx, n, len); if (rsize < MAX_BUFF_SIZE) { char *buff; rsize += VARHDRSZ; buff = palloc(rsize); if (buff) isDestLO = false; if (ARR_IS_CHUNKED(array)) { _ReadChunkArray(lowerIndx, upperIndx, len, fd, &(buff[VARHDRSZ]), array, 0, isNull); } else { _ReadArray(lowerIndx, upperIndx, len, fd, (int) &(buff[VARHDRSZ]), array, 0, isNull); } memmove(buff, &rsize, VARHDRSZ);#ifdef LOARRAY if (!*isNull) bytes = LOwrite(newfd, (struct varlena *) buff);#endif pfree(buff); } if (isDestLO) { if (ARR_IS_CHUNKED(array)) { _ReadChunkArray(lowerIndx, upperIndx, len, fd, (char *) newfd, array, 1, isNull); } else _ReadArray(lowerIndx, upperIndx, len, fd, newfd, array, 1, isNull); }#ifdef LOARRAY LOclose(fd); LOclose(newfd);#endif if (*isNull) { pfree(newArr); newArr = NULL; } /* timer_end(); */ return (Datum) newArr; } if (len > 0) { bytes = getNitems(n, span); bytes = bytes * len + ARR_OVERHEAD(n); } else { bytes = _ArrayClipCount(lowerIndx, upperIndx, array); bytes += ARR_OVERHEAD(n); } newArr = (ArrayType *) palloc(bytes); memmove(newArr, array, sizeof(ArrayType)); memmove(newArr, &bytes, sizeof(int)); memmove(ARR_DIMS(newArr), span, n * sizeof(int)); memmove(ARR_LBOUND(newArr), lowerIndx, n * sizeof(int)); _ArrayRange(lowerIndx, upperIndx, len, ARR_DATA_PTR(newArr), array, 1); return (Datum) newArr;}/*----------------------------------------------------------------------------- * array_set : * This routine sets the value of an array location (specified by an index array) * to a new value specified by "dataPtr". * result : * returns a pointer to the modified array. *----------------------------------------------------------------------------- */char *array_set(ArrayType *array, int n, int *indx, char *dataPtr, int reftype, int elmlen, int arraylen, bool *isNull){ int ndim, *dim, *lb, offset, nbytes; char *pos; if (array == (ArrayType *) NULL) RETURN_NULL; if (arraylen > 0) { /* * fixed length arrays -- these are assumed to be 1-d */ if (indx[0] * elmlen > arraylen) elog(ERROR, "array_ref: array bound exceeded"); pos = (char *) array + indx[0] * elmlen; ArrayCastAndSet(dataPtr, (bool) reftype, elmlen, pos); return (char *) array; } dim = ARR_DIMS(array); lb = ARR_LBOUND(array); ndim = ARR_NDIM(array); nbytes = (*(int32 *) array) - ARR_OVERHEAD(ndim); if (!SanityCheckInput(ndim, n, dim, lb, indx)) { elog(ERROR, "array_set: array bound exceeded"); return (char *) array; } offset = GetOffset(n, dim, lb, indx); if (ARR_IS_LO(array)) { int fd = 0; struct varlena *v; /* We are assuming fixed element lengths here */ offset *= elmlen;#ifdef LOARRAY char *lo_name; lo_name = ARR_DATA_PTR(array); if ((fd = LOopen(lo_name, ARR_IS_INV(array) ? INV_WRITE : O_WRONLY)) < 0) return (char *) array;#endif if (lo_lseek(fd, offset, SEEK_SET) < 0) return (char *) array; v = (struct varlena *) palloc(elmlen + VARHDRSZ); VARSIZE(v) = elmlen + VARHDRSZ; ArrayCastAndSet(dataPtr, (bool) reftype, elmlen, VARDATA(v));#ifdef LOARRAY n = LOwrite(fd, v);#endif /* * if (n < VARSIZE(v) - VARHDRSZ) RETURN_NULL; */ pfree(v); lo_close(fd); return (char *) array; } if (elmlen > 0) { offset = offset * elmlen; /* off the end of the array */ if (nbytes - offset < 1) return (char *) array; pos = ARR_DATA_PTR(array) + offset; } else { ArrayType *newarray; char *elt_ptr; int oldsize, newsize, oldlen, newlen, lth0, lth1, lth2; elt_ptr = array_seek(ARR_DATA_PTR(array), -1, offset); oldlen = INTALIGN(*(int32 *) elt_ptr); newlen = INTALIGN(*(int32 *) dataPtr); if (oldlen == newlen) { /* new element with same size, overwrite old data */ ArrayCastAndSet(dataPtr, (bool) reftype, elmlen, elt_ptr); return (char *) array; } /* new element with different size, reallocate the array */ oldsize = array->size; lth0 = ARR_OVERHEAD(n); lth1 = (int) (elt_ptr - ARR_DATA_PTR(array)); lth2 = (int) (oldsize - lth0 - lth1 - oldlen); newsize = lth0 + lth1 + newlen + lth2; newarray = (ArrayType *) palloc(newsize); memmove((char *) newarray, (char *) array, lth0 + lth1); newarray->size = newsize; newlen = ArrayCastAndSet(dataPtr, (bool) reftype, elmlen, (char *) newarray + lth0 + lth1); memmove((char *) newarray + lth0 + lth1 + newlen, (char *) array + lth0 + lth1 + oldlen, lth2); /* ??? who should free this storage ??? */ return (char *) newarray; } ArrayCastAndSet(dataPtr, (bool) reftype, elmlen, pos); return (char *) array;}/*---------------------------------------------------------------------------- * array_assgn : * This routine sets the value of a range of array locations (specified * by upper and lower index values ) to new values passed as * another array * result : * returns a pointer to the modified array. *---------------------------------------------------------------------------- */char *array_assgn(ArrayType *array, int n, int *upperIndx, int *lowerIndx, ArrayType *newArr, int reftype, int len, bool *isNull){ int i, ndim, *dim, *lb; if (array == (ArrayType *) NULL) RETURN_NULL; if (len < 0) elog(ERROR, "array_assgn:updates on arrays of variable length elements not allowed"); dim = ARR_DIMS(array); lb = ARR_LBOUND(array); ndim = ARR_NDIM(array); if (!SanityCheckInput(ndim, n, dim, lb, upperIndx) || !SanityCheckInput(ndim, n, dim, lb, lowerIndx)) return (char *) array; for (i = 0; i < n; i++) if (lowerIndx[i] > upperIndx[i]) elog(ERROR, "lowerIndex larger than upperIndx"); if (ARR_IS_LO(array)) { int fd = 0, newfd = 0;#ifdef LOARRAY char *lo_name; lo_name = (char *) ARR_DATA_PTR(array); if ((fd = LOopen(lo_name, ARR_IS_INV(array) ? INV_WRITE : O_WRONLY)) < 0) return (char *) array;#endif if (ARR_IS_LO(newArr)) {#ifdef LOARRAY lo_name = (char *) ARR_DATA_PTR(newArr); if ((newfd = LOopen(lo_name, ARR_IS_INV(newArr) ? INV_READ : O_RDONLY)) < 0) return (char *) array;#endif _LOArrayRange(lowerIndx, upperIndx, len, fd, newfd, array, 1, isNull); lo_close(newfd); } else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -