Re: Avoiding rewrite in ALTER TABLE ALTER TYPE

From: Noah Misch <noah(at)leadboat(dot)com>
To: Robert Haas <robertmhaas(at)gmail(dot)com>
Cc: "pgsql-hackers(at)postgresql(dot)org" <pgsql-hackers(at)postgresql(dot)org>
Subject: Re: Avoiding rewrite in ALTER TABLE ALTER TYPE
Date: 2010-12-31 01:35:34
Message-ID: 20101231013534.GA7521@tornado.leadboat.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

On Thu, Dec 30, 2010 at 12:57:45AM -0500, Robert Haas wrote:
> On Thu, Dec 30, 2010 at 12:24 AM, Noah Misch <noah(at)leadboat(dot)com> wrote:
> > On Wed, Dec 29, 2010 at 11:14:37PM -0500, Robert Haas wrote:
> >> I think for any pair of types (T1, T2) we should first determine
> >> whether we can skip the scan altogether. ?If yes, we're done. ?If no,
> >> then we should have a way of determining whether a verify-only scan is
> >> guaranteed to be sufficient (in your terminology, the verification
> >> scan is guaranteed to return either positive or error, not negative).
> >> If yes, then we do a verification scan. ?If no, we do a rewrite.
> >
> > How would we answer the second question in general?
>
> I am not sure - I guess we'd need to design some sort of mechanism for that.

Okay, here goes. Given a Var "varexpr" representing the column we're changing
and an expression tree "expr" we need to answer two questions (argument lists
simplified -- assume the same RTEs in all cases):

always-noop: "Will datumIsEquals(ExecEvalExpr(varexpr), ExecEvalExpr(expr))
return true or yield an error for all possible tuples?"
never-error: "Will ExecEvalExpr(expr) never throw an error?"

Currently we're only interested in the second question when the first is also
true; I'm not sure if there's something fundamental there, or just an artifact
of current needs. To support answering these questions, extend the CREATE CAST
changes from my earlier proposal, modifying the exemptor signature to return an
int, a bitmask containing one bit for each of these two questions. Call the
function in find_typmod_coercion_function. If its return value answers "yes" to
both questions, return COERCION_PATH_NONE, resulting in omission of the length
coercion node. For other verdicts, generate the FuncExpr as normal and insert
the verdict in a new FuncExpr field "funcexempt". (That need not increase the
size of FuncExpr, if that's a concern.)

ATPrepAlterColumnType, having generated its transformation expression, will call
a new function that recursively walks the tree to answer the two questions. The
walker will apply these rules:

1. For a Var with the varno/varattno in question, intrinsically "yes" to both.
2. A RelabelType node inherits the answers of its sole argument.
3. A CoerceToDomain node inherits the always-noop answer of its sole argument.
When GetDomainConstraints() == NIL, it also inherits the never-error answer.
Otherwise, never-error becomes "no".
4. A FuncExpr node has answers given by the bitwise-AND of its funcexempt field
and the answers from its first argument.
5. Any other node answers "no" to both questions.

If the transformation expression root has "yes" to both questions, we're done
with no scan. If only always-noop is true, we do a verification scan only.
Otherwise, we optimize nothing and do a rewrite.

Thoughts?

Thanks,
nm

In response to

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Simon Riggs 2010-12-31 01:38:32 Re: Sync Rep Design
Previous Message Simon Riggs 2010-12-31 01:15:10 Re: Sync Rep Design