* numeric_support() * * Planner support function for the numeric() length coercion function. * * Flatten calls that solely represent increases in allowable precision. * Scale changes mutate every datum, so they are unoptimizable. Some values, * e.g. 1E-1001, can only fit into an unconstrained numeric, so a change from * an unconstrained numeric to any constrained numeric is also unoptimiza
| 838 | * an unconstrained numeric to any constrained numeric is also unoptimizable. |
| 839 | */ |
| 840 | Datum |
| 841 | numeric_support(PG_FUNCTION_ARGS) |
| 842 | { |
| 843 | Node *rawreq = (Node *) PG_GETARG_POINTER(0); |
| 844 | Node *ret = NULL; |
| 845 | |
| 846 | if (IsA(rawreq, SupportRequestSimplify)) |
| 847 | { |
| 848 | SupportRequestSimplify *req = (SupportRequestSimplify *) rawreq; |
| 849 | FuncExpr *expr = req->fcall; |
| 850 | Node *typmod; |
| 851 | |
| 852 | Assert(list_length(expr->args) >= 2); |
| 853 | |
| 854 | typmod = (Node *) lsecond(expr->args); |
| 855 | |
| 856 | if (IsA(typmod, Const) && !((Const *) typmod)->constisnull) |
| 857 | { |
| 858 | Node *source = (Node *) linitial(expr->args); |
| 859 | int32 old_typmod = exprTypmod(source); |
| 860 | int32 new_typmod = DatumGetInt32(((Const *) typmod)->constvalue); |
| 861 | int32 old_scale = (old_typmod - VARHDRSZ) & 0xffff; |
| 862 | int32 new_scale = (new_typmod - VARHDRSZ) & 0xffff; |
| 863 | int32 old_precision = (old_typmod - VARHDRSZ) >> 16 & 0xffff; |
| 864 | int32 new_precision = (new_typmod - VARHDRSZ) >> 16 & 0xffff; |
| 865 | |
| 866 | /* |
| 867 | * If new_typmod < VARHDRSZ, the destination is unconstrained; |
| 868 | * that's always OK. If old_typmod >= VARHDRSZ, the source is |
| 869 | * constrained, and we're OK if the scale is unchanged and the |
| 870 | * precision is not decreasing. See further notes in function |
| 871 | * header comment. |
| 872 | */ |
| 873 | if (new_typmod < (int32) VARHDRSZ || |
| 874 | (old_typmod >= (int32) VARHDRSZ && |
| 875 | new_scale == old_scale && new_precision >= old_precision)) |
| 876 | ret = relabel_to_typmod(source, new_typmod); |
| 877 | } |
| 878 | } |
| 879 | |
| 880 | PG_RETURN_POINTER(ret); |
| 881 | } |
| 882 | |
| 883 | /* |
| 884 | * numeric() - |
nothing calls this directly
no test coverage detected