* Prepare evaluation of a CoerceToDomain expression. */
| 3217 | * Prepare evaluation of a CoerceToDomain expression. |
| 3218 | */ |
| 3219 | static void |
| 3220 | ExecInitCoerceToDomain(ExprEvalStep *scratch, CoerceToDomain *ctest, |
| 3221 | ExprState *state, Datum *resv, bool *resnull) |
| 3222 | { |
| 3223 | DomainConstraintRef *constraint_ref; |
| 3224 | Datum *domainval = NULL; |
| 3225 | bool *domainnull = NULL; |
| 3226 | ListCell *l; |
| 3227 | |
| 3228 | scratch->d.domaincheck.resulttype = ctest->resulttype; |
| 3229 | /* we'll allocate workspace only if needed */ |
| 3230 | scratch->d.domaincheck.checkvalue = NULL; |
| 3231 | scratch->d.domaincheck.checknull = NULL; |
| 3232 | |
| 3233 | /* |
| 3234 | * Evaluate argument - it's fine to directly store it into resv/resnull, |
| 3235 | * if there's constraint failures there'll be errors, otherwise it's what |
| 3236 | * needs to be returned. |
| 3237 | */ |
| 3238 | ExecInitExprRec(ctest->arg, state, resv, resnull); |
| 3239 | |
| 3240 | /* |
| 3241 | * Note: if the argument is of varlena type, it could be a R/W expanded |
| 3242 | * object. We want to return the R/W pointer as the final result, but we |
| 3243 | * have to pass a R/O pointer as the value to be tested by any functions |
| 3244 | * in check expressions. We don't bother to emit a MAKE_READONLY step |
| 3245 | * unless there's actually at least one check expression, though. Until |
| 3246 | * we've tested that, domainval/domainnull are NULL. |
| 3247 | */ |
| 3248 | |
| 3249 | /* |
| 3250 | * Collect the constraints associated with the domain. |
| 3251 | * |
| 3252 | * Note: before PG v10 we'd recheck the set of constraints during each |
| 3253 | * evaluation of the expression. Now we bake them into the ExprState |
| 3254 | * during executor initialization. That means we don't need typcache.c to |
| 3255 | * provide compiled exprs. |
| 3256 | */ |
| 3257 | constraint_ref = (DomainConstraintRef *) |
| 3258 | palloc(sizeof(DomainConstraintRef)); |
| 3259 | InitDomainConstraintRef(ctest->resulttype, |
| 3260 | constraint_ref, |
| 3261 | CurrentMemoryContext, |
| 3262 | false); |
| 3263 | |
| 3264 | /* |
| 3265 | * Compile code to check each domain constraint. NOTNULL constraints can |
| 3266 | * just be applied on the resv/resnull value, but for CHECK constraints we |
| 3267 | * need more pushups. |
| 3268 | */ |
| 3269 | foreach(l, constraint_ref->constraints) |
| 3270 | { |
| 3271 | DomainConstraintState *con = (DomainConstraintState *) lfirst(l); |
| 3272 | Datum *save_innermost_domainval; |
| 3273 | bool *save_innermost_domainnull; |
| 3274 | |
| 3275 | scratch->d.domaincheck.constraintname = con->name; |
| 3276 |
no test coverage detected