|
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 | static Datum ExecEvalCase(CaseExprState *caseExpr, ExprContext *econtext,
|
77 | 77 | bool *isNull, ExprDoneCond *isDone);
|
| 78 | +static Datum ExecEvalArray(ArrayExprState *astate, |
| 79 | + ExprContext *econtext, |
| 80 | + bool *isNull); |
78 | 81 | static Datum ExecEvalCoalesce(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 | return PointerGetDatum(resultArray);
|
264 | 267 | }
|
265 | 268 |
|
266 | 269 | if (lIndex == NULL)
|
267 | 270 | return array_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 | return PointerGetDatum(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 | +static Datum |
| 1438 | +ExecEvalArray(ArrayExprState *astate, ExprContext *econtext, |
| 1439 | + bool *isNull) |
| 1440 | +{ |
| 1441 | + ArrayExpr *arrayExpr = (ArrayExpr *) astate->xprstate.expr; |
| 1442 | + ArrayType *result; |
| 1443 | + List *element; |
| 1444 | + Oid element_type = arrayExpr->element_typeid; |
| 1445 | + int ndims = arrayExpr->ndims; |
| 1446 | + int dims[MAXDIM]; |
| 1447 | + int lbs[MAXDIM]; |
| 1448 | + |
| 1449 | + if (ndims == 1) |
| 1450 | + { |
| 1451 | + int nelems; |
| 1452 | + Datum *dvalues; |
| 1453 | + int i = 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 | + bool eisnull; |
| 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 | + Size ndatabytes = 0; |
| 1491 | + int nbytes; |
| 1492 | + int outer_nelems = length(astate->elements); |
| 1493 | + int elem_ndims = 0; |
| 1494 | + int *elem_dims = NULL; |
| 1495 | + int *elem_lbs = NULL; |
| 1496 | + bool firstone = true; |
| 1497 | + int i; |
| 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 | + bool eisnull; |
| 1507 | + Datum arraydatum; |
| 1508 | + ArrayType *array; |
| 1509 | + int elem_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 | + return PointerGetDatum(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 | + case T_ArrayExpr: |
| 2068 | + retDatum = ExecEvalArray((ArrayExprState *) expression, |
| 2069 | + econtext, |
| 2070 | + isNull); |
| 2071 | + break; |
1911 | 2072 | case T_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 | + case T_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 | case T_CoalesceExpr:
|
2178 | 2369 | {
|
2179 | 2370 | CoalesceExpr *coalesceexpr = (CoalesceExpr *) node;
|
|
0 commit comments