Thread: Nondestructive cluster, equivalent SQL?

Nondestructive cluster, equivalent SQL?

From
"Joshua b. Jore"
Date:
Since the cluster command causes so many hassles with PL/pgSQL functions,
triggers, constraints, indexes etc I'm asking if this spot of SQL emulates
the expected behaviour:

CREATE TABLE SoSIDs (
    SoSID CHARACTER(10),

    CONSTRAINT SoSIDsPKey PRIMARY KEY (SoSID)
);
CREATE RULE SoSIDsUpd AS ON UPDATE TO SoSIDs
    DO INSTEAD NOTHING;

Other PL/pgSQL functions and tables use this table for triggers, foreign
keys and triggers. Running 'CLUSTER SoSIDsPkey ON SoSIDs' is equivalent to

CREATE TABLE cluster_SoSIDs AS SELECT * FROM SoSIDs ORDER BY SoSID;
DROP TABLE SoSIDs;
ALTER TABLE cluster_SoSIDs RENAME TO SoSIDs;

So wouldn't it work just as well and avoid the problems by executing:

CREATE TABLE cluster_SoSIDs AS SELECT * FROM SoSIDs ORDER BY SoSID;
TRUNCATE SoSIDs;
INSERT INTO SoSIDs SELECT * FROM cluster_SoSIDs ORDER BY SoSID;

I'm just looking to hear a yay/nay on whether this is a good idea or not
and if I've got the idea down right. Also, since I'd like to put this
into a PL/pgSQL function how do I get the 'create table ... as ...' part
to work? PL/pgSQL appears to reserve the 'create table ... as select ...'
and 'select * into ... from ...' syntax. I'm not sure how else to
generate the SQL code to do this. Ideas?

Joshua b. Jore ; http://www.greentechnologist.org ; 10012 11010 11022
10202 1012 2122 11020 10202 10202 11002 1020 1012 11102 11102 11102 1201
11001 11002 10211 11020 10202 10202 11002 11021 1201 11010 11020 10211



Re: Nondestructive cluster, equivalent SQL?

From
Tom Lane
Date:
"Joshua b. Jore" <josh@greentechnologist.org> writes:
> So wouldn't it work just as well and avoid the problems by executing:

> CREATE TABLE cluster_SoSIDs AS SELECT * FROM SoSIDs ORDER BY SoSID;
> TRUNCATE SoSIDs;
> INSERT INTO SoSIDs SELECT * FROM cluster_SoSIDs ORDER BY SoSID;

<<itch>> ... if we allow that, we probably shouldn't.  Since TRUNCATE
can't be rolled back, it's not supposed to be allowed inside a
transaction block.

Think about what happens if you get an error or a system crash while
that INSERT is running.  The INSERT rolls back; the CREATE TABLE
rolls back; the TRUNCATE does not.  You just lost all your data.

If you can assume no one else is modifying the table then you could
defend against this by creating the holding-tank table in a separate
transaction before you do the TRUNCATE/INSERT.  Then you'd still have
your data in event of a crash, though you'd probably need a manual
recovery procedure to move it back where you want it.  But it's not
much of a general-purpose solution I'm afraid.

            regards, tom lane

Re: Nondestructive cluster, equivalent SQL?

From
"Joshua b. Jore"
Date:
Foo, ok so I'll just stick that code outside of PostgreSQL, do the
hold-tank thing and have the code call home to mom if things go really
badly (and hope to not fault during recovery).

The sql-truncate.html documentation page doesn't say that truncate isn't
transaction safe. I notice that when I actually try the code it does
complain about being inside a begin/end block. This occurs from simple SQL
at the psql client, inside a PL/pgSQL function, and inside an EXECUTE
statement. So while the bases appear to be covered in actual code, the
docs just didn't reflect that.

Thanks much,
Joshua b. Jore ; http://www.greentechnologist.org ; 10012 11010 11022
10202 1012 2122 11020 10202 10202 11002 1020 1012 11102 11102 11102 1201
11001 11002 10211 11020 10202 10202 11002 11021 1201 11010 11020 10211

On Fri, 24 May 2002, Tom Lane wrote:

> "Joshua b. Jore" <josh@greentechnologist.org> writes:
> > So wouldn't it work just as well and avoid the problems by executing:
>
> > CREATE TABLE cluster_SoSIDs AS SELECT * FROM SoSIDs ORDER BY SoSID;
> > TRUNCATE SoSIDs;
> > INSERT INTO SoSIDs SELECT * FROM cluster_SoSIDs ORDER BY SoSID;
>
> <<itch>> ... if we allow that, we probably shouldn't.  Since TRUNCATE
> can't be rolled back, it's not supposed to be allowed inside a
> transaction block.
>
> Think about what happens if you get an error or a system crash while
> that INSERT is running.  The INSERT rolls back; the CREATE TABLE
> rolls back; the TRUNCATE does not.  You just lost all your data.
>
> If you can assume no one else is modifying the table then you could
> defend against this by creating the holding-tank table in a separate
> transaction before you do the TRUNCATE/INSERT.  Then you'd still have
> your data in event of a crash, though you'd probably need a manual
> recovery procedure to move it back where you want it.  But it's not
> much of a general-purpose solution I'm afraid.
>
>             regards, tom lane
>


Re: Nondestructive cluster, equivalent SQL?

From
Tom Lane
Date:
"Joshua b. Jore" <josh@greentechnologist.org> writes:
> The sql-truncate.html documentation page doesn't say that truncate isn't
> transaction safe.

?  I see

: TRUNCATE cannot be executed inside a transaction block (BEGIN/COMMIT
: pair), because there is no way to roll it back.

This could perhaps be more verbose, but the point is covered...

            regards, tom lane