Common code for IS [NOT] NULL on a row value */
| 2698 | |
| 2699 | /* Common code for IS [NOT] NULL on a row value */ |
| 2700 | static void |
| 2701 | ExecEvalRowNullInt(ExprState *state, ExprEvalStep *op, |
| 2702 | ExprContext *econtext, bool checkisnull) |
| 2703 | { |
| 2704 | Datum value = *op->resvalue; |
| 2705 | bool isnull = *op->resnull; |
| 2706 | HeapTupleHeader tuple; |
| 2707 | Oid tupType; |
| 2708 | int32 tupTypmod; |
| 2709 | TupleDesc tupDesc; |
| 2710 | HeapTupleData tmptup; |
| 2711 | |
| 2712 | *op->resnull = false; |
| 2713 | |
| 2714 | /* NULL row variables are treated just as NULL scalar columns */ |
| 2715 | if (isnull) |
| 2716 | { |
| 2717 | *op->resvalue = BoolGetDatum(checkisnull); |
| 2718 | return; |
| 2719 | } |
| 2720 | |
| 2721 | /* |
| 2722 | * The SQL standard defines IS [NOT] NULL for a non-null rowtype argument |
| 2723 | * as: |
| 2724 | * |
| 2725 | * "R IS NULL" is true if every field is the null value. |
| 2726 | * |
| 2727 | * "R IS NOT NULL" is true if no field is the null value. |
| 2728 | * |
| 2729 | * This definition is (apparently intentionally) not recursive; so our |
| 2730 | * tests on the fields are primitive attisnull tests, not recursive checks |
| 2731 | * to see if they are all-nulls or no-nulls rowtypes. |
| 2732 | * |
| 2733 | * The standard does not consider the possibility of zero-field rows, but |
| 2734 | * here we consider them to vacuously satisfy both predicates. |
| 2735 | */ |
| 2736 | |
| 2737 | tuple = DatumGetHeapTupleHeader(value); |
| 2738 | |
| 2739 | tupType = HeapTupleHeaderGetTypeId(tuple); |
| 2740 | tupTypmod = HeapTupleHeaderGetTypMod(tuple); |
| 2741 | |
| 2742 | /* Lookup tupdesc if first time through or if type changes */ |
| 2743 | tupDesc = get_cached_rowtype(tupType, tupTypmod, |
| 2744 | &op->d.nulltest_row.rowcache, NULL); |
| 2745 | |
| 2746 | /* |
| 2747 | * heap_attisnull needs a HeapTuple not a bare HeapTupleHeader. |
| 2748 | */ |
| 2749 | tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple); |
| 2750 | tmptup.t_data = tuple; |
| 2751 | |
| 2752 | for (int att = 1; att <= tupDesc->natts; att++) |
| 2753 | { |
| 2754 | /* ignore dropped columns */ |
| 2755 | if (TupleDescAttr(tupDesc, att - 1)->attisdropped) |
| 2756 | continue; |
| 2757 | if (heap_attisnull(&tmptup, att, tupDesc)) |
no test coverage detected