Thread: using index or check in ALTER TABLE SET NOT NULL

using index or check in ALTER TABLE SET NOT NULL

From
Sergei Kornilov
Date:
Hello
I write patch to speed up ALTER TABLE SET NOT NULL by check existed check constraints or indexes. Huge phase 3 with
verifytable data will be skipped if table has valid check constraint cover "alteredfield IS NOT NULL" condition or by
SPIquery if found index with compatible condition or regular amsearchnulls index on processed field.
 

Patch based on current master branch, i believe it has no platform-dependent code, of course code compiled and pass
testslocally.
 
Tell me please, what i forgot or make incorrectly.

Implementation notes:
I use existed PartConstraintImpliedByRelConstraint method to check relation constraints. But i rename original method
tostatic ConstraintImpliedByRelConstraint (because method now used not only in partitions) and leave
PartConstraintImpliedByRelConstraintas proxy to not change public API.
 
I found it difficult to do index scan and choose index with lower costs if found many suitable indexes. Is it
acceptableto use SPI here?
 

Related archive discussions:
https://www.postgresql.org/message-id/flat/530C10CF.4020101%40strangersgate.com
https://www.postgresql.org/message-id/flat/CAASwCXdAK55BzuOy_FtYj2zQWg26PriDKL5pRoWiyFJe0eg-Hg%40mail.gmail.com

Thanks!
Attachment

Re: using index or check in ALTER TABLE SET NOT NULL

From
Robert Haas
Date:
On Tue, Nov 28, 2017 at 1:59 PM, Sergei Kornilov <sk@zsrv.org> wrote:
> I write patch to speed up ALTER TABLE SET NOT NULL by check existed check constraints or indexes. Huge phase 3 with
verifytable data will be skipped if table has valid check constraint cover "alteredfield IS NOT NULL" condition or by
SPIquery if found index with compatible condition or regular amsearchnulls index on processed field. 

Doing this based on the existence of a valid constraint which implies
that no nulls can be present seems like a good idea.  Doing it based
on an index scan doesn't necessarily seem like a good idea.  We have
no guarantee at all that the index scan will be faster than scanning
the table would have been, and a single table scan can do multiple
verification steps if, for example, multiple columns are set NOT NULL
at the same time.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company


Re: using index or check in ALTER TABLE SET NOT NULL

From
Stephen Frost
Date:
Robert,

* Robert Haas (robertmhaas@gmail.com) wrote:
> On Tue, Nov 28, 2017 at 1:59 PM, Sergei Kornilov <sk@zsrv.org> wrote:
> > I write patch to speed up ALTER TABLE SET NOT NULL by check existed check constraints or indexes. Huge phase 3 with
verifytable data will be skipped if table has valid check constraint cover "alteredfield IS NOT NULL" condition or by
SPIquery if found index with compatible condition or regular amsearchnulls index on processed field. 
>
> Doing this based on the existence of a valid constraint which implies
> that no nulls can be present seems like a good idea.  Doing it based
> on an index scan doesn't necessarily seem like a good idea.  We have
> no guarantee at all that the index scan will be faster than scanning
> the table would have been, and a single table scan can do multiple
> verification steps if, for example, multiple columns are set NOT NULL
> at the same time.

Isn't the first concern addressed by using SPI..?

As for the second concern, couldn't that be done with a more complicated
query through SPI, though things might have to be restructured some to
make it possible to do that.

Just, generally speaking, this is definitely something that I think we
want and neither of the above concerns seem like they're technical
reasons why we can't use something like this approach, just needs to
perhaps be reworked to handle multiple columns in a single query.

Thanks!

Stephen

Re: using index or check in ALTER TABLE SET NOT NULL

From
Tom Lane
Date:
Stephen Frost <sfrost@snowman.net> writes:
> Isn't the first concern addressed by using SPI..?

I did not look at the patch yet, but TBH if it uses SPI for sub-operations
of ALTER TABLE I think that is sufficient reason to reject it out of hand.
Doing things that way would create way too much of a vulnerability surface
for code touching a partially-updated table.  At minimum, we'd have to
blow holes in existing protections like CheckTableNotInUse, and I think
we'd be forever finding other stuff that failed to work quite right in
that context.  I do not want ALTER TABLE going anywhere near the planner
or executor; I'm not even happy that it uses the parser (for index
definition reconstruction).
        regards, tom lane


Re: using index or check in ALTER TABLE SET NOT NULL

From
Sergei Kornilov
Date:
Thanks all for reply!

Robert,

> Doing it based on an index scan doesn't necessarily seem like a good idea. We have
> no guarantee at all that the index scan will be faster than scanning
> the table would have been

I agree this. Thinking a little about idea of index scan i can not give reasonable usecase which required index. My
targetproblem of adding NOT NULL to big relation without long downtime can be done with ADD CONSTRAINT NOT VALID,
VALIDATEit in second transaction, then SET NOT NULL by my patch and drop unneeded constraint.
 

Stephen,

> Just, generally speaking, this is definitely something that I think we
> want and neither of the above concerns seem like they're technical
> reasons why we can't use something like this approach, just needs to
> perhaps be reworked to handle multiple columns in a single query.

I understood the idea, thank you.

Tom,

> I did not look at the patch yet, but TBH if it uses SPI for sub-operations
> of ALTER TABLE I think that is sufficient reason to reject it out of hand.

I understood, thank you.

So, i will soon delete SPI usage and index scan and post new simplified patch with verify data only by constraints.


Re: using index or check in ALTER TABLE SET NOT NULL

From
Stephen Frost
Date:
Tom,

* Tom Lane (tgl@sss.pgh.pa.us) wrote:
> Stephen Frost <sfrost@snowman.net> writes:
> > Isn't the first concern addressed by using SPI..?
>
> I did not look at the patch yet, but TBH if it uses SPI for sub-operations
> of ALTER TABLE I think that is sufficient reason to reject it out of hand.

You mean like what ALTER TABLE ... ADD FOREIGN KEY does?

> Doing things that way would create way too much of a vulnerability surface
> for code touching a partially-updated table.  At minimum, we'd have to
> blow holes in existing protections like CheckTableNotInUse, and I think
> we'd be forever finding other stuff that failed to work quite right in
> that context.  I do not want ALTER TABLE going anywhere near the planner
> or executor; I'm not even happy that it uses the parser (for index
> definition reconstruction).

That's more along the lines of the kind of response I was expecting
given the suggestion, and perhaps a good reason to just go with the
index-based lookup, when an index is available to do so with, but I'm
not entirely sure how this is different from how we handle foreign keys.

Thanks!

Stephen

Re: using index or check in ALTER TABLE SET NOT NULL

From
Robert Haas
Date:
On Wed, Nov 29, 2017 at 10:52 AM, Sergei Kornilov <sk@zsrv.org> wrote:
> I agree this. Thinking a little about idea of index scan i can not give reasonable usecase which required index. My
targetproblem of adding NOT NULL to big relation without long downtime can be done with ADD CONSTRAINT NOT VALID,
VALIDATEit in second transaction, then SET NOT NULL by my patch and drop unneeded constraint. 

Yes, I had the same thought.

Thinking a little bit further, maybe the idea you had in mind using
the index scan was that some indexes offer cheap ways of testing
whether ANY nulls are present in the column.  For example, if we had a
non-partial btree index whose first column is the one being made NOT
NULL, we could try an index scan - via index_beginscan() /
index_getnext() / index_endscan() - trying to pull exactly one null
from the index, and judge whether or not there are nulls present based
only whether we get one.  This would be a lot cheaper than scanning a
large table, but it needs some careful thought because of visibility
issues.  It's not sufficient that the index contains no nulls that are
visible to our snapshot; it must contain no nulls that are visible to
any plausible current or future snapshot.  I doubt that test can be
written in SQL, but it can probably be written in C.  Moreover, we
need to avoid not only false negatives (thinking that there is no NULL
when there is one) but also false positives (thinking there's a NULL
in the column when there isn't, and thus failing spuriously).  But it
seems like it might be useful if someone can figure out the details of
how to make it 100% correct; one index lookup is sure to be a lot
quicker than a full table scan.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company


Re: using index or check in ALTER TABLE SET NOT NULL

From
Tom Lane
Date:
Stephen Frost <sfrost@snowman.net> writes:
> * Tom Lane (tgl@sss.pgh.pa.us) wrote:
>> I did not look at the patch yet, but TBH if it uses SPI for sub-operations
>> of ALTER TABLE I think that is sufficient reason to reject it out of hand.

> You mean like what ALTER TABLE ... ADD FOREIGN KEY does?

Yeah, and if you look at the warts that SPI has grown to support that
usage, you'll see why I'm so unhappy.  We should never have allowed
FKs to be built on top of SPI; they require semantics that don't exist
in SQL.  I think this would lead to more of the same --- not exactly
the same of course, but more warts.  See Robert's nearby musings about
semantics of index null checks for an example.
        regards, tom lane


Re: using index or check in ALTER TABLE SET NOT NULL

From
Stephen Frost
Date:
Robert,

* Robert Haas (robertmhaas@gmail.com) wrote:
> On Wed, Nov 29, 2017 at 10:52 AM, Sergei Kornilov <sk@zsrv.org> wrote:
> > I agree this. Thinking a little about idea of index scan i can not give reasonable usecase which required index. My
targetproblem of adding NOT NULL to big relation without long downtime can be done with ADD CONSTRAINT NOT VALID,
VALIDATEit in second transaction, then SET NOT NULL by my patch and drop unneeded constraint. 
>
> Yes, I had the same thought.

I have to admit that the case I was thinking about was the one you
outline below..

> Thinking a little bit further, maybe the idea you had in mind using
> the index scan was that some indexes offer cheap ways of testing
> whether ANY nulls are present in the column.  For example, if we had a
> non-partial btree index whose first column is the one being made NOT
> NULL, we could try an index scan - via index_beginscan() /
> index_getnext() / index_endscan() - trying to pull exactly one null
> from the index, and judge whether or not there are nulls present based
> only whether we get one.  This would be a lot cheaper than scanning a
> large table, but it needs some careful thought because of visibility
> issues.  It's not sufficient that the index contains no nulls that are
> visible to our snapshot; it must contain no nulls that are visible to
> any plausible current or future snapshot.  I doubt that test can be
> written in SQL, but it can probably be written in C.  Moreover, we
> need to avoid not only false negatives (thinking that there is no NULL
> when there is one) but also false positives (thinking there's a NULL
> in the column when there isn't, and thus failing spuriously).  But it
> seems like it might be useful if someone can figure out the details of
> how to make it 100% correct; one index lookup is sure to be a lot
> quicker than a full table scan.

This was along the lines I was thinking also (though I had thought SPI
might be reasonable given our usage of it with FKs, but if it'd require
uglier warts than what SPI already has, then just finding an
appropriate index and using the internal methods would be best).

As for conflicting snapshots, isn't the lock we're taking already
AccessExclusive..?

Thanks!

Stephen

Re: using index or check in ALTER TABLE SET NOT NULL

From
Sergei Kornilov
Date:
Here is new patch with check only existed valid constraints and without SPI at all.

Thanks
Attachment

Re: using index or check in ALTER TABLE SET NOT NULL

From
Andres Freund
Date:

On November 29, 2017 8:50:31 AM PST, Stephen Frost <sfrost@snowman.net> wrote:
>As for conflicting snapshots, isn't the lock we're taking already
>AccessExclusive..?

Doesn't help if e.g. the current xact is repeatable read or if your own xact deleted things (other xacts with snapshots
couldstill see null rows, despite new take definition).  

Andres
--
Sent from my Android device with K-9 Mail. Please excuse my brevity.


Re: using index or check in ALTER TABLE SET NOT NULL

From
Robert Haas
Date:
On Wed, Nov 29, 2017 at 11:53 AM, Sergei Kornilov <sk@zsrv.org> wrote:
> Here is new patch with check only existed valid constraints and without SPI at all.

Please use pgindent or anyway try to follow project style.  { needs to
go on a line by itself, for example.

isSetNotNullNeedsTableScan seems different than other similarly-named
functions we have.  NotNullImpliedByRelConstraints?

It also lacks a header comment.

Having both PartConstraintImpliedByRelConstraint and
ConstraintImpliedByRelConstraint with identical implementations
doesn't seem like a good idea to me.  I guess just renaming it is
probably fine.

The comment /* T if we added new NOT NULL constraints */ should
probably be changed to /* T if we should recheck NOT NULL constraints
*/ or similar.

I'd suggest registering this with the next CommitFest.

-- 
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company


Re: using index or check in ALTER TABLE SET NOT NULL

From
Sergei Kornilov
Date:
Hello
I update patch and also rebase to current head. I hope now it is better aligned with project style
Attachment

Re: using index or check in ALTER TABLE SET NOT NULL

From
Stephen Frost
Date:
Greetings Sergei,

* Sergei Kornilov (sk@zsrv.org) wrote:
> I update patch and also rebase to current head. I hope now it is better aligned with project style

Thanks for updating it and continuing to work on it.  I haven't done a
full review but there were a few things below that I thought could be
improved-

> @@ -5863,8 +5864,11 @@ ATExecSetNotNull(AlteredTableInfo *tab, Relation rel,
>
>          CatalogTupleUpdate(attr_rel, &tuple->t_self, tuple);
>
> -        /* Tell Phase 3 it needs to test the constraint */
> -        tab->new_notnull = true;
> +        if (!NotNullImpliedByRelConstraints(rel, (Form_pg_attribute) GETSTRUCT(tuple)))
> +        {
> +            /* Tell Phase 3 it needs to test the constraint */
> +            tab->verify_new_notnull = true;
> +        }
>
>          ObjectAddressSubSet(address, RelationRelationId,
>                              RelationGetRelid(rel), attnum);

This could really use some additional comments, imv.  In particular, we
need to make it clear that verify_new_notnull only moves from the
initial 'false' value to 'true', since we could be asked to add multiple
NOT NULL constraints and if any of them aren't already covered by an
existing CHECK constraint then we need to perform the full table check.

> @@ -13618,15 +13662,14 @@ ComputePartitionAttrs(Relation rel, List *partParams, AttrNumber *partattrs,
>  }
>
>  /*
> - * PartConstraintImpliedByRelConstraint
> - *        Does scanrel's existing constraints imply the partition constraint?
> + * ConstraintImpliedByRelConstraint
> + *        Does scanrel's existing constraints imply given constraint
>   *
>   * Existing constraints includes its check constraints and column-level
>   * NOT NULL constraints and partConstraint describes the partition constraint.
>   */
>  bool
> -PartConstraintImpliedByRelConstraint(Relation scanrel,
> -                                     List *partConstraint)
> +ConstraintImpliedByRelConstraint(Relation scanrel, List *partConstraint)
>  {
>      List       *existConstraint = NIL;
>      TupleConstr *constr = RelationGetDescr(scanrel)->constr;

I would also rename 'partConstraint' since this function is no longer,
necessairly, working with a partition's constraint.

This could also really use some regression tests and I'd be sure to
include tests of adding multiple NOT NULL constraints, sometimes where
they're all covered by existing CHECK constraints and other times when
only one or the other is (and there's existing NULL values in the other
column), etc.

Thanks!

Stephen

Attachment

Re: using index or check in ALTER TABLE SET NOT NULL

From
Sergei Kornilov
Date:
Hello Stephen

I changed the suggested things and added some regression tests. Also i wrote few words to the documentation. New patch
isattached.
 

Thank you for feedback!
regards, Sergei
Attachment

Re: using index or check in ALTER TABLE SET NOT NULL

From
Ildar Musin
Date:
Hello Sergei,

I couldn't find any case when your code doesn't work properly. So it 
seems ok to me.

> @@ -220,6 +220,13 @@ WITH ( MODULUS <replaceable class="parameter">numeric_literal</replaceable>, REM
>       </para>
>
>       <para>
> +      Full table scan is performed to check that no existing row
> +      in the table has null values in given column.  It is possible to avoid
> +      this scan by adding a valid <literal>CHECK</literal> constraint to
> +      the table that would allow only NOT NULL values for given column.
> +     </para>

Adding check constraint will also force the full table scan. So I think 
it would be better to rephrased it as follows:

"Full table scan is performed to check that column doesn't contain NULL 
values unless there are valid check constraints that prohibit NULL 
values for specified column. In the latter case table scan is skipped."

A native English speaker input would be helpful here.

Regarding regression tests it may be useful to set client_min_messages 
to 'debug1' before setting "NOT NULL" attribute for a column. In this 
case you can tell for sure that NotNullImpliedByRelConstraints() 
returned true (i.e. your code actually did the job) as the special debug 
message is printed to the log.

Thanks!

-- 
Ildar Musin
i.musin@postgrespro.ru


Re: using index or check in ALTER TABLE SET NOT NULL

From
Sergei Kornilov
Date:
Hello
thank you for review!

> Adding check constraint will also force the full table scan. So I think
> it would be better to rephrased it as follows:
Agree. I updated docs in new attached patch slightly different

> Regarding regression tests it may be useful to set client_min_messages
> to 'debug1' before setting "NOT NULL" attribute for a column. In this
> case you can tell for sure that NotNullImpliedByRelConstraints()
> returned true (i.e. your code actually did the job) as the special debug
> message is printed to the log.
I can not find any debug messages in tests: grep client_min_messages -irn src/test/ Only some warning level and few
error.So i verify in regression tests only top-level behavior.
 
Or this paragraph was for other people, not for tests?

regards, Sergei
Attachment

Re: using index or check in ALTER TABLE SET NOT NULL

From
Ildar Musin
Date:

On 06.03.2018 16:12, Sergei Kornilov wrote:
> Hello thank you for review!
>
>> Adding check constraint will also force the full table scan. So I
>> think it would be better to rephrased it as follows:
> Agree. I updated docs in new attached patch slightly different
>
>> Regarding regression tests it may be useful to set
>> client_min_messages to 'debug1' before setting "NOT NULL" attribute
>> for a column. In this case you can tell for sure that
>> NotNullImpliedByRelConstraints() returned true (i.e. your code
>> actually did the job) as the special debug message is printed to
>> the log.
> I can not find any debug messages in tests: grep client_min_messages
> -irn src/test/ Only some warning level and few error. So i verify in
> regression tests only top-level behavior. Or this paragraph was for
> other people, not for tests?
>

Sorry, probably I didn't explain it clearly enough. I meant that your
regression tests can't distinguish cases when the full table scan was
actually performed from the ones when it was skipped due to
NotNullImpliedByRelConstraints() check. For instance, consider this
piece from the test suite:


# create table atacc1 (test_a int, test_b int);
CREATE TABLE
...

# alter table atacc1 add constraint atacc1_constr_a_valid check(test_a
is not null);
ALTER TABLE

# alter table atacc1 alter test_a set not null;
ALTER TABLE


It is not obvious that full table scan was omitted. But if we set
client_min_messages to 'debug1', we'll be able to see what is really
happened by the different debug messages. For example:


# create table atacc1 (test_a int, test_b int);
CREATE TABLE
...

# set client_min_messages to 'debug1';
SET

# alter table atacc1 alter test_a set not null;
DEBUG:  verifying table "atacc1"   <<<< full table scan!
ALTER TABLE

# alter table atacc1 alter test_a drop not null;
ALTER TABLE

# alter table atacc1 add constraint atacc1_constr_a_valid check(test_a
is not null);
DEBUG:  verifying table "atacc1"
ALTER TABLE

# alter table atacc1 alter test_a set not null;
DEBUG:  verifying table "atacc1" NOT NULL constraint on test_a attribute
by existed constraints   <<<< full scan was skipped!
ALTER TABLE


-- 
Ildar Musin
i.musin@postgrespro.ru


Re: using index or check in ALTER TABLE SET NOT NULL

From
Sergei Kornilov
Date:
Hello, Ildar
Thanks. I looked ATTACH PARTITION tests and found such checks. If no one is against i will just use in my patch INFO
levelinstead DEBUG1, similarly ATTACH PARTITION code. Updated patch attached.
 

Or i can rewrite tests to use DEBUG1 level.

regards, Sergei
Attachment

Re: using index or check in ALTER TABLE SET NOT NULL

From
Alvaro Herrera
Date:
Sergei Kornilov wrote:
> Hello, Ildar
> Thanks. I looked ATTACH PARTITION tests and found such checks. If no one is against i will just use in my patch INFO
levelinstead DEBUG1, similarly ATTACH PARTITION code. Updated patch attached.
 
> 
> Or i can rewrite tests to use DEBUG1 level.

You should be able to use an event trigger that raises a message when
table_rewrite is hit, to notify the test driver that a rewrite happens.

(If any DDL that causes a table rewrite fails to trigger the
table_rewrite event correctly, that is a bug.)

ISTM that depending on DEBUG messages is bad because debugging lines
added elsewhere will make your tests fail; and INFO is generally frowned
upon (I, for one, would frown upon an INFO message raised by ALTER
TABLE, for sure.) so let's not do that either.

-- 
Álvaro Herrera                https://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services


Re: using index or check in ALTER TABLE SET NOT NULL

From
Sergei Kornilov
Date:
Hello

> You should be able to use an event trigger that raises a message when
> table_rewrite is hit, to notify the test driver that a rewrite happens.
Here is no table rewrite, only verify. So here EventTriggerTableRewrite is not called. Or i missed something?

> ISTM that depending on DEBUG messages is bad because debugging lines
> added elsewhere will make your tests fail;
I agree and this is reason why i not used DEBUG message in tests as was proposed. I found INFO messages in tests and
decidedthat this was an acceptable option year ago.
 

> and INFO is generally frowned upon (I, for one, would frown upon an INFO message raised by ALTER
> TABLE, for sure.) so let's not do that either.
In this case we need remove INFO from ALTER TABLE ATTACH PARTITION code and tests. I think is a bad idea of using
differentrules for same stuff, right? Probably i can do this work too.
 

But it is necessary to decide how the test should look.

regards, Sergei


Re: using index or check in ALTER TABLE SET NOT NULL

From
Tom Lane
Date:
Sergei Kornilov <sk@zsrv.org> writes:
>> ISTM that depending on DEBUG messages is bad because debugging lines
>> added elsewhere will make your tests fail;

> I agree and this is reason why i not used DEBUG message in tests as was proposed. I found INFO messages in tests and
decidedthat this was an acceptable option year ago. 

INFO is for user-facing messages, such as output from VACUUM VERBOSE,
where the user has specifically requested the output.  I do not think
this falls into that category.  Even if you persuade some committer
to commit it like that, there will be user pushback asking us to get
this noise out of their faces ... and then we'll have to find some
other way to test it.

Do you actually need test output proving that this code path was taken
rather than the default one?  Seems like looking at the code coverage
report might be enough.

> In this case we need remove INFO from ALTER TABLE ATTACH PARTITION code and tests. I think is a bad idea of using
differentrules for same stuff, right? Probably i can do this work too. 

I did not see any INFO messages in a quick test of ALTER TABLE ATTACH
PARTITION, but if there are any lurking in there, they probably need
to be downgraded.

            regards, tom lane


Re: using index or check in ALTER TABLE SET NOT NULL

From
Sergei Kornilov
Date:
Hello

> Do you actually need test output proving that this code path was taken
> rather than the default one? Seems like looking at the code coverage
> report might be enough.
I not known. In v4 i use DEBUG1 message and do not check code path in tests at all: by full table scan or by
constraint,i tested only command result to not break behavior.
 
Today Ildar Musin proposed to test code path through NotNullImpliedByRelConstraints function. This is my first patch
andI do not have the confidence to write a test. So I looked more closely at the alter table tests, found several info
inattach partition and updated my patch.
 

> I did not see any INFO messages in a quick test of ALTER TABLE ATTACH
> PARTITION, but if there are any lurking in there, they probably need
> to be downgraded.
In src/test/regress/expected/alter_table.out i found 7 test with
> INFO: partition constraint for table "..." is implied by existing constraints
and 5 with
> INFO:  updated partition constraint for default partition "..." is implied by existing constraints
ereport's are in ValidatePartitionConstraints function src/backend/commands/tablecmds.c

regards, Sergei


Re: using index or check in ALTER TABLE SET NOT NULL

From
Ildar Musin
Date:
Hello Sergei, Alvaro, Tom,

On 06.03.2018 20:25, Alvaro Herrera wrote:
> You should be able to use an event trigger that raises a message when
> table_rewrite is hit, to notify the test driver that a rewrite happens.
>
> (If any DDL that causes a table rewrite fails to trigger the
> table_rewrite event correctly, that is a bug.)
>

It seems that 'table_rewrite' event trigger isn't fired in case of 
simple scan (without actual rewrite).

> ISTM that depending on DEBUG messages is bad because debugging lines
> added elsewhere will make your tests fail;

I think that between test depending on DEBUG message and no test at all 
the former one is preferable. Are there other options to test it?

On 06.03.2018 21:51, Tom Lane wrote:
>
> Do you actually need test output proving that this code path was taken
> rather than the default one?  Seems like looking at the code coverage
> report might be enough.
>

Code coverage cannot guarantee correctness. I think there should be at 
least two tests:
* full scan is performed when there are no check constraints that 
restrict NULL values;
* full scan is omitted when there are such constraints.

The last one could also include some unobvious cases like CHECK (col > 
0), complex expressions with boolean operators etc.


PS: Btw, some check constraints that implies NOT NULL still won't 
prevent from full table scan. For instance:

# create table test (a int, b int check ((a + b) is not null));
CREATE TABLE

# set client_min_messages to 'debug1';
SET

# insert into test values (1, 1);
INSERT 0 1

# alter table test alter column a set not null;
DEBUG:  verifying table "test"   <<<< full table scan!
ALTER TABLE

Since operator+ (aka int4pl) is strict it returns NULL if at least one 
of its operands is NULL. And this check constraint ensures therefore 
that both columns 'a' and 'b' are NOT NULL. It isn't probably the issue 
of this patch, just something that someone may find interesting.

-- 
Ildar Musin
i.musin@postgrespro.ru


Re: using index or check in ALTER TABLE SET NOT NULL

From
Sergei Kornilov
Date:
Hello all!
Summarizing, how i must update tests?
We want test real skip of verify phase or only result correctness?

I can verify what i do not break alter table by tests in v4 of my patch. But here is no check code path. So my feature
maybe broken in future without test fail. alter table will be correct regardless this feature.
 
Or i must test code path too? I understood Tom and will remove INFO ereport from patch anyway. But currently i have no
ideahow check code path. As mentioned earlier using debug ereport is uncomfortable too. Here is no suitable event
triggerto track what exactly happens with table. Adding new one for test purposes seems overkill.
 

regards, Sergei


Re: using index or check in ALTER TABLE SET NOT NULL

From
Sergei Kornilov
Date:
Hello
My patch does not apply after commit 5748f3a0aa7cf78ac6979010273bd9d50869bb8e. Here is update to current master. Not
nullconstraint is immutable too, so here is no changes in PartConstraintImpliedByRelConstraint excepts rename and
commentsfix.
 

In this patch version i also revert tests to v4 state: i use DEBUG ereport instead INFO and code path not tested.
Pleasetell me if i must change tests some way.
 

regards, Sergei
Attachment

Re: using index or check in ALTER TABLE SET NOT NULL

From
Ildar Musin
Date:
Hello Sergei,

On 10.03.2018 12:35, Sergei Kornilov wrote:
> Hello My patch does not apply after commit
> 5748f3a0aa7cf78ac6979010273bd9d50869bb8e. Here is update to current
> master. Not null constraint is immutable too, so here is no changes
> in PartConstraintImpliedByRelConstraint excepts rename and comments
> fix.
>
> In this patch version i also revert tests to v4 state: i use DEBUG
> ereport instead INFO and code path not tested. Please tell me if i
> must change tests some way.
>
> regards, Sergei
>

Ok, I can't think of any other ways to test it so I have to agree with
Tom Lane i.e. rely only on coverage. (There also were another suggestion
to use statistics [select seq_scan from pg_stat_user_tables where
relid='test'::regclass] which show number of table scans. But statistics
is collected by stat collector process with some latency and hence
cannot be reliable for tests).

Patch seems correct to me, it applies and compiles cleanly, docs
compiles as well, tests pass. Changed status to Ready for Committer.

-- 
Ildar Musin
i.musin@postgrespro.ru


Re: using index or check in ALTER TABLE SET NOT NULL

From
Peter Eisentraut
Date:
On 11/29/17 10:52, Sergei Kornilov wrote:
> My target problem of adding NOT NULL to big relation without long downtime can be done with ADD CONSTRAINT NOT VALID,
VALIDATEit in second transaction, then SET NOT NULL by my patch and drop unneeded constraint.
 

It seems to me that this is a workaround for not properly cataloguing
NOT NULL constraints.  If we fixed that, you could do SET NOT NULL NOT
VALID and go from there.  Maybe we should look again into fixing that.
That would solve so many problems.

-- 
Peter Eisentraut              http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services


Re: using index or check in ALTER TABLE SET NOT NULL

From
Sergei Kornilov
Date:
Hello, Peter!
I agree my patch seems as strange workaround. And better will be SET NOT NULL NOT VALID feature. But this change is
verycomplicated for me
 
For now my patch is small, simple and provides way for users.

regards, Sergei

06.04.2018, 06:29, "Peter Eisentraut" <peter.eisentraut@2ndquadrant.com>:
> On 11/29/17 10:52, Sergei Kornilov wrote:
>>  My target problem of adding NOT NULL to big relation without long downtime can be done with ADD CONSTRAINT NOT
VALID,VALIDATE it in second transaction, then SET NOT NULL by my patch and drop unneeded constraint.
 
>
> It seems to me that this is a workaround for not properly cataloguing
> NOT NULL constraints. If we fixed that, you could do SET NOT NULL NOT
> VALID and go from there. Maybe we should look again into fixing that.
> That would solve so many problems.
>
> --
> Peter Eisentraut http://www.2ndQuadrant.com/
> PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services


Re: using index or check in ALTER TABLE SET NOT NULL

From
Sergei Kornilov
Date:
Hello
I notice my patch does not apply again. Here is update to current HEAD

regards, Sergei
Attachment

Re: using index or check in ALTER TABLE SET NOT NULL

From
Sergei Kornilov
Date:
Hi
I noticed new merge conflict, updated version attached.

regards, Sergei
Attachment

Re: using index or check in ALTER TABLE SET NOT NULL

From
Sergei Kornilov
Date:
Hello
Attached updated patch follows recent Reorganize partitioning code commit.
regards, Sergei
Attachment

Re: using index or check in ALTER TABLE SET NOT NULL

From
Dmitry Dolgov
Date:
>On Sun, 15 Apr 2018 at 09:09, Sergei Kornilov <sk@zsrv.org> wrote:
>
> Attached updated patch follows recent Reorganize partitioning code commit.
> regards, Sergei

This patch went through the last tree commit fests without any noticeable
activity, but cfbot says it still applies and doesn't break any tests. The
patch itself is rather small, the only significant objection I see from the
thread is that probably "SET NOT NULL NOT VALID" feature could be more
appropriate way of fixing the original problem, but looks like no one is
working on that (the only related thread I could found was this one [1]). If
not properly cataloguing NOT NULL constraints would be fixed, can it
potentially conflict with the current patch or not?


[1]: https://www.postgresql.org/message-id/flat/CAASwCXcOokBqHf8BXECbDgOLkXxJyL_Q_twhg2dGWSvgMzz%3DxA%40mail.gmail.com


Re: using index or check in ALTER TABLE SET NOT NULL

From
Sergei Kornilov
Date:
Hello

> This patch went through the last tree commit fests without any noticeable activity
Well, last two CF. During march commitfest patch has activity and was marked as ready for committer. But at end of july
CFwas no further activity and patch was reverted back to "need review" with reason [1]:
 
> It's not clear that there is consensus that this is wanted.
I can't say something here.

> If not properly cataloguing NOT NULL constraints would be fixed, can it
> potentially conflict with the current patch or not?
We already doing same stuff for "alter table attach partition" and in this patch i use exactly this routine. If proper
cataloguingwould conflict with my patch - it would conflict with "attach partition" validation too.
 
I think proper cataloguing can be implemented without conflict with proposed feature.

regards, Sergei

[1]: https://www.postgresql.org/message-id/c4c7556d-a046-ac29-2549-bdef0078b6fe%402ndQuadrant.com


Re: using index or check in ALTER TABLE SET NOT NULL

From
Dmitry Dolgov
Date:
> On Sun, 4 Nov 2018 at 19:03, Sergei Kornilov <sk@zsrv.org> wrote:
>
> > If not properly cataloguing NOT NULL constraints would be fixed, can it
> > potentially conflict with the current patch or not?
> We already doing same stuff for "alter table attach partition" and in this patch i use exactly this routine. If
propercataloguing would conflict with my patch - it would conflict with "attach partition" validation too.
 
> I think proper cataloguing can be implemented without conflict with proposed feature.

Yes, indeed, this patch relies on the PartConstraintImpliedByRelConstraint.
Then maybe it makes sense to go with the solution, proposed in this thread,
while leaving open the possibility of having "SET NOT NULL NOT VALID"? From
the functionality point of view it definitely would be beneficial. Any other
opinions?


Re: using index or check in ALTER TABLE SET NOT NULL

From
Alvaro Herrera
Date:
On 2018-Nov-13, Dmitry Dolgov wrote:

> > On Sun, 4 Nov 2018 at 19:03, Sergei Kornilov <sk@zsrv.org> wrote:
> >
> > > If not properly cataloguing NOT NULL constraints would be fixed, can it
> > > potentially conflict with the current patch or not?
> > We already doing same stuff for "alter table attach partition" and in this patch i use exactly this routine. If
propercataloguing would conflict with my patch - it would conflict with "attach partition" validation too.
 
> > I think proper cataloguing can be implemented without conflict with proposed feature.
> 
> Yes, indeed, this patch relies on the PartConstraintImpliedByRelConstraint.
> Then maybe it makes sense to go with the solution, proposed in this thread,
> while leaving open the possibility of having "SET NOT NULL NOT VALID"? From
> the functionality point of view it definitely would be beneficial. Any other
> opinions?

I think we should ignore any SET NOT NULL NOT VALID patches, because
in practice they don't exist.  Let's move forward with this, because the
optimization being proposed is clearly very useful.

-- 
Álvaro Herrera                https://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services


Re: using index or check in ALTER TABLE SET NOT NULL

From
Dmitry Dolgov
Date:
> On Tue, Nov 13, 2018 at 1:59 PM Alvaro Herrera <alvherre@2ndquadrant.com> wrote:
>
> On 2018-Nov-13, Dmitry Dolgov wrote:
>
> > > On Sun, 4 Nov 2018 at 19:03, Sergei Kornilov <sk@zsrv.org> wrote:
> > >
> > > > If not properly cataloguing NOT NULL constraints would be fixed, can it
> > > > potentially conflict with the current patch or not?
> > > We already doing same stuff for "alter table attach partition" and in this patch i use exactly this routine. If
propercataloguing would conflict with my patch - it would conflict with "attach partition" validation too.
 
> > > I think proper cataloguing can be implemented without conflict with proposed feature.
> >
> > Yes, indeed, this patch relies on the PartConstraintImpliedByRelConstraint.
> > Then maybe it makes sense to go with the solution, proposed in this thread,
> > while leaving open the possibility of having "SET NOT NULL NOT VALID"? From
> > the functionality point of view it definitely would be beneficial. Any other
> > opinions?
>
> I think we should ignore any SET NOT NULL NOT VALID patches, because
> in practice they don't exist.  Let's move forward with this, because the
> optimization being proposed is clearly very useful.

Absolutely agree. Looking at the history of the patch I see that it went
through some extensive review and even was marked as Ready for Committer before
the commentary from Peter, but since then some changes were made (rebase and
code reorganization). Can someone from the reviewers confirm (or not) if the
patch is in a good shape? If no, then I'll try to allocate some time for that,
but can't promise any exact date.


Re: using index or check in ALTER TABLE SET NOT NULL

From
Dmitry Dolgov
Date:
> On Thu, Nov 22, 2018 at 6:04 PM Dmitry Dolgov <9erthalion6@gmail.com> wrote:
>
> Absolutely agree. Looking at the history of the patch I see that it went
> through some extensive review and even was marked as Ready for Committer before
> the commentary from Peter, but since then some changes were made (rebase and
> code reorganization). Can someone from the reviewers confirm (or not) if the
> patch is in a good shape? If no, then I'll try to allocate some time for that,
> but can't promise any exact date.

Ok, I've reviewed this patch a bit. I don't see any significant problems with
the code itself, but to be honest I've got an impression that simplicity of
this patch is misleading and it covers too narrow use case. E.g. one can do
something equal to SET NOT NULL, like adding a new constraint

    CREATE TABLE test(data text, CHECK(data IS NOT NULL));
    ALTER TABLE test ADD CONTSTRAINT data_chk CHECK (data is not null);

or use not null domain

    CREATE DOMAIN not_null AS text CHECK(VALUE IS NOT NULL);
    CREATE TABLE test(data not_null);
    ALTER TABLE test ALTER COLUMN data SET NOT NULL;

and it still leads to a full table scan. For foreign tables the control flow
jump over NotNullImpliedByRelConstraints, so this logic is never checked. I'm
not sure if taking care of mentioned examples is enough (maybe there are more
of them), or the patch needs to suggest some more general solution here.

Of course there is a possibility that improvement even in this form for this
narrow use case is better than potentially more general approach in the future.
Any opinions about this?


Re: using index or check in ALTER TABLE SET NOT NULL

From
David Rowley
Date:
On Sun, 15 Apr 2018 at 19:09, Sergei Kornilov <sk@zsrv.org> wrote:
> Attached updated patch follows recent Reorganize partitioning code commit.

I've made a pass over v10. I think it's in pretty good shape, but I
did end up changing a few small things.

1. Tweaked the documents a bit. I was going to just change "Full table
scan" to "A full table scan", but I ended up rewriting the entire
paragraph.
2. In ATRewriteTables, updated comment to mention "If required" since
the scan may not be required if SET NOT NULLs are already proved okay.
3. Updated another forgotten comment in ATRewriteTables.
4. Removed mention about table's with OIDs in ATExecAddColumn(). This
seems left over from 578b229718.
5. Changed ATExecSetNotNull not to check for matching constraints if
we're already going to make a pass over the table. Setting
verify_new_notnull to true again does not make it any more true. :)
6. Tweaked NotNullImpliedByRelConstraints() a bit. You were calling
lappend on an empty list. make_list1() is fine. Don't need a variable
for that, just pass it to the function.
7. Tightened up the comments in ConstraintImpliedByRelConstraint() to
mention that it only supports immutable quals containing vars with
varno=1. Removed the comment near the bottom that mentioned that in
passing.

The only thing that I'm a bit unsure of is the tests. I've read the
thread and I see the discussion above about it.  I'd personally have
thought INFO was fine since ATTACH PARTITION does that, but I see
objections.  It appears that all the tests just assume that the CHECK
constraint was used to validate the SET NOT NULL. I'm not all that
sure if there's any good reason not to set client_min_messages =
'debug1' just before your test then RESET client_min_messages;
afterwards.  No other tests seem to do it, but my only thoughts on the
reason not to would be that it might fail if someone added another
debug somewhere, but so what? they should update the expected results
too.

Oh, one other thing I don't really like is that
ConstraintImpliedByRelConstraint() adds all of the other column's IS
NOT NULL constraints to the existConstraint. This is always wasted
effort for the SET NOT NULL use case.  I wonder if a new flag should
be added to control this, or even better, separate that part out and
put back the function named PartConstraintImpliedByRelConstraint and
have it do the IS NOT NULL building before calling
ConstraintImpliedByRelConstraint(). No duplicate code that way and you
also don't need to touch partbound.c

Setting this on waiting on author.

-- 
 David Rowley                   http://www.2ndQuadrant.com/
 PostgreSQL Development, 24x7 Support, Training & Services

Attachment

Re: using index or check in ALTER TABLE SET NOT NULL

From
Sergei Kornilov
Date:
Hello, David!

> I've made a pass over v10. I think it's in pretty good shape, but I
> did end up changing a few small things.

Thank you! I merged your changes to new patch version.

> The only thing that I'm a bit unsure of is the tests. I've read the
> thread and I see the discussion above about it. I'd personally have
> thought INFO was fine since ATTACH PARTITION does that, but I see
> objections.

It is unclear for me if we have consensus about INFO ereport in ATTACH PARTITION.

> It appears that all the tests just assume that the CHECK
> constraint was used to validate the SET NOT NULL. I'm not all that
> sure if there's any good reason not to set client_min_messages =
> 'debug1' just before your test then RESET client_min_messages;
> afterwards. No other tests seem to do it, but my only thoughts on the
> reason not to would be that it might fail if someone added another
> debug somewhere, but so what? they should update the expected results
> too.

Not sure we have consensus about debug messages in tests, so I did such test changes in additional patch.

> separate that part out and
> put back the function named PartConstraintImpliedByRelConstraint and
> have it do the IS NOT NULL building before calling
> ConstraintImpliedByRelConstraint(). No duplicate code that way and you
> also don't need to touch partbound.c

In this case we need extra argument for ConstraintImpliedByRelConstraint for some caller-provided existConstraint,
right?Along with Relation itself? Then I need make copy of existConstraint, append relation constraints and call
predicate_implied_by.If I understood correctly pseudocode would be:
 

PartConstraintImpliedByRelConstraint(rel, testConstraint)
  generate notNullConstraint from NOT NULL table attributes
  call ConstraintImpliedByRelConstraint(rel, testConstraint, notNullConstraint)

ConstraintImpliedByRelConstraint(rel, testConstraint, existsConstraint)
  copy existsConstraint to localExistsConstraint variable
  append relation constraints to localExistsConstraint list
  call predicate_implied_by
  
I thing redundant IS NOT NULL check is not issue here and we not need extra arguments for
ConstraintImpliedByRelConstraint.Was not changed in attached version, but I will change if you think this would be
betterdesign.
 

regards, Sergei
Attachment

Re: using index or check in ALTER TABLE SET NOT NULL

From
David Rowley
Date:
On Wed, 6 Mar 2019 at 08:41, Sergei Kornilov <sk@zsrv.org> wrote:
> In this case we need extra argument for ConstraintImpliedByRelConstraint for some caller-provided existConstraint,
right?Along with Relation itself? Then I need make copy of existConstraint, append relation constraints and call
predicate_implied_by.If I understood correctly pseudocode would be: 
>
> PartConstraintImpliedByRelConstraint(rel, testConstraint)
>   generate notNullConstraint from NOT NULL table attributes
>   call ConstraintImpliedByRelConstraint(rel, testConstraint, notNullConstraint)
>
> ConstraintImpliedByRelConstraint(rel, testConstraint, existsConstraint)
>   copy existsConstraint to localExistsConstraint variable
>   append relation constraints to localExistsConstraint list
>   call predicate_implied_by
>
> I thing redundant IS NOT NULL check is not issue here and we not need extra arguments for
ConstraintImpliedByRelConstraint.Was not changed in attached version, but I will change if you think this would be
betterdesign. 

I was really just throwing the idea out there for review. I don't
think that I'm insisting on it.

FWIW I think you could get away without the copy of the constraint
providing it was documented that the list is modified during the
ConstraintImpliedByRelConstraint call and callers must make a copy
themselves if they need an unmodified version. Certainly,
PartConstraintImpliedByRelConstraint won't need to make a copy, so
there's probably not much reason to assume that possible future
callers will.

Providing I'm imagining it correctly, I do think the patch is slightly
cleaner with that change.

It's:
a) slightly more efficient due to not needlessly checking a bunch of
IS NOT NULLs (imagine a 1000 column table with almost all NOT NULL and
a single CHECK constraint); and
b) patch has a smaller footprint (does not modify existing callers of
PartConstraintImpliedByRelConstraint()); and
c) does not modify an existing API function.

--
 David Rowley                   http://www.2ndQuadrant.com/
 PostgreSQL Development, 24x7 Support, Training & Services


Re: using index or check in ALTER TABLE SET NOT NULL

From
Sergei Kornilov
Date:
Hi

> Providing I'm imagining it correctly, I do think the patch is slightly
> cleaner with that change.

Ok, sounds reasonable. I changed patch this way.

regards, Sergei
Attachment

Re: using index or check in ALTER TABLE SET NOT NULL

From
David Rowley
Date:
On Mon, 11 Mar 2019 at 00:13, Sergei Kornilov <sk@zsrv.org> wrote:
>
> > Providing I'm imagining it correctly, I do think the patch is slightly
> > cleaner with that change.
>
> Ok, sounds reasonable. I changed patch this way.

Looks good to me.  Good idea to keep the controversial setting of
client_min_messages to debug1 in the tests in a separate patch.

Apart from a few lines that need to be wrapped at 80 chars and some
comment lines that seem to have been wrapped early, I'm happy for it
to be marked as ready for committer, but I'll defer to Ildar in case
he wants to have another look.

-- 
 David Rowley                   http://www.2ndQuadrant.com/
 PostgreSQL Development, 24x7 Support, Training & Services


Re: using index or check in ALTER TABLE SET NOT NULL

From
Robert Haas
Date:
On Sun, Mar 10, 2019 at 11:30 PM David Rowley
<david.rowley@2ndquadrant.com> wrote:
> Looks good to me.  Good idea to keep the controversial setting of
> client_min_messages to debug1 in the tests in a separate patch.
>
> Apart from a few lines that need to be wrapped at 80 chars and some
> comment lines that seem to have been wrapped early, I'm happy for it
> to be marked as ready for committer, but I'll defer to Ildar in case
> he wants to have another look.

Dispatches from the department of grammatical nitpicking...

+      entire table, however if a valid <literal>CHECK</literal> constraint is

I think this should be:

entire table; however, if...

+ * are set NOT NULL, however, if we can find a constraint which proves

similarly here

+ ereport(DEBUG1,
+ (errmsg("verifying table \"%s\" NOT NULL constraint "
+ "on %s attribute by existed constraints",
+ RelationGetRelationName(rel), NameStr(attr->attname))));

Ugh, that doesn't read well at all.  How about:

existing constraints on column "%s"."%s" are sufficient to prove that
it does not contain nulls

- * in implicit-AND form.
+ * in implicitly-AND form, must only contain immutable clauses
+ * and all Vars must be varno=1.

I think you should leave the existing sentence alone (implicit-AND is
correct, implicitly-AND is not) and add a new sentence that says the
stuff you want to add.

+ * "Existing constraints" include its check constraints and optional
+ * caller-provided existConstraint list. existConstraint list is modified
+ * during ConstraintImpliedByRelConstraint call and would represent all
+ * assumed conditions. testConstraint describes the constraint to validate.
+ * Both existConstraint and testConstraint must be in implicitly-AND form,
+ * must only contain immutable clauses and all Vars must be varno=1.

I think that it might be better to copy the list rather than to have
the comment note that it gets mutated, but regardless the grammar
needs improvement here.  Maybe: On entry, existConstraint is a
caller-provided list of conditions which this function may assume to
be true; on exit, it will have been destructively modified by the
addition of the table's CHECK constraints.  testConstraint is the
constraint to validate.  Both existConstraint and testConstraint must
be in implicit-AND form, must only contain immutable clauses, and must
contain only Vars with varno = 1.

- * not-false and try to prove the same for partConstraint.
- *
- * Note that predicate_implied_by assumes its first argument is known
- * immutable.  That should always be true for partition constraints, so we
- * don't test it here.
+ * not-false and try to prove the same for testConstraint.

I object to removing this.

-- 
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company


Re: using index or check in ALTER TABLE SET NOT NULL

From
Sergei Kornilov
Date:
Hello

> Dispatches from the department of grammatical nitpicking...

Thank you!

> + entire table, however if a valid <literal>CHECK</literal> constraint is
>
> I think this should be:
>
> entire table; however, if...
>
> + * are set NOT NULL, however, if we can find a constraint which proves
>
> similarly here

Changed

> + ereport(DEBUG1,
> + (errmsg("verifying table \"%s\" NOT NULL constraint "
> + "on %s attribute by existed constraints",
> + RelationGetRelationName(rel), NameStr(attr->attname))));
>
> Ugh, that doesn't read well at all. How about:
>
> existing constraints on column "%s"."%s" are sufficient to prove that
> it does not contain nulls

Changed

> - * in implicit-AND form.
> + * in implicitly-AND form, must only contain immutable clauses
> + * and all Vars must be varno=1.
>
> I think you should leave the existing sentence alone (implicit-AND is
> correct, implicitly-AND is not) and add a new sentence that says the
> stuff you want to add.

Ok

> + * "Existing constraints" include its check constraints and optional
> + * caller-provided existConstraint list. existConstraint list is modified
> + * during ConstraintImpliedByRelConstraint call and would represent all
> + * assumed conditions. testConstraint describes the constraint to validate.
> + * Both existConstraint and testConstraint must be in implicitly-AND form,
> + * must only contain immutable clauses and all Vars must be varno=1.
>
> I think that it might be better to copy the list rather than to have
> the comment note that it gets mutated, but regardless the grammar
> needs improvement here.

Agreed, in attached new version I copy the list and do not modify parameter.

> I object to removing this.

Okay, I revert this David's change

regards, Sergei
Attachment

Re: using index or check in ALTER TABLE SET NOT NULL

From
Robert Haas
Date:
On Tue, Mar 12, 2019 at 4:27 PM Sergei Kornilov <sk@zsrv.org> wrote:
> Agreed, in attached new version ...

Committed with a little more nitpicking.

-- 
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company


Re: using index or check in ALTER TABLE SET NOT NULL

From
Sergei Kornilov
Date:
Wow, thank you!

13.03.2019, 15:57, "Robert Haas" <robertmhaas@gmail.com>:
> On Tue, Mar 12, 2019 at 4:27 PM Sergei Kornilov <sk@zsrv.org> wrote:
>>  Agreed, in attached new version ...
>
> Committed with a little more nitpicking.
>
> --
> Robert Haas
> EnterpriseDB: http://www.enterprisedb.com
> The Enterprise PostgreSQL Company


Re: using index or check in ALTER TABLE SET NOT NULL

From
Tom Lane
Date:
Robert Haas <robertmhaas@gmail.com> writes:
> On Tue, Mar 12, 2019 at 4:27 PM Sergei Kornilov <sk@zsrv.org> wrote:
>> Agreed, in attached new version ...

> Committed with a little more nitpicking.

The buildfarm thinks additional nitpicking is needed.

            regards, tom lane


Re: using index or check in ALTER TABLE SET NOT NULL

From
Sergei Kornilov
Date:
Hi

> The buildfarm thinks additional nitpicking is needed.

hm. Patch was committed with debug1 level tests and many animals uses log_statement = 'all'. Therefore they have
additionalline in result: LOG:  statement: alter table pg_class alter column relname drop not null; and similar for
otherqueries.
 
I think we better would be to revert "set client_min_messages to 'debug1';"  part.

regards, Sergei


Re: using index or check in ALTER TABLE SET NOT NULL

From
Robert Haas
Date:
On Wed, Mar 13, 2019 at 11:17 AM Sergei Kornilov <sk@zsrv.org> wrote:
> > The buildfarm thinks additional nitpicking is needed.
>
> hm. Patch was committed with debug1 level tests and many animals uses log_statement = 'all'. Therefore they have
additionalline in result: LOG:  statement: alter table pg_class alter column relname drop not null; and similar for
otherqueries.
 
> I think we better would be to revert "set client_min_messages to 'debug1';"  part.

Ugh, I guess so.  Or how about changing the message itself to  use
INFO, like we already do in QueuePartitionConstraintValidation?

-- 
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company


Re: using index or check in ALTER TABLE SET NOT NULL

From
Sergei Kornilov
Date:
Hi

> Ugh, I guess so. Or how about changing the message itself to use
> INFO, like we already do in QueuePartitionConstraintValidation?

Fine for me. But year ago this was implemented in my patch and Tom voted against using INFO level for such purpose:
https://www.postgresql.org/message-id/1142.1520362313%40sss.pgh.pa.us

regards, Sergei


Re: using index or check in ALTER TABLE SET NOT NULL

From
Tom Lane
Date:
Sergei Kornilov <sk@zsrv.org> writes:
>> Ugh, I guess so. Or how about changing the message itself to use
>> INFO, like we already do in QueuePartitionConstraintValidation?

> Fine for me. But year ago this was implemented in my patch and Tom voted against using INFO level for such purpose:
https://www.postgresql.org/message-id/1142.1520362313%40sss.pgh.pa.us

What I thought then was that you didn't need the message at all,
at any debug level.  I still think that.  It might have been useful
for development purposes but it does not belong in committed code.
INFO (making it impossible for anybody to not have the message
in-their-face) is right out.

            regards, tom lane


Re: using index or check in ALTER TABLE SET NOT NULL

From
Tom Lane
Date:
I wrote:
> Sergei Kornilov <sk@zsrv.org> writes:
>>> Ugh, I guess so. Or how about changing the message itself to use
>>> INFO, like we already do in QueuePartitionConstraintValidation?

>> Fine for me. But year ago this was implemented in my patch and Tom voted against using INFO level for such purpose:
https://www.postgresql.org/message-id/1142.1520362313%40sss.pgh.pa.us

> What I thought then was that you didn't need the message at all,
> at any debug level.  I still think that.

Oh, and yes, I think QueuePartitionConstraintValidation's usage
is an unacceptable abuse of INFO level.  I'm surprised we haven't
gotten complaints about it yet.

            regards, tom lane


Re: using index or check in ALTER TABLE SET NOT NULL

From
Robert Haas
Date:
On Wed, Mar 13, 2019 at 1:09 PM Tom Lane <tgl@sss.pgh.pa.us> wrote:
> Sergei Kornilov <sk@zsrv.org> writes:
> >> Ugh, I guess so. Or how about changing the message itself to use
> >> INFO, like we already do in QueuePartitionConstraintValidation?
>
> > Fine for me. But year ago this was implemented in my patch and Tom voted against using INFO level for such purpose:
https://www.postgresql.org/message-id/1142.1520362313%40sss.pgh.pa.us
>
> What I thought then was that you didn't need the message at all,
> at any debug level.  I still think that.  It might have been useful
> for development purposes but it does not belong in committed code.
> INFO (making it impossible for anybody to not have the message
> in-their-face) is right out.

I find that position entirely wrong-headed.  If you think users have
no interest in a message telling them whether their gigantic table is
getting scanned or not, you're wrong.  Maybe you're right that
everyone doesn't want it, but I'm positive some do.  We've had
requests for very similar things on this very mailing list more than
one.

And if you think that it's not useful to have regression tests that
verify that the behavior is correct, well, that's not a question with
one objectively right answer, but I emphatically disagree with that
position.  This behavior is often quite subtle, especially in
combination with partitioned tables where different partitions may get
different treatment.  It would not be at all difficult to break it
without realizing.

I do understand that we seem to have no good way of doing this that
lets users have the option of seeing this message and also makes it
something that can be regression-tested.  INFO is out because there's
no option, and DEBUG1 is out because it doesn't work in the regression
tests.  However, I think giving up and saying "ok, well that's just
how it is, too bad" is, one, letting the tail wag the dog, and two, a
terribly disappointing attitude.

I've just reverted the 0002 portion of the patch, which should
hopefully fix this problem for now.  But I strongly encourage you
think of something to which you could say "yes" instead of just
shooting everything people want to do in this area down.

-- 
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company


Re: using index or check in ALTER TABLE SET NOT NULL

From
Robert Haas
Date:
On Wed, Mar 13, 2019 at 1:19 PM Tom Lane <tgl@sss.pgh.pa.us> wrote:
> Oh, and yes, I think QueuePartitionConstraintValidation's usage
> is an unacceptable abuse of INFO level.  I'm surprised we haven't
> gotten complaints about it yet.

Perhaps that's because users aren't as direly opposed to informational
messages from DDL commands as you seem to believe...

-- 
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company


Re: using index or check in ALTER TABLE SET NOT NULL

From
Justin Pryzby
Date:
Hi,

On Wed, Mar 13, 2019 at 01:25:11PM -0400, Robert Haas wrote:
> On Wed, Mar 13, 2019 at 1:19 PM Tom Lane <tgl@sss.pgh.pa.us> wrote:
> > Oh, and yes, I think QueuePartitionConstraintValidation's usage
> > is an unacceptable abuse of INFO level.  I'm surprised we haven't
> > gotten complaints about it yet.
> 
> Perhaps that's because users aren't as direly opposed to informational
> messages from DDL commands as you seem to believe...

On Wed, Mar 13, 2019 at 01:09:32PM -0400, Tom Lane wrote:
> Sergei Kornilov <sk@zsrv.org> writes:
> >> Ugh, I guess so. Or how about changing the message itself to use
> >> INFO, like we already do in QueuePartitionConstraintValidation?
> 
> > Fine for me. But year ago this was implemented in my patch and Tom voted against using INFO level for such purpose:
https://www.postgresql.org/message-id/1142.1520362313%40sss.pgh.pa.us
> 
> What I thought then was that you didn't need the message at all,
> at any debug level.  I still think that.  It might have been useful
> for development purposes but it does not belong in committed code.
> INFO (making it impossible for anybody to not have the message
> in-their-face) is right out.

I'm writing to provide a datapoint for the existing message regarding "implied
by existing constraints" in QueuePartitionConstraintValidation.

On the one hand, I agree that message at INFO is more verbose than other
commands, and I'm 20% surprised by it.

On the other hand, I *like* the output (including at INFO level).  It alerted
me to 1) deficiency with some of our tables (due to column not marked NOT
NULL); and, 2) helped me to understand how to improve some of our dynamic DDL.

If the message weren't visible at LOG, I'd miss it, at least sometimes, and
look for how to re-enable it (but statement logging of DEBUG is beyond
excessive).

For context, I'm someone who configures servers with log_min_messages=info and
who sometimes SETs client_min_messages='DEBUG1' ; I have $toomany warnings in
our monitoring system, because I'd rather see twice as much stuff that may or
may not be interesting than miss 10% of things I needed to see.

Justin


Re: using index or check in ALTER TABLE SET NOT NULL

From
David Rowley
Date:
On Thu, 14 Mar 2019 at 06:24, Robert Haas <robertmhaas@gmail.com> wrote:
>
> On Wed, Mar 13, 2019 at 1:09 PM Tom Lane <tgl@sss.pgh.pa.us> wrote:
> > Sergei Kornilov <sk@zsrv.org> writes:
> > >> Ugh, I guess so. Or how about changing the message itself to use
> > >> INFO, like we already do in QueuePartitionConstraintValidation?
> >
> > > Fine for me. But year ago this was implemented in my patch and Tom voted against using INFO level for such
purpose:https://www.postgresql.org/message-id/1142.1520362313%40sss.pgh.pa.us
 
> >
> > What I thought then was that you didn't need the message at all,
> > at any debug level.  I still think that.  It might have been useful
> > for development purposes but it does not belong in committed code.
> > INFO (making it impossible for anybody to not have the message
> > in-their-face) is right out.
>
> I find that position entirely wrong-headed.  If you think users have
> no interest in a message telling them whether their gigantic table is
> getting scanned or not, you're wrong.  Maybe you're right that
> everyone doesn't want it, but I'm positive some do.  We've had
> requests for very similar things on this very mailing list more than
> one.

If we don't have this for SET NOT NULL then we should either add it or
remove the one from ATTACH PARTITION.  I don't think we need to decide
which it is now, so I've added an item to the open items list that
this is out for debate.

https://wiki.postgresql.org/wiki/PostgreSQL_12_Open_Items#Open_Issues

I think we can mark this patch as committed now as I don't think the
lack of a way to test it is likely to cause it to be reverted.

-- 
 David Rowley                   http://www.2ndQuadrant.com/
 PostgreSQL Development, 24x7 Support, Training & Services


Re: using index or check in ALTER TABLE SET NOT NULL

From
Sergei Kornilov
Date:
Hello

> If we don't have this for SET NOT NULL then we should either add it or
> remove the one from ATTACH PARTITION.

I proposed to lower report level to debug1 in a separate thread:
https://www.postgresql.org/message-id/4859321552643736%40myt5-02b80404fd9e.qloud-c.yandex.net
Possible better would be link it.

regards, Sergei


Re: Re: using index or check in ALTER TABLE SET NOT NULL

From
David Steele
Date:
Hi Robert,

On 3/17/19 3:40 PM, David Rowley wrote:
> On Thu, 14 Mar 2019 at 06:24, Robert Haas <robertmhaas@gmail.com> wrote:
> 
> I think we can mark this patch as committed now as I don't think the
> lack of a way to test it is likely to cause it to be reverted.

Should we mark this as committed now or is there more tweaking to be done?

Regards,
-- 
-David
david@pgmasters.net


Re: Re: using index or check in ALTER TABLE SET NOT NULL

From
Robert Haas
Date:
On Mon, Mar 25, 2019 at 3:51 AM David Steele <david@pgmasters.net> wrote:
> On 3/17/19 3:40 PM, David Rowley wrote:
> > On Thu, 14 Mar 2019 at 06:24, Robert Haas <robertmhaas@gmail.com> wrote:
> >
> > I think we can mark this patch as committed now as I don't think the
> > lack of a way to test it is likely to cause it to be reverted.
>
> Should we mark this as committed now or is there more tweaking to be done?

I have now marked it as Committed.

-- 
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company


Re: using index or check in ALTER TABLE SET NOT NULL

From
Andres Freund
Date:
On 2019-03-25 11:09:47 -0400, Robert Haas wrote:
> On Mon, Mar 25, 2019 at 3:51 AM David Steele <david@pgmasters.net> wrote:
> > On 3/17/19 3:40 PM, David Rowley wrote:
> > > On Thu, 14 Mar 2019 at 06:24, Robert Haas <robertmhaas@gmail.com> wrote:
> > >
> > > I think we can mark this patch as committed now as I don't think the
> > > lack of a way to test it is likely to cause it to be reverted.
> >
> > Should we mark this as committed now or is there more tweaking to be done?
> 
> I have now marked it as Committed.

There's still an open item "Debate INFO messages in ATTACH PARTITION and
SET NOT NULL" for this thread.  Is there anything further to be done? Or
are we content with this for v12?

- Andres



Re: using index or check in ALTER TABLE SET NOT NULL

From
Tom Lane
Date:
Andres Freund <andres@anarazel.de> writes:
> There's still an open item "Debate INFO messages in ATTACH PARTITION and
> SET NOT NULL" for this thread.  Is there anything further to be done? Or
> are we content with this for v12?

IIRC, that's based on my complaint that these messages have no business
being INFO level.  I'm definitely not content with the current state.

I proposed that we didn't need those messages at all, which Robert pushed
back on, but I'd be willing to compromise by reducing them to NOTICE or
DEBUG level.

The actually intended use of INFO level is to mark messages that the user
actively asked for (via VERBOSE or some morally-equivalent option), which
is why that level has such high priority.  If we had something like a
VERBOSE option for ALTER TABLE, it'd make plenty of sense to follow
VACUUM's precedent:

    if (params->options & VACOPT_VERBOSE)
        elevel = INFO;
    else
        elevel = DEBUG2;

It seems a bit late to be inventing such a thing for v12 though.

In the meantime, I'm not very content with random subsets of
ALTER TABLE acting as if they have been granted permission
to be VERBOSE.  It's unfriendly, and it's inconsistent because
there are so many other expensive ALTER TABLE actions that don't
do this.

            regards, tom lane



Re: using index or check in ALTER TABLE SET NOT NULL

From
Sergei Kornilov
Date:
Hi

> I proposed that we didn't need those messages at all, which Robert pushed
> back on, but I'd be willing to compromise by reducing them to NOTICE or
> DEBUG level.

I posted patch with such change in a separate topic: https://commitfest.postgresql.org/23/2076/

PS: not think this is blocker for v12

regards, Sergei



Re: using index or check in ALTER TABLE SET NOT NULL

From
David Rowley
Date:
On Thu, 2 May 2019 at 06:18, Sergei Kornilov <sk@zsrv.org> wrote:
>
> > I proposed that we didn't need those messages at all, which Robert pushed
> > back on, but I'd be willing to compromise by reducing them to NOTICE or
> > DEBUG level.
>
> I posted patch with such change in a separate topic: https://commitfest.postgresql.org/23/2076/
>
> PS: not think this is blocker for v12

Probably not a blocker, but now does not seem like an unreasonable
time to lower these INFO messages down to DEBUG. If not, then we can
just remove the item from the open items list. I just put it there as
I didn't want it getting forgotten about as it wasn't going to be
anybody's priority to think hard about it on the final few days of the
last commitfest of the release.

-- 
 David Rowley                   http://www.2ndQuadrant.com/
 PostgreSQL Development, 24x7 Support, Training & Services



Re: using index or check in ALTER TABLE SET NOT NULL

From
Tom Lane
Date:
David Rowley <david.rowley@2ndquadrant.com> writes:
> On Thu, 2 May 2019 at 06:18, Sergei Kornilov <sk@zsrv.org> wrote:
>> PS: not think this is blocker for v12

> Probably not a blocker, but now does not seem like an unreasonable
> time to lower these INFO messages down to DEBUG.

Not a blocker perhaps, but it's better if we can get new behavior to
be more or less right the first time.

            regards, tom lane



Re: using index or check in ALTER TABLE SET NOT NULL

From
David Rowley
Date:
On Thu, 2 May 2019 at 13:08, Tom Lane <tgl@sss.pgh.pa.us> wrote:
>
> David Rowley <david.rowley@2ndquadrant.com> writes:
> > On Thu, 2 May 2019 at 06:18, Sergei Kornilov <sk@zsrv.org> wrote:
> >> PS: not think this is blocker for v12
>
> > Probably not a blocker, but now does not seem like an unreasonable
> > time to lower these INFO messages down to DEBUG.
>
> Not a blocker perhaps, but it's better if we can get new behavior to
> be more or less right the first time.

It's not really new behaviour though. The code in question is for
ATTACH PARTITION and was added in c31e9d4bafd (back in 2017).
bbb96c3704c is the commit for using constraints to speed up SET NOT
NULL. The mention of using the constraint for proof was made DEBUG1 in
the initial commit.  What we need to decide is if we want to make
ATTACH PARTITION's INFO message a DEBUG1 in pg12 or not.

-- 
 David Rowley                   http://www.2ndQuadrant.com/
 PostgreSQL Development, 24x7 Support, Training & Services



Re: using index or check in ALTER TABLE SET NOT NULL

From
David Rowley
Date:
On Thu, 2 May 2019 at 14:22, David Rowley <david.rowley@2ndquadrant.com> wrote:
>
> On Thu, 2 May 2019 at 13:08, Tom Lane <tgl@sss.pgh.pa.us> wrote:
> >
> > Not a blocker perhaps, but it's better if we can get new behavior to
> > be more or less right the first time.
>
> It's not really new behaviour though. The code in question is for
> ATTACH PARTITION and was added in c31e9d4bafd (back in 2017).
> bbb96c3704c is the commit for using constraints to speed up SET NOT
> NULL. The mention of using the constraint for proof was made DEBUG1 in
> the initial commit.  What we need to decide is if we want to make
> ATTACH PARTITION's INFO message a DEBUG1 in pg12 or not.

FWIW, I'm in favour of changing ATTACH PARTITION's INFO messages to
DEBUG1 for PG12 to align it to what bbb96c3704c did.

Anyone else?

-- 
 David Rowley                   http://www.2ndQuadrant.com/
 PostgreSQL Development, 24x7 Support, Training & Services



Re: using index or check in ALTER TABLE SET NOT NULL

From
David Rowley
Date:
On Fri, 3 May 2019 at 19:06, David Rowley <david.rowley@2ndquadrant.com> wrote:
> FWIW, I'm in favour of changing ATTACH PARTITION's INFO messages to
> DEBUG1 for PG12 to align it to what bbb96c3704c did.
>
> Anyone else?

Does anyone think we shouldn't change the INFO message in ATTACH
PARTITION to a DEBUG1 in PG12?

I think it makes sense make this change so that it matches the
behaviour of the output of ALTER TABLE .. ALTER COLUMN .. SET NOT NULL
when it uses a CHECK constraint.

-- 
 David Rowley                   http://www.2ndQuadrant.com/
 PostgreSQL Development, 24x7 Support, Training & Services



Re: using index or check in ALTER TABLE SET NOT NULL

From
Sergei Kornilov
Date:
Hello

> Does anyone think we shouldn't change the INFO message in ATTACH
> PARTITION to a DEBUG1 in PG12?

Seems no one wants to vote against this change.

My proposed patch was here: https://commitfest.postgresql.org/23/2076/

regards, Sergei



Re: using index or check in ALTER TABLE SET NOT NULL

From
David Rowley
Date:
On Tue, 11 Jun 2019 at 03:35, Sergei Kornilov <sk@zsrv.org> wrote:
> > Does anyone think we shouldn't change the INFO message in ATTACH
> > PARTITION to a DEBUG1 in PG12?
>
> Seems no one wants to vote against this change.

I'm concerned about two things:

1. The patch reduces the test coverage of ATTACH PARTITION. We now
have no way to ensure the constraint was used to validate the rows in
the partition.
2. We're inconsistent with what we do for SET NOT NULL and ATTACH
PARTITION. We raise an INFO message when we use a constraint for
ATTACH PARTITION and only a DEBUG1 for SET NOT NULL.

Unfortunately, my two concerns conflict with each other.

-- 
 David Rowley                   http://www.2ndQuadrant.com/
 PostgreSQL Development, 24x7 Support, Training & Services



Re: using index or check in ALTER TABLE SET NOT NULL

From
Tomas Vondra
Date:
On Wed, Jun 12, 2019 at 08:34:57AM +1200, David Rowley wrote:
>On Tue, 11 Jun 2019 at 03:35, Sergei Kornilov <sk@zsrv.org> wrote:
>> > Does anyone think we shouldn't change the INFO message in ATTACH
>> > PARTITION to a DEBUG1 in PG12?
>>
>> Seems no one wants to vote against this change.
>
>I'm concerned about two things:
>
>1. The patch reduces the test coverage of ATTACH PARTITION. We now
>have no way to ensure the constraint was used to validate the rows in
>the partition.
>2. We're inconsistent with what we do for SET NOT NULL and ATTACH
>PARTITION. We raise an INFO message when we use a constraint for
>ATTACH PARTITION and only a DEBUG1 for SET NOT NULL.
>
>Unfortunately, my two concerns conflict with each other.
>

We're getting close to beta3/rc1, and this thread was idle for ~1 month.

I think there's a consensus to change INFO to DEBUG1 in pg12, and then
maybe imlpement something like VERBOSE mode in the future. Objections?

As for the reduction of test coverage, can't we deduce whether a
constraint was used from data in pg_stats or something like that?

regards

-- 
Tomas Vondra                  http://www.2ndQuadrant.com
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services 



Re: using index or check in ALTER TABLE SET NOT NULL

From
Tom Lane
Date:
Tomas Vondra <tomas.vondra@2ndquadrant.com> writes:
> I think there's a consensus to change INFO to DEBUG1 in pg12, and then
> maybe imlpement something like VERBOSE mode in the future. Objections?

ISTM the consensus is "we'd rather reduce the verbosity, but we don't
want to give up test coverage".  So what's blocking this is lack of
a patch to show that there's another way to verify what code path
was taken.

> As for the reduction of test coverage, can't we deduce whether a
> constraint was used from data in pg_stats or something like that?

Not sure how exactly ... and we've already learned that pg_stats
isn't too reliable.

            regards, tom lane