|
7 | 7 | * |
8 | 8 | * |
9 | 9 | * IDENTIFICATION |
10 | | - * $Header: /cvsroot/pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.38 1999/02/13 23:19:00 momjian Exp $ |
| 10 | + * $Header: /cvsroot/pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.39 1999/05/0319:09:59 momjian Exp $ |
11 | 11 | * |
12 | 12 | *------------------------------------------------------------------------- |
13 | 13 | */ |
14 | 14 |
|
15 | 15 | #include<ctype.h> |
16 | 16 | #include<stdio.h> |
17 | 17 | #include<string.h> |
| 18 | +#include<stdarg.h> |
18 | 19 |
|
19 | 20 | #include"postgres.h" |
20 | 21 |
|
|
26 | 27 | #include"storage/fd.h" |
27 | 28 | #include"fmgr.h" |
28 | 29 | #include"utils/array.h" |
| 30 | +#include"utils/elog.h" |
29 | 31 |
|
30 | 32 | #include"libpq/libpq-fs.h" |
31 | 33 | #include"libpq/be-fsstubs.h" |
@@ -614,7 +616,9 @@ array_out(ArrayType *v, Oid element_type) |
614 | 616 | i, |
615 | 617 | j, |
616 | 618 | k, |
| 619 | +#ifndefTCL_ARRAYS |
617 | 620 | l, |
| 621 | +#endif |
618 | 622 | indx[MAXDIM]; |
619 | 623 | booldummy_bool; |
620 | 624 | intndim, |
@@ -1274,6 +1278,156 @@ array_assgn(ArrayType *array, |
1274 | 1278 | return (char*)array; |
1275 | 1279 | } |
1276 | 1280 |
|
| 1281 | +/* |
| 1282 | + * array_map() |
| 1283 | + * |
| 1284 | + * Map an arbitrary function to an array and return a new array with |
| 1285 | + * same dimensions and the source elements transformed by fn(). |
| 1286 | + */ |
| 1287 | +ArrayType* |
| 1288 | +array_map(ArrayType*v, |
| 1289 | +Oidtype, |
| 1290 | +char*(fn)(char*p, ...), |
| 1291 | +OidretType, |
| 1292 | +intnargs, |
| 1293 | + ...) |
| 1294 | +{ |
| 1295 | +ArrayType*result; |
| 1296 | +void*args[4]; |
| 1297 | +char**values; |
| 1298 | +char*elt; |
| 1299 | +int*dim; |
| 1300 | +intndim; |
| 1301 | +intnitems; |
| 1302 | +inti; |
| 1303 | +intnbytes=0; |
| 1304 | +intinp_typlen; |
| 1305 | +boolinp_typbyval; |
| 1306 | +inttyplen; |
| 1307 | +booltypbyval; |
| 1308 | +chartypdelim; |
| 1309 | +Oidtypelem; |
| 1310 | +Oidproc; |
| 1311 | +chartypalign; |
| 1312 | +char*s; |
| 1313 | +char*p; |
| 1314 | +va_listap; |
| 1315 | + |
| 1316 | +/* Large objects not yet supported */ |
| 1317 | +if (ARR_IS_LO(v)== true) { |
| 1318 | +elog(ERROR,"array_map: large objects not supported"); |
| 1319 | +} |
| 1320 | + |
| 1321 | +/* Check nargs */ |
| 1322 | +if ((nargs<0)|| (nargs>4)) { |
| 1323 | +elog(ERROR,"array_map: invalid nargs: %d",nargs); |
| 1324 | +} |
| 1325 | + |
| 1326 | +/* Copy extra args to local variable */ |
| 1327 | +va_start(ap,nargs); |
| 1328 | +for (i=0;i<nargs;i++) { |
| 1329 | +args[i]= (void*)va_arg(ap,char*); |
| 1330 | +} |
| 1331 | +va_end(ap); |
| 1332 | + |
| 1333 | +/* Lookup source and result types. Unneeded variables are reused. */ |
| 1334 | +system_cache_lookup(type, false,&inp_typlen,&inp_typbyval, |
| 1335 | +&typdelim,&typelem,&proc,&typalign); |
| 1336 | +system_cache_lookup(retType, false,&typlen,&typbyval, |
| 1337 | +&typdelim,&typelem,&proc,&typalign); |
| 1338 | + |
| 1339 | +/* Allocate temporary array for new values */ |
| 1340 | +ndim=ARR_NDIM(v); |
| 1341 | +dim=ARR_DIMS(v); |
| 1342 | +nitems=getNitems(ndim,dim); |
| 1343 | +values= (char**)palloc(nitems*sizeof(char*)); |
| 1344 | +MemSet(values,0,nitems*sizeof(char*)); |
| 1345 | + |
| 1346 | +/* Loop over source data */ |
| 1347 | +s= (char*)ARR_DATA_PTR(v); |
| 1348 | +for (i=0;i<nitems;i++) { |
| 1349 | +/* Get source element */ |
| 1350 | +if (inp_typbyval) { |
| 1351 | +switch (inp_typlen) { |
| 1352 | +case1: |
| 1353 | +elt= (char*) ((int) (*(char*)s)); |
| 1354 | +break; |
| 1355 | +case2: |
| 1356 | +elt= (char*) ((int) (*(int16*)s)); |
| 1357 | +break; |
| 1358 | +case3: |
| 1359 | +case4: |
| 1360 | +default: |
| 1361 | +elt= (char*) (*(int32*)s); |
| 1362 | +break; |
| 1363 | +} |
| 1364 | +s+=inp_typlen; |
| 1365 | +}else { |
| 1366 | +elt=s; |
| 1367 | +if (inp_typlen>0) { |
| 1368 | +s+=inp_typlen; |
| 1369 | +}else { |
| 1370 | +s+=INTALIGN(*(int32*)s); |
| 1371 | +} |
| 1372 | +} |
| 1373 | + |
| 1374 | +/* |
| 1375 | + * Apply the given function to source elt and extra args. |
| 1376 | + * nargs is the number of extra args taken by fn(). |
| 1377 | + */ |
| 1378 | +switch (nargs) { |
| 1379 | +case0: |
| 1380 | +p= (char*) (*fn) (elt); |
| 1381 | +break; |
| 1382 | +case1: |
| 1383 | +p= (char*) (*fn) (elt,args[0]); |
| 1384 | +break; |
| 1385 | +case2: |
| 1386 | +p= (char*) (*fn) (elt,args[0],args[1]); |
| 1387 | +break; |
| 1388 | +case3: |
| 1389 | +p= (char*) (*fn) (elt,args[0],args[1],args[2]); |
| 1390 | +break; |
| 1391 | +case4: |
| 1392 | +default: |
| 1393 | +p= (char*) (*fn) (elt,args[0],args[1],args[2],args[3]); |
| 1394 | +break; |
| 1395 | +} |
| 1396 | + |
| 1397 | +/* Update values and total result size */ |
| 1398 | +if (typbyval) { |
| 1399 | +values[i]= (char*)p; |
| 1400 | +nbytes+=typlen; |
| 1401 | +}else { |
| 1402 | +intlen; |
| 1403 | +len= ((typlen>0) ?typlen :INTALIGN(*(int32*)p)); |
| 1404 | +/* Needed because _CopyArrayEls tries to pfree items */ |
| 1405 | +if (p==elt) { |
| 1406 | +p= (char*)palloc(len); |
| 1407 | +memcpy(p,elt,len); |
| 1408 | +} |
| 1409 | +values[i]= (char*)p; |
| 1410 | +nbytes+=len; |
| 1411 | +} |
| 1412 | +} |
| 1413 | + |
| 1414 | +/* Allocate and initialize the result array */ |
| 1415 | +nbytes+=ARR_OVERHEAD(ndim); |
| 1416 | +result= (ArrayType*)palloc(nbytes); |
| 1417 | +MemSet(result,0,nbytes); |
| 1418 | + |
| 1419 | +memcpy((char*)result, (char*)&nbytes,sizeof(int)); |
| 1420 | +memcpy((char*)ARR_NDIM_PTR(result), (char*)&ndim,sizeof(int)); |
| 1421 | +memcpy((char*)ARR_DIMS(result),ARR_DIMS(v),2*ndim*sizeof(int)); |
| 1422 | + |
| 1423 | +/* Copy new values into the result array. values is pfreed. */ |
| 1424 | +_CopyArrayEls((char**)values, |
| 1425 | +ARR_DATA_PTR(result),nitems, |
| 1426 | +typlen,typalign,typbyval); |
| 1427 | + |
| 1428 | +returnresult; |
| 1429 | +} |
| 1430 | + |
1277 | 1431 | /*----------------------------------------------------------------------------- |
1278 | 1432 | * array_eq : |
1279 | 1433 | * compares two arrays for equality |
|