* transformPLAssignStmt - * transform a PL/pgSQL assignment statement * * If there is no opt_indirection, the transformed statement looks like * "SELECT a_expr ...", except the expression has been cast to the type of * the target. With indirection, it's still a SELECT, but the expression will * incorporate FieldStore and/or assignment SubscriptingRef nodes to compute a * new value for a
| 3014 | * expression references the target as the container source. |
| 3015 | */ |
| 3016 | static Query * |
| 3017 | transformPLAssignStmt(ParseState *pstate, PLAssignStmt *stmt) |
| 3018 | { |
| 3019 | Query *qry = makeNode(Query); |
| 3020 | ColumnRef *cref = makeNode(ColumnRef); |
| 3021 | List *indirection = stmt->indirection; |
| 3022 | int nnames = stmt->nnames; |
| 3023 | SelectStmt *sstmt = stmt->val; |
| 3024 | Node *target; |
| 3025 | Oid targettype; |
| 3026 | int32 targettypmod; |
| 3027 | Oid targetcollation; |
| 3028 | List *tlist; |
| 3029 | TargetEntry *tle; |
| 3030 | Oid type_id; |
| 3031 | Node *qual; |
| 3032 | ListCell *l; |
| 3033 | |
| 3034 | /* |
| 3035 | * First, construct a ColumnRef for the target variable. If the target |
| 3036 | * has more than one dotted name, we have to pull the extra names out of |
| 3037 | * the indirection list. |
| 3038 | */ |
| 3039 | cref->fields = list_make1(makeString(stmt->name)); |
| 3040 | cref->location = stmt->location; |
| 3041 | if (nnames > 1) |
| 3042 | { |
| 3043 | /* avoid munging the raw parsetree */ |
| 3044 | indirection = list_copy(indirection); |
| 3045 | while (--nnames > 0 && indirection != NIL) |
| 3046 | { |
| 3047 | Node *ind = (Node *) linitial(indirection); |
| 3048 | |
| 3049 | if (!IsA(ind, String)) |
| 3050 | elog(ERROR, "invalid name count in PLAssignStmt"); |
| 3051 | cref->fields = lappend(cref->fields, ind); |
| 3052 | indirection = list_delete_first(indirection); |
| 3053 | } |
| 3054 | } |
| 3055 | |
| 3056 | /* |
| 3057 | * Transform the target reference. Typically we will get back a Param |
| 3058 | * node, but there's no reason to be too picky about its type. |
| 3059 | */ |
| 3060 | target = transformExpr(pstate, (Node *) cref, |
| 3061 | EXPR_KIND_UPDATE_TARGET); |
| 3062 | targettype = exprType(target); |
| 3063 | targettypmod = exprTypmod(target); |
| 3064 | targetcollation = exprCollation(target); |
| 3065 | |
| 3066 | /* |
| 3067 | * The rest mostly matches transformSelectStmt, except that we needn't |
| 3068 | * consider WITH or INTO, and we build a targetlist our own way. |
| 3069 | */ |
| 3070 | qry->commandType = CMD_SELECT; |
| 3071 | pstate->p_is_insert = false; |
| 3072 | |
| 3073 | /* make FOR UPDATE/FOR SHARE info available to addRangeTableEntry */ |
no test coverage detected