|
8 | 8 | *
|
9 | 9 | *
|
10 | 10 | * IDENTIFICATION
|
11 |
| - * $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.127 2003/03/27 16:51:27 momjian Exp $ |
| 11 | + * $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.128 2003/04/08 23:20:00 tgl Exp $ |
12 | 12 | *
|
13 | 13 | *-------------------------------------------------------------------------
|
14 | 14 | */
|
@@ -75,6 +75,9 @@ static Datum ExecEvalAnd(BoolExprState *andExpr, ExprContext *econtext,
|
75 | 75 | bool*isNull);
|
76 | 76 | staticDatumExecEvalCase(CaseExprState*caseExpr,ExprContext*econtext,
|
77 | 77 | bool*isNull,ExprDoneCond*isDone);
|
| 78 | +staticDatumExecEvalArray(ArrayExprState*astate, |
| 79 | +ExprContext*econtext, |
| 80 | +bool*isNull); |
78 | 81 | staticDatumExecEvalCoalesce(CoalesceExprState*coalesceExpr,
|
79 | 82 | ExprContext*econtext,
|
80 | 83 | bool*isNull);
|
@@ -246,38 +249,38 @@ ExecEvalArrayRef(ArrayRefExprState *astate,
|
246 | 249 | resultArray=array_set(array_source,i,
|
247 | 250 | upper.indx,
|
248 | 251 | sourceData,
|
249 |
| -arrayRef->refattrlength, |
250 |
| -arrayRef->refelemlength, |
251 |
| -arrayRef->refelembyval, |
252 |
| -arrayRef->refelemalign, |
| 252 | +astate->refattrlength, |
| 253 | +astate->refelemlength, |
| 254 | +astate->refelembyval, |
| 255 | +astate->refelemalign, |
253 | 256 | isNull);
|
254 | 257 | else
|
255 | 258 | resultArray=array_set_slice(array_source,i,
|
256 | 259 | upper.indx,lower.indx,
|
257 | 260 | (ArrayType*)DatumGetPointer(sourceData),
|
258 |
| -arrayRef->refattrlength, |
259 |
| -arrayRef->refelemlength, |
260 |
| -arrayRef->refelembyval, |
261 |
| -arrayRef->refelemalign, |
| 261 | +astate->refattrlength, |
| 262 | +astate->refelemlength, |
| 263 | +astate->refelembyval, |
| 264 | +astate->refelemalign, |
262 | 265 | isNull);
|
263 | 266 | returnPointerGetDatum(resultArray);
|
264 | 267 | }
|
265 | 268 |
|
266 | 269 | if (lIndex==NULL)
|
267 | 270 | returnarray_ref(array_source,i,upper.indx,
|
268 |
| -arrayRef->refattrlength, |
269 |
| -arrayRef->refelemlength, |
270 |
| -arrayRef->refelembyval, |
271 |
| -arrayRef->refelemalign, |
| 271 | +astate->refattrlength, |
| 272 | +astate->refelemlength, |
| 273 | +astate->refelembyval, |
| 274 | +astate->refelemalign, |
272 | 275 | isNull);
|
273 | 276 | else
|
274 | 277 | {
|
275 | 278 | resultArray=array_get_slice(array_source,i,
|
276 | 279 | upper.indx,lower.indx,
|
277 |
| -arrayRef->refattrlength, |
278 |
| -arrayRef->refelemlength, |
279 |
| -arrayRef->refelembyval, |
280 |
| -arrayRef->refelemalign, |
| 280 | +astate->refattrlength, |
| 281 | +astate->refelemlength, |
| 282 | +astate->refelembyval, |
| 283 | +astate->refelemalign, |
281 | 284 | isNull);
|
282 | 285 | returnPointerGetDatum(resultArray);
|
283 | 286 | }
|
@@ -613,6 +616,7 @@ init_fcache(Oid foid, FuncExprState *fcache, MemoryContext fcacheCxt)
|
613 | 616 |
|
614 | 617 | /* Initialize additional info */
|
615 | 618 | fcache->setArgsValid= false;
|
| 619 | +fcache->func.fn_expr= (Node*)fcache->xprstate.expr; |
616 | 620 | }
|
617 | 621 |
|
618 | 622 | /*
|
@@ -1426,6 +1430,158 @@ ExecEvalCase(CaseExprState *caseExpr, ExprContext *econtext,
|
1426 | 1430 | return (Datum)0;
|
1427 | 1431 | }
|
1428 | 1432 |
|
| 1433 | +/* ---------------------------------------------------------------- |
| 1434 | + *ExecEvalArray - ARRAY[] expressions |
| 1435 | + * ---------------------------------------------------------------- |
| 1436 | + */ |
| 1437 | +staticDatum |
| 1438 | +ExecEvalArray(ArrayExprState*astate,ExprContext*econtext, |
| 1439 | +bool*isNull) |
| 1440 | +{ |
| 1441 | +ArrayExpr*arrayExpr= (ArrayExpr*)astate->xprstate.expr; |
| 1442 | +ArrayType*result; |
| 1443 | +List*element; |
| 1444 | +Oidelement_type=arrayExpr->element_typeid; |
| 1445 | +intndims=arrayExpr->ndims; |
| 1446 | +intdims[MAXDIM]; |
| 1447 | +intlbs[MAXDIM]; |
| 1448 | + |
| 1449 | +if (ndims==1) |
| 1450 | +{ |
| 1451 | +intnelems; |
| 1452 | +Datum*dvalues; |
| 1453 | +inti=0; |
| 1454 | + |
| 1455 | +nelems=length(astate->elements); |
| 1456 | + |
| 1457 | +/* Shouldn't happen here, but if length is 0, return NULL */ |
| 1458 | +if (nelems==0) |
| 1459 | +{ |
| 1460 | +*isNull= true; |
| 1461 | +return (Datum)0; |
| 1462 | +} |
| 1463 | + |
| 1464 | +dvalues= (Datum*)palloc(nelems*sizeof(Datum)); |
| 1465 | + |
| 1466 | +/* loop through and build array of datums */ |
| 1467 | +foreach(element,astate->elements) |
| 1468 | +{ |
| 1469 | +ExprState*e= (ExprState*)lfirst(element); |
| 1470 | +booleisnull; |
| 1471 | + |
| 1472 | +dvalues[i++]=ExecEvalExpr(e,econtext,&eisnull,NULL); |
| 1473 | +if (eisnull) |
| 1474 | +elog(ERROR,"Arrays cannot have NULL elements"); |
| 1475 | +} |
| 1476 | + |
| 1477 | +/* setup for 1-D array of the given length */ |
| 1478 | +dims[0]=nelems; |
| 1479 | +lbs[0]=1; |
| 1480 | + |
| 1481 | +result=construct_md_array(dvalues,ndims,dims,lbs, |
| 1482 | +element_type, |
| 1483 | +astate->elemlength, |
| 1484 | +astate->elembyval, |
| 1485 | +astate->elemalign); |
| 1486 | +} |
| 1487 | +else |
| 1488 | +{ |
| 1489 | +char*dat=NULL; |
| 1490 | +Sizendatabytes=0; |
| 1491 | +intnbytes; |
| 1492 | +intouter_nelems=length(astate->elements); |
| 1493 | +intelem_ndims=0; |
| 1494 | +int*elem_dims=NULL; |
| 1495 | +int*elem_lbs=NULL; |
| 1496 | +boolfirstone= true; |
| 1497 | +inti; |
| 1498 | + |
| 1499 | +if (ndims <=0||ndims>MAXDIM) |
| 1500 | +elog(ERROR,"Arrays cannot have more than %d dimensions",MAXDIM); |
| 1501 | + |
| 1502 | +/* loop through and get data area from each element */ |
| 1503 | +foreach(element,astate->elements) |
| 1504 | +{ |
| 1505 | +ExprState*e= (ExprState*)lfirst(element); |
| 1506 | +booleisnull; |
| 1507 | +Datumarraydatum; |
| 1508 | +ArrayType*array; |
| 1509 | +intelem_ndatabytes; |
| 1510 | + |
| 1511 | +arraydatum=ExecEvalExpr(e,econtext,&eisnull,NULL); |
| 1512 | +if (eisnull) |
| 1513 | +elog(ERROR,"Arrays cannot have NULL elements"); |
| 1514 | + |
| 1515 | +array=DatumGetArrayTypeP(arraydatum); |
| 1516 | + |
| 1517 | +if (firstone) |
| 1518 | +{ |
| 1519 | +/* Get sub-array details from first member */ |
| 1520 | +elem_ndims=ARR_NDIM(array); |
| 1521 | +elem_dims= (int*)palloc(elem_ndims*sizeof(int)); |
| 1522 | +memcpy(elem_dims,ARR_DIMS(array),elem_ndims*sizeof(int)); |
| 1523 | +elem_lbs= (int*)palloc(elem_ndims*sizeof(int)); |
| 1524 | +memcpy(elem_lbs,ARR_LBOUND(array),elem_ndims*sizeof(int)); |
| 1525 | +firstone= false; |
| 1526 | +} |
| 1527 | +else |
| 1528 | +{ |
| 1529 | +/* Check other sub-arrays are compatible */ |
| 1530 | +if (elem_ndims!=ARR_NDIM(array)) |
| 1531 | +elog(ERROR,"Multiple dimension arrays must have array " |
| 1532 | +"expressions with matching number of dimensions"); |
| 1533 | + |
| 1534 | +if (memcmp(elem_dims,ARR_DIMS(array), |
| 1535 | +elem_ndims*sizeof(int))!=0) |
| 1536 | +elog(ERROR,"Multiple dimension arrays must have array " |
| 1537 | +"expressions with matching dimensions"); |
| 1538 | + |
| 1539 | +if (memcmp(elem_lbs,ARR_LBOUND(array), |
| 1540 | +elem_ndims*sizeof(int))!=0) |
| 1541 | +elog(ERROR,"Multiple dimension arrays must have array " |
| 1542 | +"expressions with matching dimensions"); |
| 1543 | +} |
| 1544 | + |
| 1545 | +elem_ndatabytes=ARR_SIZE(array)-ARR_OVERHEAD(elem_ndims); |
| 1546 | +ndatabytes+=elem_ndatabytes; |
| 1547 | +if (dat==NULL) |
| 1548 | +dat= (char*)palloc(ndatabytes); |
| 1549 | +else |
| 1550 | +dat= (char*)repalloc(dat,ndatabytes); |
| 1551 | + |
| 1552 | +memcpy(dat+ (ndatabytes-elem_ndatabytes), |
| 1553 | +ARR_DATA_PTR(array), |
| 1554 | +elem_ndatabytes); |
| 1555 | +} |
| 1556 | + |
| 1557 | +/* setup for multi-D array */ |
| 1558 | +dims[0]=outer_nelems; |
| 1559 | +lbs[0]=1; |
| 1560 | +for (i=1;i<ndims;i++) |
| 1561 | +{ |
| 1562 | +dims[i]=elem_dims[i-1]; |
| 1563 | +lbs[i]=elem_lbs[i-1]; |
| 1564 | +} |
| 1565 | + |
| 1566 | +nbytes=ndatabytes+ARR_OVERHEAD(ndims); |
| 1567 | +result= (ArrayType*)palloc(nbytes); |
| 1568 | + |
| 1569 | +result->size=nbytes; |
| 1570 | +result->ndim=ndims; |
| 1571 | +result->flags=0; |
| 1572 | +result->elemtype=element_type; |
| 1573 | +memcpy(ARR_DIMS(result),dims,ndims*sizeof(int)); |
| 1574 | +memcpy(ARR_LBOUND(result),lbs,ndims*sizeof(int)); |
| 1575 | +if (ndatabytes>0) |
| 1576 | +memcpy(ARR_DATA_PTR(result),dat,ndatabytes); |
| 1577 | + |
| 1578 | +if (dat!=NULL) |
| 1579 | +pfree(dat); |
| 1580 | +} |
| 1581 | + |
| 1582 | +returnPointerGetDatum(result); |
| 1583 | +} |
| 1584 | + |
1429 | 1585 | /* ----------------------------------------------------------------
|
1430 | 1586 | *ExecEvalCoalesce
|
1431 | 1587 | * ----------------------------------------------------------------
|
@@ -1908,6 +2064,11 @@ ExecEvalExpr(ExprState *expression,
|
1908 | 2064 | isNull,
|
1909 | 2065 | isDone);
|
1910 | 2066 | break;
|
| 2067 | +caseT_ArrayExpr: |
| 2068 | +retDatum=ExecEvalArray((ArrayExprState*)expression, |
| 2069 | +econtext, |
| 2070 | +isNull); |
| 2071 | +break; |
1911 | 2072 | caseT_CoalesceExpr:
|
1912 | 2073 | retDatum=ExecEvalCoalesce((CoalesceExprState*)expression,
|
1913 | 2074 | econtext,
|
@@ -2060,6 +2221,12 @@ ExecInitExpr(Expr *node, PlanState *parent)
|
2060 | 2221 | astate->refexpr=ExecInitExpr(aref->refexpr,parent);
|
2061 | 2222 | astate->refassgnexpr=ExecInitExpr(aref->refassgnexpr,
|
2062 | 2223 | parent);
|
| 2224 | +/* do one-time catalog lookups for type info */ |
| 2225 | +astate->refattrlength=get_typlen(aref->refarraytype); |
| 2226 | +get_typlenbyvalalign(aref->refelemtype, |
| 2227 | +&astate->refelemlength, |
| 2228 | +&astate->refelembyval, |
| 2229 | +&astate->refelemalign); |
2063 | 2230 | state= (ExprState*)astate;
|
2064 | 2231 | }
|
2065 | 2232 | break;
|
@@ -2174,6 +2341,30 @@ ExecInitExpr(Expr *node, PlanState *parent)
|
2174 | 2341 | state= (ExprState*)cstate;
|
2175 | 2342 | }
|
2176 | 2343 | break;
|
| 2344 | +caseT_ArrayExpr: |
| 2345 | +{ |
| 2346 | +ArrayExpr*arrayexpr= (ArrayExpr*)node; |
| 2347 | +ArrayExprState*astate=makeNode(ArrayExprState); |
| 2348 | +List*outlist=NIL; |
| 2349 | +List*inlist; |
| 2350 | + |
| 2351 | +foreach(inlist,arrayexpr->elements) |
| 2352 | +{ |
| 2353 | +Expr*e= (Expr*)lfirst(inlist); |
| 2354 | +ExprState*estate; |
| 2355 | + |
| 2356 | +estate=ExecInitExpr(e,parent); |
| 2357 | +outlist=lappend(outlist,estate); |
| 2358 | +} |
| 2359 | +astate->elements=outlist; |
| 2360 | +/* do one-time catalog lookup for type info */ |
| 2361 | +get_typlenbyvalalign(arrayexpr->element_typeid, |
| 2362 | +&astate->elemlength, |
| 2363 | +&astate->elembyval, |
| 2364 | +&astate->elemalign); |
| 2365 | +state= (ExprState*)astate; |
| 2366 | +} |
| 2367 | +break; |
2177 | 2368 | caseT_CoalesceExpr:
|
2178 | 2369 | {
|
2179 | 2370 | CoalesceExpr*coalesceexpr= (CoalesceExpr*)node;
|
|