1 /*-------------------------------------------------------------------------
4 * Special functions for arrays.
6 * Copyright (c) 1994, Regents of the University of California
10 * $Header: /cvsroot/pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.35 1999/01/17 06:18:45 momjian Exp $
12 *-------------------------------------------------------------------------
21 #include "catalog/catalog.h"
22 #include "catalog/pg_type.h"
24 #include "utils/syscache.h"
25 #include "utils/memutils.h"
26 #include "storage/fd.h"
28 #include "utils/array.h"
30 #include "libpq/libpq-fs.h"
31 #include "libpq/be-fsstubs.h"
35 /* An array has the following internal structure:
36 * <nbytes> - total number of bytes
37 * <ndim> - number of dimensions of the array
38 * <flags> - bit mask of flags
39 * <dim> - size of each array axis
40 * <dim_lower> - lower boundary of each dimension
41 * <actual data> - whatever is the stored data
44 /*-=-=--=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-*/
45 static int _ArrayCount(char *str, int *dim, int typdelim);
46 static char *_ReadArrayStr(char *arrayStr, int nitems, int ndim, int *dim,
47 FmgrInfo *inputproc, Oid typelem, int32 typmod,
48 char typdelim, int typlen, bool typbyval,
49 char typalign, int *nbytes);
52 static char *_ReadLOArray(char *str, int *nbytes, int *fd, bool *chunkFlag,
53 int ndim, int *dim, int baseSize);
56 static void _CopyArrayEls(char **values, char *p, int nitems, int typlen,
57 char typalign, bool typbyval);
58 static void system_cache_lookup(Oid element_type, bool input, int *typlen,
59 bool *typbyval, char *typdelim, Oid *typelem, Oid *proc,
61 static Datum _ArrayCast(char *value, bool byval, int len);
64 static char *_AdvanceBy1word(char *str, char **word);
67 static void _ArrayRange(int *st, int *endp, int bsize, char *destPtr,
68 ArrayType *array, int from);
69 static int _ArrayClipCount(int *stI, int *endpI, ArrayType *array);
70 static void _LOArrayRange(int *st, int *endp, int bsize, int srcfd,
71 int destfd, ArrayType *array, int isSrcLO, bool *isNull);
72 static void _ReadArray(int *st, int *endp, int bsize, int srcfd, int destfd,
73 ArrayType *array, int isDestLO, bool *isNull);
74 static int ArrayCastAndSet(char *src, bool typbyval, int typlen, char *dest);
75 static int SanityCheckInput(int ndim, int n, int *dim, int *lb, int *indx);
76 static int array_read(char *destptr, int eltsize, int nitems, char *srcptr);
77 static char *array_seek(char *ptr, int eltsize, int nitems);
79 /*---------------------------------------------------------------------
81 * converts an array from the external format in "string" to
84 * the internal representation of the input array
85 *--------------------------------------------------------------------
88 array_in(char *string, /* input array in external form */
89 Oid element_type, /* type OID of an array element */
107 ArrayType *retval = NULL;
113 system_cache_lookup(element_type, true, &typlen, &typbyval, &typdelim,
114 &typelem, &typinput, &typalign);
116 fmgr_info(typinput, &inputproc);
118 string_save = (char *) palloc(strlen(string) + 3);
119 strcpy(string_save, string);
121 /* --- read array dimensions ---------- */
124 for (ndim = 0; !done;)
131 if ((r = (char *) strchr(p, ':')) == (char *) NULL)
136 lBound[ndim] = atoi(p);
139 for (q = p; isdigit(*q); q++);
141 elog(ERROR, "array_in: missing ']' in array declaration");
144 if ((dim[ndim] < 0) || (lBound[ndim] < 0))
145 elog(ERROR, "array_in: array dimensions need to be positive");
146 dim[ndim] = dim[ndim] - lBound[ndim] + 1;
148 elog(ERROR, "array_in: upper_bound cannot be < lower_bound");
160 ndim = _ArrayCount(p, dim, typdelim);
161 for (i = 0; i < ndim; lBound[i++] = 1);
164 elog(ERROR, "array_in: Need to specify dimension");
170 if (strncmp(p, ASSGN, strlen(ASSGN)))
171 elog(ERROR, "array_in: missing assignment operator");
178 printf("array_in- ndim %d (", ndim);
179 for (i = 0; i < ndim; i++)
181 printf(" %d", dim[i]);
183 printf(") for %s\n", string);
186 nitems = getNitems(ndim, dim);
189 char *emptyArray = palloc(sizeof(ArrayType));
191 MemSet(emptyArray, 0, sizeof(ArrayType));
192 *(int32 *) emptyArray = sizeof(ArrayType);
198 /* array not a large object */
200 (char *) _ReadArrayStr(p, nitems, ndim, dim, &inputproc, typelem,
201 typmod, typdelim, typlen, typbyval, typalign,
203 nbytes += ARR_OVERHEAD(ndim);
204 retval = (ArrayType *) palloc(nbytes);
205 MemSet(retval, 0, nbytes);
206 memmove(retval, (char *) &nbytes, sizeof(int));
207 memmove((char *) ARR_NDIM_PTR(retval), (char *) &ndim, sizeof(int));
208 SET_LO_FLAG(false, retval);
209 memmove((char *) ARR_DIMS(retval), (char *) dim, ndim * sizeof(int));
210 memmove((char *) ARR_LBOUND(retval), (char *) lBound,
214 * dataPtr is an array of arbitraystuff even though its type is
215 * char* cast to char** to pass to _CopyArrayEls for now - jolly
217 _CopyArrayEls((char **) dataPtr,
218 ARR_DATA_PTR(retval), nitems,
219 typlen, typalign, typbyval);
226 bool chunked = false;
228 dataPtr = _ReadLOArray(p, &bytes, &dummy, &chunked, ndim,
230 nbytes = bytes + ARR_OVERHEAD(ndim);
231 retval = (ArrayType *) palloc(nbytes);
232 MemSet(retval, 0, nbytes);
233 memmove(retval, (char *) &nbytes, sizeof(int));
234 memmove((char *) ARR_NDIM_PTR(retval), (char *) &ndim, sizeof(int));
235 SET_LO_FLAG(true, retval);
236 SET_CHUNK_FLAG(chunked, retval);
237 memmove((char *) ARR_DIMS(retval), (char *) dim, ndim * sizeof(int));
238 memmove((char *) ARR_LBOUND(retval), (char *) lBound, ndim * sizeof(int));
239 memmove(ARR_DATA_PTR(retval), dataPtr, bytes);
241 elog(ERROR, "large object arrays not supported");
244 return (char *) retval;
247 /*-----------------------------------------------------------------------------
249 * Counts the number of dimensions and the *dim array for an array string.
250 * The syntax for array input is C-like nested curly braces
251 *-----------------------------------------------------------------------------
254 _ArrayCount(char *str, int *dim, int typdelim)
260 bool scanning_string = false;
261 bool eoArray = false;
264 for (i = 0; i < MAXDIM; ++i)
265 temp[i] = dim[i] = 0;
267 if (strncmp(str, "{}", 2) == 0)
271 while (eoArray != true)
280 /* skip escaped characters (\ and ") inside strings */
281 if (scanning_string && *(q + 1))
287 * Signal a premature end of the string. DZ -
290 elog(ERROR, "malformed array constant: %s", str);
293 scanning_string = !scanning_string;
296 if (!scanning_string)
298 temp[nest_level] = 0;
303 if (!scanning_string)
309 temp[nest_level - 1]++;
311 eoArray = done = true;
317 if (*q == typdelim && !scanning_string)
330 for (i = 0; i < ndim; ++i)
336 /*---------------------------------------------------------------------------
338 * parses the array string pointed by "arrayStr" and converts it in the
339 * internal format. The external format expected is like C array
340 * declaration. Unspecified elements are initialized to zero for fixed length
341 * base types and to empty varlena structures for variable length base
344 * returns the internal representation of the array elements
345 * nbytes is set to the size of the array in its internal representation.
346 *---------------------------------------------------------------------------
349 _ReadArrayStr(char *arrayStr,
353 FmgrInfo *inputproc, /* function used for the
369 bool scanning_string = false;
372 bool eoArray = false;
374 mda_get_prod(ndim, dim, prod);
375 for (i = 0; i < ndim; indx[i++] = 0);
376 /* read array enclosed within {} */
377 values = (char **) palloc(nitems * sizeof(char *));
378 MemSet(values, 0, nitems * sizeof(char *));
391 /* Crunch the string on top of the backslash. */
392 for (r = q; *r != '\0'; r++)
396 if (!scanning_string)
400 p++; /* get p past first doublequote */
404 scanning_string = !scanning_string;
407 if (!scanning_string)
411 if (nest_level > ndim)
412 elog(ERROR, "array_in: illformed array constant");
413 indx[nest_level - 1] = 0;
418 if (!scanning_string)
421 i = tuple2linear(ndim, indx, prod);
424 eoArray = done = true;
428 indx[nest_level - 1]++;
433 if (*q == typdelim && !scanning_string)
436 i = tuple2linear(ndim, indx, prod);
447 elog(ERROR, "array_in: illformed array constant");
448 values[i] = (*fmgr_faddr(inputproc)) (p, typelem, typmod);
453 * if not at the end of the array skip white space
463 *nbytes = nitems * typlen;
465 for (i = 0; i < nitems; i++)
468 values[i] = palloc(typlen);
469 MemSet(values[i], 0, typlen);
474 for (i = 0, *nbytes = 0; i < nitems; i++)
479 *nbytes += DOUBLEALIGN(*(int32 *) values[i]);
481 *nbytes += INTALIGN(*(int32 *) values[i]);
485 *nbytes += sizeof(int32);
486 values[i] = palloc(sizeof(int32));
487 *(int32 *) values[i] = sizeof(int32);
491 return (char *) values;
495 /*----------------------------------------------------------------------------
496 * Read data about an array to be stored as a large object
497 *----------------------------------------------------------------------------
501 _ReadLOArray(char *str,
516 str = _AdvanceBy1word(str, &inputfile);
522 str = _AdvanceBy1word(str, &word);
524 if (!strcmp(word, "-chunk"))
527 elog(ERROR, "array_in: access pattern file required");
528 str = _AdvanceBy1word(str, &accessfile);
530 else if (!strcmp(word, "-noreorg"))
533 elog(ERROR, "array_in: chunk file required");
534 str = _AdvanceBy1word(str, &chunkfile);
537 elog(ERROR, "usage: <input file> -chunk DEFAULT/<access pattern file> -invert/-native [-noreorg <chunk file>]");
540 if (inputfile == NULL)
541 elog(ERROR, "array_in: missing file name");
542 lobjId = lo_creat(0);
543 *fd = lo_open(lobjId, INV_READ);
545 elog(ERROR, "Large object create failed");
547 *nbytes = strlen(retStr) + 2;
554 if ((afd = AllocateFile(accessfile, "r")) == NULL)
556 if ((afd = AllocateFile(accessfile, "r")) == NULL)
558 elog(ERROR, "unable to open access pattern file");
560 retStr = _ChunkArray(*fd, afd, ndim, dim, baseSize, nbytes,
570 _CopyArrayEls(char **values,
579 for (i = 0; i < nitems; i++)
583 inc = ArrayCastAndSet(values[i], typbyval, typlen, p);
591 /*-------------------------------------------------------------------------
593 * takes the internal representation of an array and returns a string
594 * containing the array in its external format.
595 *-------------------------------------------------------------------------
598 array_out(ArrayType *v, Oid element_type)
624 if (v == (ArrayType *) NULL)
625 return (char *) NULL;
627 if (ARR_IS_LO(v) == true)
633 /* get a wide string to print to */
634 p = array_dims(v, &dummy_bool);
635 nbytes = strlen(ARR_DATA_PTR(v)) + VARHDRSZ + *(int *) p;
637 save_p = (char *) palloc(nbytes);
639 strcpy(save_p, p + sizeof(int));
640 strcat(save_p, ASSGN);
641 strcat(save_p, ARR_DATA_PTR(v));
646 system_cache_lookup(element_type, false, &typlen, &typbyval,
647 &typdelim, &typelem, &typoutput, &typalign);
648 fmgr_info(typoutput, &outputproc);
649 sprintf(delim, "%c", typdelim);
652 nitems = getNitems(ndim, dim);
656 char *emptyArray = palloc(3);
660 emptyArray[2] = '\0';
665 overall_length = 1; /* [TRH] don't forget to count \0 at end. */
666 values = (char **) palloc(nitems * sizeof(char *));
667 for (i = 0; i < nitems; i++)
674 values[i] = (*fmgr_faddr(&outputproc)) (*p, typelem);
677 values[i] = (*fmgr_faddr(&outputproc)) (*(int16 *) p, typelem);
681 values[i] = (*fmgr_faddr(&outputproc)) (*(int32 *) p, typelem);
688 values[i] = (*fmgr_faddr(&outputproc)) (p, typelem);
692 p += INTALIGN(*(int32 *) p);
695 * For the pair of double quotes
699 for (tmp = values[i]; *tmp; tmp++)
709 * count total number of curly braces in output string
711 for (i = j = 0, k = 1; i < ndim; k *= dim[i++], j += k);
713 p = (char *) palloc(overall_length + 2 * j);
717 for (i = 0; i < ndim; indx[i++] = 0);
722 for (i = j; i < ndim - 1; i++)
726 * Surround anything that is not passed by value in double quotes.
727 * See above for more details.
733 for (tmp = values[k]; *tmp; tmp++)
743 strcat(p, values[k]);
746 for (i = ndim - 1; i >= 0; i--)
748 indx[i] = (indx[i] + 1) % dim[i];
764 /*-----------------------------------------------------------------------------
766 * returns the dimension of the array pointed to by "v"
767 *----------------------------------------------------------------------------
770 array_dims(ArrayType *v, bool *isNull)
779 if (v == (ArrayType *) NULL)
781 nbytes = ARR_NDIM(v) * 33;
784 * 33 since we assume 15 digits per number + ':' +'[]'
786 save_p = p = (char *) palloc(nbytes + VARHDRSZ);
787 MemSet(save_p, 0, nbytes + VARHDRSZ);
791 for (i = 0; i < ARR_NDIM(v); i++)
793 sprintf(p, "[%d:%d]", lb[i], dimv[i] + lb[i] - 1);
796 nbytes = strlen(save_p + VARHDRSZ) + VARHDRSZ;
797 memmove(save_p, &nbytes, VARHDRSZ);
801 /*---------------------------------------------------------------------------
803 * This routing takes an array pointer and an index array and returns
804 * a pointer to the referred element if element is passed by
805 * reference otherwise returns the value of the referred element.
806 *---------------------------------------------------------------------------
809 array_ref(ArrayType *array,
823 struct varlena *v = NULL;
826 if (array == (ArrayType *) NULL)
832 * fixed length arrays -- these are assumed to be 1-d
834 if (indx[0] * elmlen > arraylen)
835 elog(ERROR, "array_ref: array bound exceeded");
836 retval = (char *) array + indx[0] * elmlen;
837 return _ArrayCast(retval, reftype, elmlen);
839 dim = ARR_DIMS(array);
840 lb = ARR_LBOUND(array);
841 ndim = ARR_NDIM(array);
842 nbytes = (*(int32 *) array) - ARR_OVERHEAD(ndim);
844 if (!SanityCheckInput(ndim, n, dim, lb, indx))
847 offset = GetOffset(n, dim, lb, indx);
849 if (ARR_IS_LO(array))
854 /* We are assuming fixed element lengths here */
856 lo_name = (char *) ARR_DATA_PTR(array);
858 if ((fd = LOopen(lo_name, ARR_IS_INV(array) ? INV_READ : O_RDONLY)) < 0)
861 if (ARR_IS_CHUNKED(array))
862 v = _ReadChunkArray1El(indx, elmlen, fd, array, isNull);
865 if (lo_lseek(fd, offset, SEEK_SET) < 0)
868 v = (struct varlena *) LOread(fd, elmlen);
873 if (VARSIZE(v) - VARHDRSZ < elmlen)
876 retval = (char *) _ArrayCast((char *) VARDATA(v), reftype, elmlen);
879 char *tempdata = palloc(elmlen);
881 memmove(tempdata, retval, elmlen);
885 return (Datum) retval;
890 offset = offset * elmlen;
891 /* off the end of the array */
892 if (nbytes - offset < 1)
894 retval = ARR_DATA_PTR(array) + offset;
895 return _ArrayCast(retval, reftype, elmlen);
903 temp = ARR_DATA_PTR(array);
905 while (bytes > 0 && !done)
912 bytes -= INTALIGN(*(int32 *) temp);
913 temp += INTALIGN(*(int32 *) temp);
918 return (Datum) retval;
922 /*-----------------------------------------------------------------------------
924 * This routine takes an array and a range of indices (upperIndex and
925 * lowerIndx), creates a new array structure for the referred elements
926 * and returns a pointer to it.
927 *-----------------------------------------------------------------------------
930 array_clip(ArrayType *array,
948 if (array == (ArrayType *) NULL)
950 dim = ARR_DIMS(array);
951 lb = ARR_LBOUND(array);
952 ndim = ARR_NDIM(array);
953 nbytes = (*(int32 *) array) - ARR_OVERHEAD(ndim);
955 if (!SanityCheckInput(ndim, n, dim, lb, upperIndx))
958 if (!SanityCheckInput(ndim, n, dim, lb, lowerIndx))
961 for (i = 0; i < n; i++)
962 if (lowerIndx[i] > upperIndx[i])
963 elog(ERROR, "lowerIndex cannot be larger than upperIndx");
964 mda_get_range(n, span, lowerIndx, upperIndx);
966 if (ARR_IS_LO(array))
972 char *newname = NULL;
979 elog(ERROR, "array_clip: array of variable length objects not supported");
981 lo_name = (char *) ARR_DATA_PTR(array);
982 if ((fd = LOopen(lo_name, ARR_IS_INV(array) ? INV_READ : O_RDONLY)) < 0)
984 newname = _array_newLO(&newfd, Unix);
986 bytes = strlen(newname) + 1 + ARR_OVERHEAD(n);
987 newArr = (ArrayType *) palloc(bytes);
988 memmove(newArr, array, sizeof(ArrayType));
989 memmove(newArr, &bytes, sizeof(int));
990 memmove(ARR_DIMS(newArr), span, n * sizeof(int));
991 memmove(ARR_LBOUND(newArr), lowerIndx, n * sizeof(int));
992 strcpy(ARR_DATA_PTR(newArr), newname);
994 rsize = compute_size(lowerIndx, upperIndx, n, len);
995 if (rsize < MAX_BUFF_SIZE)
1000 buff = palloc(rsize);
1003 if (ARR_IS_CHUNKED(array))
1005 _ReadChunkArray(lowerIndx, upperIndx, len, fd, &(buff[VARHDRSZ]),
1010 _ReadArray(lowerIndx, upperIndx, len, fd, (int) &(buff[VARHDRSZ]),
1014 memmove(buff, &rsize, VARHDRSZ);
1017 bytes = LOwrite(newfd, (struct varlena *) buff);
1023 if (ARR_IS_CHUNKED(array))
1025 _ReadChunkArray(lowerIndx, upperIndx, len, fd, (char *) newfd, array,
1029 _ReadArray(lowerIndx, upperIndx, len, fd, newfd, array, 1, isNull);
1041 return (Datum) newArr;
1046 bytes = getNitems(n, span);
1047 bytes = bytes * len + ARR_OVERHEAD(n);
1051 bytes = _ArrayClipCount(lowerIndx, upperIndx, array);
1052 bytes += ARR_OVERHEAD(n);
1054 newArr = (ArrayType *) palloc(bytes);
1055 memmove(newArr, array, sizeof(ArrayType));
1056 memmove(newArr, &bytes, sizeof(int));
1057 memmove(ARR_DIMS(newArr), span, n * sizeof(int));
1058 memmove(ARR_LBOUND(newArr), lowerIndx, n * sizeof(int));
1059 _ArrayRange(lowerIndx, upperIndx, len, ARR_DATA_PTR(newArr), array, 1);
1060 return (Datum) newArr;
1063 /*-----------------------------------------------------------------------------
1065 * This routine sets the value of an array location (specified by an index array)
1066 * to a new value specified by "dataPtr".
1068 * returns a pointer to the modified array.
1069 *-----------------------------------------------------------------------------
1072 array_set(ArrayType *array,
1088 if (array == (ArrayType *) NULL)
1094 * fixed length arrays -- these are assumed to be 1-d
1096 if (indx[0] * elmlen > arraylen)
1097 elog(ERROR, "array_ref: array bound exceeded");
1098 pos = (char *) array + indx[0] * elmlen;
1099 ArrayCastAndSet(dataPtr, (bool) reftype, elmlen, pos);
1100 return (char *) array;
1102 dim = ARR_DIMS(array);
1103 lb = ARR_LBOUND(array);
1104 ndim = ARR_NDIM(array);
1105 nbytes = (*(int32 *) array) - ARR_OVERHEAD(ndim);
1107 if (!SanityCheckInput(ndim, n, dim, lb, indx))
1109 elog(ERROR, "array_set: array bound exceeded");
1110 return (char *) array;
1112 offset = GetOffset(n, dim, lb, indx);
1114 if (ARR_IS_LO(array))
1119 /* We are assuming fixed element lengths here */
1124 lo_name = ARR_DATA_PTR(array);
1125 if ((fd = LOopen(lo_name, ARR_IS_INV(array) ? INV_WRITE : O_WRONLY)) < 0)
1126 return (char *) array;
1128 if (lo_lseek(fd, offset, SEEK_SET) < 0)
1129 return (char *) array;
1130 v = (struct varlena *) palloc(elmlen + VARHDRSZ);
1131 VARSIZE(v) = elmlen + VARHDRSZ;
1132 ArrayCastAndSet(dataPtr, (bool) reftype, elmlen, VARDATA(v));
1138 * if (n < VARSIZE(v) - VARHDRSZ) RETURN_NULL;
1142 return (char *) array;
1146 offset = offset * elmlen;
1147 /* off the end of the array */
1148 if (nbytes - offset < 1)
1149 return (char *) array;
1150 pos = ARR_DATA_PTR(array) + offset;
1154 ArrayType *newarray;
1164 elt_ptr = array_seek(ARR_DATA_PTR(array), -1, offset);
1165 oldlen = INTALIGN(*(int32 *) elt_ptr);
1166 newlen = INTALIGN(*(int32 *) dataPtr);
1168 if (oldlen == newlen)
1170 /* new element with same size, overwrite old data */
1171 ArrayCastAndSet(dataPtr, (bool) reftype, elmlen, elt_ptr);
1172 return (char *) array;
1175 /* new element with different size, reallocate the array */
1176 oldsize = array->size;
1177 lth0 = ARR_OVERHEAD(n);
1178 lth1 = (int) (elt_ptr - ARR_DATA_PTR(array));
1179 lth2 = (int) (oldsize - lth0 - lth1 - oldlen);
1180 newsize = lth0 + lth1 + newlen + lth2;
1182 newarray = (ArrayType *) palloc(newsize);
1183 memmove((char *) newarray, (char *) array, lth0 + lth1);
1184 newarray->size = newsize;
1185 newlen = ArrayCastAndSet(dataPtr, (bool) reftype, elmlen,
1186 (char *) newarray + lth0 + lth1);
1187 memmove((char *) newarray + lth0 + lth1 + newlen,
1188 (char *) array + lth0 + lth1 + oldlen, lth2);
1190 /* ??? who should free this storage ??? */
1191 return (char *) newarray;
1193 ArrayCastAndSet(dataPtr, (bool) reftype, elmlen, pos);
1194 return (char *) array;
1197 /*----------------------------------------------------------------------------
1199 * This routine sets the value of a range of array locations (specified
1200 * by upper and lower index values ) to new values passed as
1203 * returns a pointer to the modified array.
1204 *----------------------------------------------------------------------------
1207 array_assgn(ArrayType *array,
1221 if (array == (ArrayType *) NULL)
1224 elog(ERROR, "array_assgn:updates on arrays of variable length elements not allowed");
1226 dim = ARR_DIMS(array);
1227 lb = ARR_LBOUND(array);
1228 ndim = ARR_NDIM(array);
1230 if (!SanityCheckInput(ndim, n, dim, lb, upperIndx) ||
1231 !SanityCheckInput(ndim, n, dim, lb, lowerIndx))
1232 return (char *) array;
1234 for (i = 0; i < n; i++)
1235 if (lowerIndx[i] > upperIndx[i])
1236 elog(ERROR, "lowerIndex larger than upperIndx");
1238 if (ARR_IS_LO(array))
1246 lo_name = (char *) ARR_DATA_PTR(array);
1247 if ((fd = LOopen(lo_name, ARR_IS_INV(array) ? INV_WRITE : O_WRONLY)) < 0)
1248 return (char *) array;
1250 if (ARR_IS_LO(newArr))
1253 lo_name = (char *) ARR_DATA_PTR(newArr);
1254 if ((newfd = LOopen(lo_name, ARR_IS_INV(newArr) ? INV_READ : O_RDONLY)) < 0)
1255 return (char *) array;
1257 _LOArrayRange(lowerIndx, upperIndx, len, fd, newfd, array, 1, isNull);
1262 _LOArrayRange(lowerIndx, upperIndx, len, fd, (int) ARR_DATA_PTR(newArr),
1266 return (char *) array;
1268 _ArrayRange(lowerIndx, upperIndx, len, ARR_DATA_PTR(newArr), array, 0);
1269 return (char *) array;
1272 /*-----------------------------------------------------------------------------
1274 * compares two arrays for equality
1276 * returns 1 if the arrays are equal, 0 otherwise.
1277 *-----------------------------------------------------------------------------
1280 array_eq(ArrayType *array1, ArrayType *array2)
1282 if ((array1 == NULL) || (array2 == NULL))
1284 if (*(int *) array1 != *(int *) array2)
1286 if (memcmp(array1, array2, *(int *) array1))
1291 /***************************************************************************/
1292 /******************| Support Routines |*****************/
1293 /***************************************************************************/
1295 system_cache_lookup(Oid element_type,
1304 HeapTuple typeTuple;
1305 Form_pg_type typeStruct;
1307 typeTuple = SearchSysCacheTuple(TYPOID,
1308 ObjectIdGetDatum(element_type),
1311 if (!HeapTupleIsValid(typeTuple))
1313 elog(ERROR, "array_out: Cache lookup failed for type %d\n",
1317 typeStruct = (Form_pg_type) GETSTRUCT(typeTuple);
1318 *typlen = typeStruct->typlen;
1319 *typbyval = typeStruct->typbyval;
1320 *typdelim = typeStruct->typdelim;
1321 *typelem = typeStruct->typelem;
1322 *typalign = typeStruct->typalign;
1324 *proc = typeStruct->typinput;
1326 *proc = typeStruct->typoutput;
1330 _ArrayCast(char *value, bool byval, int len)
1337 return (Datum) *value;
1339 return (Datum) *(int16 *) value;
1342 return (Datum) *(int32 *) value;
1344 elog(ERROR, "array_ref: byval and elt len > 4!");
1349 return (Datum) value;
1355 ArrayCastAndSet(char *src,
1369 *dest = DatumGetChar(src);
1372 *(int16 *) dest = DatumGetInt16(src);
1375 *(int32 *) dest = (int32) src;
1380 memmove(dest, src, typlen);
1385 memmove(dest, src, *(int32 *) src);
1386 inc = (INTALIGN(*(int32 *) src));
1393 _AdvanceBy1word(char *str, char **word)
1401 while (isspace(*str))
1404 if ((space = (char *) strchr(str, ' ')) != (char *) NULL)
1417 SanityCheckInput(int ndim, int n, int *dim, int *lb, int *indx)
1421 /* Do Sanity check on input */
1424 for (i = 0; i < ndim; i++)
1425 if ((lb[i] > indx[i]) || (indx[i] >= (dim[i] + lb[i])))
1431 _ArrayRange(int *st,
1451 n = ARR_NDIM(array);
1452 dim = ARR_DIMS(array);
1453 lb = ARR_LBOUND(array);
1454 srcPtr = ARR_DATA_PTR(array);
1455 for (i = 0; i < n; st[i] -= lb[i], endp[i] -= lb[i], i++);
1456 mda_get_prod(n, dim, prod);
1457 st_pos = tuple2linear(n, st, prod);
1458 srcPtr = array_seek(srcPtr, bsize, st_pos);
1459 mda_get_range(n, span, st, endp);
1460 mda_get_offset_values(n, dist, prod, span);
1461 for (i = 0; i < n; indx[i++] = 0);
1466 srcPtr = array_seek(srcPtr, bsize, dist[j]);
1468 inc = array_read(destPtr, bsize, 1, srcPtr);
1470 inc = array_read(srcPtr, bsize, 1, destPtr);
1473 } while ((j = next_tuple(i + 1, indx, span)) != -1);
1477 _ArrayClipCount(int *stI, int *endpI, ArrayType *array)
1495 n = ARR_NDIM(array);
1496 dim = ARR_DIMS(array);
1497 lb = ARR_LBOUND(array);
1498 ptr = ARR_DATA_PTR(array);
1499 for (i = 0; i < n; st[i] = stI[i] - lb[i], endp[i] = endpI[i] - lb[i], i++);
1500 mda_get_prod(n, dim, prod);
1501 st_pos = tuple2linear(n, st, prod);
1502 ptr = array_seek(ptr, -1, st_pos);
1503 mda_get_range(n, span, st, endp);
1504 mda_get_offset_values(n, dist, prod, span);
1505 for (i = 0; i < n; indx[i++] = 0);
1509 ptr = array_seek(ptr, -1, dist[j]);
1510 inc = INTALIGN(*(int32 *) ptr);
1513 } while ((j = next_tuple(i + 1, indx, span)) != -1);
1518 array_seek(char *ptr, int eltsize, int nitems)
1523 return ptr + eltsize * nitems;
1524 for (i = 0; i < nitems; i++)
1525 ptr += INTALIGN(*(int32 *) ptr);
1530 array_read(char *destptr, int eltsize, int nitems, char *srcptr)
1538 memmove(destptr, srcptr, eltsize * nitems);
1539 return eltsize * nitems;
1541 for (i = inc = 0; i < nitems; i++)
1543 tmp = (INTALIGN(*(int32 *) srcptr));
1544 memmove(destptr, srcptr, tmp);
1553 _LOArrayRange(int *st,
1576 n = ARR_NDIM(array);
1577 dim = ARR_DIMS(array);
1578 lb = ARR_LBOUND(array);
1579 for (i = 0; i < n; st[i] -= lb[i], endp[i] -= lb[i], i++);
1581 mda_get_prod(n, dim, prod);
1582 st_pos = tuple2linear(n, st, prod);
1583 offset = st_pos * bsize;
1584 if (lo_lseek(srcfd, offset, SEEK_SET) < 0)
1586 mda_get_range(n, span, st, endp);
1587 mda_get_offset_values(n, dist, prod, span);
1588 for (i = 0; i < n; indx[i++] = 0);
1589 for (i = n - 1, inc = bsize; i >= 0; inc *= span[i--])
1595 offset += (dist[j] * bsize);
1596 if (lo_lseek(srcfd, offset, SEEK_SET) < 0)
1598 tmp = _LOtransfer((char **) &srcfd, inc, 1, (char **) &destfd, isSrcLO, 1);
1602 } while ((j = next_tuple(i + 1, indx, span)) != -1);
1630 n = ARR_NDIM(array);
1631 dim = ARR_DIMS(array);
1632 lb = ARR_LBOUND(array);
1633 for (i = 0; i < n; st[i] -= lb[i], endp[i] -= lb[i], i++);
1635 mda_get_prod(n, dim, prod);
1636 st_pos = tuple2linear(n, st, prod);
1637 offset = st_pos * bsize;
1638 if (lo_lseek(srcfd, offset, SEEK_SET) < 0)
1640 mda_get_range(n, span, st, endp);
1641 mda_get_offset_values(n, dist, prod, span);
1642 for (i = 0; i < n; indx[i++] = 0);
1643 for (i = n - 1, inc = bsize; i >= 0; inc *= span[i--])
1649 offset += (dist[j] * bsize);
1650 if (lo_lseek(srcfd, offset, SEEK_SET) < 0)
1652 tmp = _LOtransfer((char **) &destfd, inc, 1, (char **) &srcfd, 1, isDestLO);
1656 } while ((j = next_tuple(i + 1, indx, span)) != -1);
1661 _LOtransfer(char **destfd,
1668 #define MAX_READ (512 * 1024)
1669 #define min(a, b) (a < b ? a : b)
1670 struct varlena *v = NULL;
1675 inc = nitems * size;
1676 if (isSrcLO && isDestLO && inc > 0)
1677 for (tmp = 0, resid = inc;
1678 resid > 0 && (inc = min(resid, MAX_READ)) > 0; resid -= inc)
1681 v = (struct varlena *) LOread((int) *srcfd, inc);
1682 if (VARSIZE(v) - VARHDRSZ < inc)
1687 tmp += LOwrite((int) *destfd, v);
1692 else if (!isSrcLO && isDestLO)
1694 tmp = lo_write((int) *destfd, *srcfd, inc);
1695 *srcfd = *srcfd + tmp;
1697 else if (isSrcLO && !isDestLO)
1699 tmp = lo_read((int) *srcfd, *destfd, inc);
1700 *destfd = *destfd + tmp;
1704 memmove(*destfd, *srcfd, inc);
1714 _array_newLO(int *fd, int flag)
1717 char saveName[NAME_LEN];
1719 p = (char *) palloc(NAME_LEN);
1720 sprintf(p, "/Arry.%d", newoid());
1721 strcpy(saveName, p);
1723 if ((*fd = LOcreat(saveName, 0600, flag)) < 0)
1724 elog(ERROR, "Large object create failed");