<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<!DOCTYPE bugzilla SYSTEM "http://www.slony.info/bugzilla/bugzilla.dtd">

<bugzilla version="3.4.4"
          urlbase="http://www.slony.info/bugzilla/"
          
          maintainer="devrim@gunduz.org"
>

    <bug>
          <bug_id>134</bug_id>
          
          <creation_ts>2010-06-07 01:43:00 -0700</creation_ts>
          <short_desc>TRUNCATE support</short_desc>
          <delta_ts>2010-11-16 14:50:21 -0800</delta_ts>
          <reporter_accessible>1</reporter_accessible>
          <cclist_accessible>1</cclist_accessible>
          <classification_id>1</classification_id>
          <classification>Unclassified</classification>
          <product>Slony-I</product>
          <component>stored procedures</component>
          <version>devel</version>
          <rep_platform>PC</rep_platform>
          <op_sys>Linux</op_sys>
          <bug_status>RESOLVED</bug_status>
          <resolution>FIXED</resolution>
          
          
          <bug_file_loc>http://github.com/cbbrowne/slony1-engine/commits/local-master/bug-134</bug_file_loc>
          
          
          <priority>low</priority>
          <bug_severity>enhancement</bug_severity>
          <target_milestone>---</target_milestone>
          
          <blocked>137</blocked>
          
          <everconfirmed>1</everconfirmed>
          <reporter name="Peter Eisentraut">peter_e</reporter>
          <assigned_to name="Christopher Browne">cbbrowne</assigned_to>
          <cc>slony1-bugs</cc>

      

      

      

          <long_desc isprivate="0">
            <who name="Peter Eisentraut">peter_e</who>
            <bug_when>2010-06-07 01:43:39 -0700</bug_when>
            <thetext>Wishlist: Add support for TRUNCATE.  Either add a trigger that prevents TRUNCATE on the master, or propagate the TRUNCATE event to the slaves.

Right now, TRUNCATE is a loose foot-gun on a Slony setup.  See http://shoaibmir.wordpress.com/2010/06/03/truncate-problems-with-slony/ for example.</thetext>
          </long_desc>
          <long_desc isprivate="0">
            <who name="Christopher Browne">cbbrowne</who>
            <bug_when>2010-06-07 08:35:43 -0700</bug_when>
            <thetext>Yep, I had a chat with various people about this at PGCon, and had some resolutions of outstanding questions.

The trouble with TRUNCATE comes when there are foreign key relationships.  In the case of circularity, one might find it necessary to submit:

  TRUNCATE a, b, c;

in order to get all three tables emptied.

Supposing that request is submitted, we&apos;d find, logged, 3 TRUNCATE requests that were captured by ON TRUNCATE triggers.  (I&apos;m assuming here that all 3 tables were replicated.)

I see 4 strategies for implementing the handling of TRUNCATE:

1.  Deny

Basically, we put the same stored function used for &quot;deny_access&quot; onto the ON TRUNCATE action.

This isn&apos;t ideal, but is better than what we have now.

2.  Log truncate, action on subscriber is &quot;TRUNCATE ONLY&quot;

This won&apos;t work out in the &quot;TRUNCATE a,b,c;&quot; scenario described earlier, as the FK is liable to cause each of these truncate requests to fail.

3.  Log truncate...  Try to form sets of successive TRUNCATEs into one request.

This adds substantially to complexity, and there&apos;s the question of when to do the set of truncates:

  a) At the earliest point in the stream, or
  b) At the latest point in the stream.

More thought necessary to see which order is expected to be &quot;compatible.&quot;

[Thinking a bit more...  This might well work...  The transaction claims an exclusive lock on all the tables, so it ought to be possible to, upon seeing a TRUNCATE, look for all the adjacent TRUNCATE requests in that same transaction.  The only trouble is how to not bother reprocessing the subsequent TRUNCATE requests.]

There is still some risk of failure on the subscriber; supposing there are differences in FK relations there, there is the possibility of everything rolling back, and replication becoming blocked at this point.

4.  Log the truncates, and, for each one, submit
   TRUNCATE foo CASCADE;

This has merits over all the others:

- It performs TRUNCATE (unlike 1!)
- Guaranteed to work (unlike 2)
- Much simpler than #3
- No risk of getting stuck because of a FK relationship

There&apos;s a big scary demerit:

- It&apos;ll blindly truncate everything tied to the table being truncated.

I had a chat about this with Rod Taylor and Greg Sabino Mullane at the EDB dinner; Rod suggested that #4 was the way to go, and I made sure Greg was aware of the challenge here.

Peter, your thoughts would definitely be valued.</thetext>
          </long_desc>
          <long_desc isprivate="0">
            <who name="Peter Eisentraut">peter_e</who>
            <bug_when>2010-06-07 11:41:14 -0700</bug_when>
            <thetext>My immediate interest in this comes more from the point of closing possible breakage vectors, so prohibiting TRUNCATE on the master would be good for me.

I don&apos;t have a qualified opinion at the moment on how to implement replicating the TRUNCATE event.</thetext>
          </long_desc>
          <long_desc isprivate="0">
            <who name="Christopher Browne">cbbrowne</who>
            <bug_when>2010-06-07 11:48:05 -0700</bug_when>
            <thetext>(In reply to comment #2)
&gt; My immediate interest in this comes more from the point of closing possible
&gt; breakage vectors, so prohibiting TRUNCATE on the master would be good for me.

Actually, we&apos;d want to prohibit TRUNCATE on all nodes, in that case.

It&apos;s not so much of an improvement if you can still easily blow up subscribers! 
:-(</thetext>
          </long_desc>
          <long_desc isprivate="0">
            <who name="Christopher Browne">cbbrowne</who>
            <bug_when>2010-08-09 14:09:17 -0700</bug_when>
            <thetext>Thinking about implementation...

We could:

a) Try to capture the trigger using the existing C/SPI function.  That seems like overkill, as we don&apos;t need to collect data.

b) Create a trigger function that captures the table ID as its argument, and uses that to determine which table to truncate.

Consistent with the preceding discussion, I propose using &quot;policy #4&quot; to handle this, that is, on replicated nodes, we&apos;ll run, for each table:
   truncate ONLY my_table CASCADE;</thetext>
          </long_desc>
          <long_desc isprivate="0">
            <who name="Christopher Browne">cbbrowne</who>
            <bug_when>2010-08-10 09:33:39 -0700</bug_when>
            <thetext>I have a branch out on GitHub that has a preliminary implementation.</thetext>
          </long_desc>
          <long_desc isprivate="0">
            <who name="Christopher Browne">cbbrowne</who>
            <bug_when>2010-08-11 12:38:26 -0700</bug_when>
            <thetext>Add in some more tests, notably involving foreign key relationships.</thetext>
          </long_desc>
          <long_desc isprivate="0">
            <who name="Christopher Browne">cbbrowne</who>
            <bug_when>2010-08-12 14:55:53 -0700</bug_when>
            <thetext>I&apos;ve got a basically working implementation, here.

http://github.com/cbbrowne/slony1-engine/commits/local-master/bug-134</thetext>
          </long_desc>
          <long_desc isprivate="0">
            <who name="Steve Singer">ssinger</who>
            <bug_when>2010-11-15 13:45:47 -0800</bug_when>
            <thetext>I reviewed a3a2e4839f5cf21bfd076e30e916cd23112daf97 rebased to our current master (3cbbaba072b38527fa2ac7949ba680e7bd410a9a) with conflicts resolved.

A few comments

1.  Upgrade script support.  As it stands today an upgrade from 2.0
to 2.1 doesn&apos;t require re-installing the cluster.  This patch doesn&apos;t
warrent (in my opinion) requiring that.  Something else in the future
might but I would like to see an upgrade script add the truncate triggers
to all replicated tables.

2. I manually tested the functionality and it looked okay.  However run I tried the regression test you added I got the same &apos;result&apos; against 8.3 and 9.1master.
Since 8.3 doesn&apos;t support truncate triggers this confused me, it might just be my unfamiliarity with the regression tests.  I was expecting a it to say it failed with 8.3 (is that what we want?)

3. This probably should also have a documentation update, limitations.sgml at a minimum to say we now support truncate in 8.4 and above.  We also might want to say somewhere that the truncate on the slave is a CASCADE.   This would be important to note for setups who have a different schema on their slave vs master. 

Other than that I&apos;m happy with this for master.</thetext>
          </long_desc>
          <long_desc isprivate="0">
            <who name="Christopher Browne">cbbrowne</who>
            <bug_when>2010-11-15 14:44:30 -0800</bug_when>
            <thetext>(In reply to comment #8)
&gt; I reviewed a3a2e4839f5cf21bfd076e30e916cd23112daf97 rebased to our current
&gt; master (3cbbaba072b38527fa2ac7949ba680e7bd410a9a) with conflicts resolved.
&gt; 
&gt; A few comments
&gt; 
&gt; 1.  Upgrade script support.  As it stands today an upgrade from 2.0
&gt; to 2.1 doesn&apos;t require re-installing the cluster.  This patch doesn&apos;t
&gt; warrent (in my opinion) requiring that.  Something else in the future
&gt; might but I would like to see an upgrade script add the truncate triggers
&gt; to all replicated tables.

Good idea; I will rework it so that it tries to add the triggers, if possible.

&gt; 2. I manually tested the functionality and it looked okay.  However run I tried
&gt; the regression test you added I got the same &apos;result&apos; against 8.3 and
&gt; 9.1master.
&gt; Since 8.3 doesn&apos;t support truncate triggers this confused me, it might just be
&gt; my unfamiliarity with the regression tests.  I was expecting a it to say it
&gt; failed with 8.3 (is that what we want?)

Hmm.  I&apos;d expect the test to fail on 8.3, because tables would be empty there, but not on the subscribers.

I don&apos;t think I tried running it on 8.3, because I expected it not to work properly there.

&gt; 3. This probably should also have a documentation update, limitations.sgml at a
&gt; minimum to say we now support truncate in 8.4 and above.  We also might want to
&gt; say somewhere that the truncate on the slave is a CASCADE.   This would be
&gt; important to note for setups who have a different schema on their slave vs
&gt; master. 

Yep, something needs to be put in there.  I think I&apos;ll either need to:
a) Merge docs from HEAD into this branch, or
b) Document as part of the merge into HEAD, as
c) Try and muddle docs in as-is won&apos;t work out very happily due to the lots of upstream changes to the docs.

Probably b) is simplest.

&gt; Other than that I&apos;m happy with this for master.</thetext>
          </long_desc>
          <long_desc isprivate="0">
            <who name="Christopher Browne">cbbrowne</who>
            <bug_when>2010-11-16 09:35:23 -0800</bug_when>
            <thetext>(In reply to comment #9)
&gt; (In reply to comment #8)
&gt; &gt; I reviewed a3a2e4839f5cf21bfd076e30e916cd23112daf97 rebased to our current
&gt; &gt; master (3cbbaba072b38527fa2ac7949ba680e7bd410a9a) with conflicts resolved.
&gt; &gt; 
&gt; &gt; A few comments
&gt; &gt; 
&gt; &gt; 1.  Upgrade script support.  As it stands today an upgrade from 2.0
&gt; &gt; to 2.1 doesn&apos;t require re-installing the cluster.  This patch doesn&apos;t
&gt; &gt; warrent (in my opinion) requiring that.  Something else in the future
&gt; &gt; might but I would like to see an upgrade script add the truncate triggers
&gt; &gt; to all replicated tables.
&gt; 
&gt; Good idea; I will rework it so that it tries to add the triggers, if possible.

Done.

https://github.com/cbbrowne/slony1-engine/commit/f1fb66ceec3d32039f83f293a362668d9d820746</thetext>
          </long_desc>
          <long_desc isprivate="0">
            <who name="Christopher Browne">cbbrowne</who>
            <bug_when>2010-11-16 13:16:00 -0800</bug_when>
            <thetext>Created an attachment (id=74)
Differences from test run

getting data from origin DB for diffing
done
getting data from node 2 for diffing against origin
comparing
./run_test.sh: WARNING: /tmp/slony-regress.abhpMa/db_1.dmp /tmp/slony-regress.abhpMa/db_2.dmp differ, see /tmp/slony-regress.abhpMa/db_diff.2 for details
done


Looking good...</thetext>
          </long_desc>
          <long_desc isprivate="0">
            <who name="Christopher Browne">cbbrowne</who>
            <bug_when>2010-11-16 14:50:21 -0800</bug_when>
            <thetext>Committed code changes to master:

http://git.postgresql.org/gitweb?p=slony1-engine.git;a=commit;h=587f926d5b2ab1ed332d8e966eede6c7e4574da0

Also, documentation changes:

http://git.postgresql.org/gitweb?p=slony1-engine.git;a=commit;h=4e0eede18828b2a0dcecd159cbaa3456eb40118e</thetext>
          </long_desc>
      
          <attachment
              isobsolete="0"
              ispatch="0"
              isprivate="0"
          >
            <attachid>74</attachid>
            <date>2010-11-16 13:16 -0800</date>
            <desc>Differences from test run</desc>
            <filename>db_diff.2</filename>
            <type>text/plain</type>
            <size>945</size>
            <attacher>cbbrowne</attacher>
            
              <data encoding="base64">NzUsNzZjNzUsMTI5CjwgIGlkIHwgIGNuYW1lICAKPCAtLS0tKy0tLS0tLS0tLQotLS0KPiAgaWQg
fCAgIGNuYW1lICAgIAo+IC0tLS0rLS0tLS0tLS0tLS0tCj4gICAxIHwgbmVpbAo+ICAgMiB8IHJp
Y2hhcmQKPiAgIDMgfCBiaWxsCj4gICA0IHwgcGhpbAo+ICAgNSB8IHN0ZXZlCj4gICA2IHwgZmFy
b3VsdAo+ICAgNyB8IHJvYnNvbgo+ICAgOCB8IHRyZWUKPiAgIDkgfCBtYW5pcwo+ICAxMCB8IHNj
aGFmZmVyCj4gIDExIHwgam9yZ2Vuc2VuCj4gIDEyIHwgZ29vc2Vucwo+ICAxMyB8IG1pdHRlbGJh
Y2gKPiAgMTQgfCBjMjU1OTEKPiAgMTUgfCBjMjU1OTIKPiAgMTYgfCBjMjU1OTMKPiAgMTcgfCBj
MjU1OTQKPiAgMTggfCBjMjU1OTUKPiAgMTkgfCBjMjU1OTYKPiAgMjAgfCBjMjU1OTcKPiAgMjEg
fCBjMjU1OTgKPiAgMjIgfCBjMjU1OTkKPiAgMjMgfCBjMjU1OTEwCj4gIDI0IHwgYzI1NTkxMQo+
ICAyNSB8IGMyNTU5MTIKPiAgMjYgfCBjMjU1OTEzCj4gIDI3IHwgYzI1NTkxNAo+ICAyOCB8IGMy
NTU5MTUKPiAgMjkgfCBjMjU1OTE2Cj4gIDMwIHwgYzI1NTkxNwo+ICAzMSB8IGMyNTU5MTgKPiAg
MzIgfCBjMjU1OTE5Cj4gIDMzIHwgYzI1NTkyMAo+ICAzNCB8IGM3NDYyMQo+ICAzNSB8IGM3NDYy
Mgo+ICAzNiB8IGM3NDYyMwo+ICAzNyB8IGM3NDYyNAo+ICAzOCB8IGM3NDYyNQo+ICAzOSB8IGM3
NDYyNgo+ICA0MCB8IGM3NDYyNwo+ICA0MSB8IGM3NDYyOAo+ICA0MiB8IGM3NDYyOQo+ICA0MyB8
IGM3NDYyMTAKPiAgNDQgfCBjNzQ2MjExCj4gIDQ1IHwgYzc0NjIxMgo+ICA0NiB8IGM3NDYyMTMK
PiAgNDcgfCBjNzQ2MjE0Cj4gIDQ4IHwgYzc0NjIxNQo+ICA0OSB8IGM3NDYyMTYKPiAgNTAgfCBj
NzQ2MjE3Cj4gIDUxIHwgYzc0NjIxOAo+ICA1MiB8IGM3NDYyMTkKPiAgNTMgfCBjNzQ2MjIwCjk3
YzE1MAo8ICgyMCByb3dzKQotLS0KPiAoNzMgcm93cykK
</data>

          </attachment>
      

    </bug>

</bugzilla>