Skip to content

Commit

Permalink
Merge branch 'master' of ssh://git.postgresql.org/slony1-engine
Browse files Browse the repository at this point in the history
Conflicts:
	RELEASE
	doc/adminguide/ddlchanges.sgml
  • Loading branch information
Christopher Browne committed Aug 30, 2013
2 parents acbb608 + 6d0a562 commit 24a8b60
Show file tree
Hide file tree
Showing 13 changed files with 421 additions and 55 deletions.
8 changes: 5 additions & 3 deletions RELEASE
@@ -1,14 +1,16 @@
#+OPTIONS: ^:{}
* Slony-I Release Notes
***
*** 2.2.0 rc 1

- Bug 305 :: set session_replication_role to local when applying DDL_SCRIPT on a replica

*** TBD

- Bug 304 :: Record sequence values each time SQL is recorded in
~sl_log_script~, and set those values before invoking the
SQL on the replica.
- Bug 309 :: create sl_failover_targets when upgrading 2.1.x to 2.2.0

- Bug 310 :: Fixing issue where the FAILOVER command can put slon in a restart loop


*** 2.2.0 b5

Expand Down
10 changes: 10 additions & 0 deletions clustertest/regression/testddl/init_schema.sql
Expand Up @@ -60,3 +60,13 @@ zone_id integer
ALTER TABLE ONLY billing_discount
ADD CONSTRAINT billing_discount_pkey PRIMARY KEY (billing_discount_id);

CREATE OR REPLACE FUNCTION insert_table1() returns trigger
as $$
declare

begin
insert into table1(data) values (NEW.data);
return NEW;
end;
$$
language plpgsql;
35 changes: 35 additions & 0 deletions clustertest/regression/testddl/testddl.js
Expand Up @@ -29,6 +29,9 @@ function init_tables() {
+"set add table (id=4, set id=1, origin=1, fully qualified name = 'public.table4');\n"
+"set add table (id=5, set id=1, origin=1, fully qualified name = 'public.table5');\n"
+"set add table (id=6, set id=1, origin=1, fully qualified name = 'public.billing_discount');\n"
+ "set add sequence(id=1,set id=1, origin=1, fully qualified name= 'public.table1_id_seq');\n"
+ "set add sequence(id=2,set id=1, origin=1, fully qualified name= 'public.table5_id_seq');\n"


return script;
}
Expand Down Expand Up @@ -121,6 +124,33 @@ function individual_ddl(coordinator, nodenum) {
run_slonik('update ddl',coordinator,preamble,slonikScript);
}

function trigger_function(coordinator) {
/**
* We stop the slons because we want to make sure that a SYNC does not
* happen in between the EXECUTE_SCRIPT and the next SYNC.
*/
terminate_slon(coordinator);
var sql = '';
for(var idx=0; idx < 1000; idx++) {
sql = sql + "insert into table5(data) values ('seqtest');\n"
}
var psql = coordinator.createPsqlCommand('db1',sql);
psql.run();
coordinator.join(psql);
premable = get_slonik_preamble();
slonikScript = "EXECUTE SCRIPT( SQL='alter table table1 drop column seqed;create trigger table5_trigger "
+ " before INSERT on public.table5 for each row execute procedure "
+ " insert_table1();'"
+ ' ,EVENT NODE=1 );';
run_slonik('add trigger ddl',coordinator,preamble,slonikScript);
slonikScript = "EXECUTE SCRIPT( SQL='insert into table5(data) values (9);'"
+ ' ,EVENT NODE=1);';
run_slonik('add trigger ddl',coordinator,preamble,slonikScript);

launch_slon(coordinator);

}


function inline_ddl(coordinator) {
premable = get_slonik_preamble();
Expand Down Expand Up @@ -166,6 +196,11 @@ function do_test(coordinator) {

inline_ddl(coordinator);
wait_for_sync(coordinator);


trigger_function(coordinator);
wait_for_sync(coordinator);

}

function get_compare_queries() {
Expand Down
6 changes: 3 additions & 3 deletions config.h.in
Expand Up @@ -12,9 +12,9 @@
#ifndef SLONY_I_CONFIG_H
#define SLONY_I_CONFIG_H

#define SLONY_I_VERSION_STRING "2.2.0.b5"
#define SLONY_I_VERSION_STRING_DEC 2,2,0,b5
#define SLONY_I_FUNC_VERSION_STRING 2_2_0_b5
#define SLONY_I_VERSION_STRING "2.2.0.rc1"
#define SLONY_I_VERSION_STRING_DEC 2,2,0,rc1
#define SLONY_I_FUNC_VERSION_STRING 2_2_0_rc1

#ifndef PG_VERSION_MAJOR
#define PG_VERSION_MAJOR 0
Expand Down
6 changes: 3 additions & 3 deletions config_msvc.h
Expand Up @@ -4,9 +4,9 @@

#include <server/pg_config.h>

#define SLONY_I_VERSION_STRING "2.2.0.b5"
#define SLONY_I_VERSION_STRING_DEC 2,2,0,b5
#define SLONY_I_FUNC_VERSION_STRING 2_2_0_b5
#define SLONY_I_VERSION_STRING "2.2.0.rc1"
#define SLONY_I_VERSION_STRING_DEC 2,2,0,rc1
#define SLONY_I_FUNC_VERSION_STRING 2_2_0_rc1

#if PG_VERSION_NUM >= 90300
#define HAVE_GETACTIVESNAPSHOT 1
Expand Down
2 changes: 1 addition & 1 deletion configure.ac
Expand Up @@ -11,7 +11,7 @@
# ----------
m4_define([SLONREL_VERSION], esyscmd([echo "$Name: $" | \
sed -e 's/\:\ REL_//' -e 's/\$//g' -e 's/_/./g' -e 's/\./\_/3' \
-e 's/\ //g' -e s/\:/`echo 2.2.0.b5`/ | tr -d '\n']))
-e 's/\ //g' -e s/\:/`echo 2.2.0.rc1`/ | tr -d '\n']))

m4_pattern_allow([^SLON_AC_])

Expand Down
67 changes: 67 additions & 0 deletions doc/adminguide/ddlchanges.sgml
Expand Up @@ -66,6 +66,73 @@ replica nodes. It is advisiable to not be concurrently inserting,deleting
or updating rows to a table while a script changing that table (adding or
deleting columns) is also running.</para></listitem>

<listitem><para>&slony1; 2.2.x and higher replicate the SQL requests
of an EXECUTE SCRIPT alongside other logged replication activity as
part of an ordinary SYNC. Scripts that perform an <command>ALTER
TABLE</command> to a replicated table are replicated in the correct
order with respect to other concurrent activities on that table, and
this is guaranteed because of the exclusive lock that the
<command>ALTER TABLE</command> acquired on the origin node. If your
EXECUTE SCRIPT does not obtain exclusive locks on all of the tables it
uses, then you need to make sure that any transactions running
concurrently with the script are not making changes that can adversely
affect the computations in the script.</para>

<warning><para> For example, if your script performs
<function>nextval('some_replicated_seq')</function>, and that sequence
is concurrently being incremented by another transaction, then it is
possible that when the queries are replayed on a replica, the sequence
may have different values on the replica than it had on the
origin.</para></warning>

<warning><para> In addition, it is crucial that DML requests
propagated by EXECUTE SCRIPT be deterministic in their behaviour,
otherwise the requests may (legitimately) be processed differently on
different nodes, thereby corrupting data. </para>

<para> For instance, the following queries are all not deterministic,
as they do not clearly indicate which of the tuples in the table will
be affected:

<itemizedlist>
<listitem><para> Insufficiently specified
<command>
insert into table2 (id, data)
select id, data from table1 limit 10;
</command></para>

<para>This query may legitimately take <emphasis>any</emphasis> 10
tuples from <envar>table1</envar>, no reason for it to behave the same
across nodes.</para></listitem>
<listitem><para> Ridiculously different behaviour
<command>
insert into table2 (id, data)
select id, data from table1 order by random () limit 10;
</command></para>

<para>This query makes it more obvious that it could draw
<emphasis>any</emphasis> 10 tuples from <envar>table1</envar>, in any
order. </para></listitem>

<listitem><para> Node-local results
<command>
insert into table3 (id, data, transaction_date, value)
select id, data, now(), random() from table1 order by id limit 10;
</command></para>

<para>This query will compute <function>now()</function> based on the
time the query runs on each node, and values of
<function>random()</function> varying each time, so that while the
<command>order by id</command> clause would have eliminated the
ambiguity in the earlier cases, we can be quite certain that this
query will put substantially different data into <envar>table3</envar>
on every node on which it is executed. </para></listitem>

</itemizedlist>
</warning>

</listitem>

</itemizedlist>

</sect2>
Expand Down
18 changes: 18 additions & 0 deletions share/slon.conf-sample
Expand Up @@ -111,3 +111,21 @@

# Should slon run the monitoring thread?
# monitor_threads=true

# TCP keep alive configurations
# Enable sending of TCP keep alive between slon and the PostgreSQL backends
# tcp_keepalive = true

# The number of seconds after which a TCP keep alive is sent across an idle
# connection. tcp_keepalive must be enabled for this to take effect. Default
# value of 0 means use operating system default
# tcp_keepalive_idle = 0

# The number of keep alive requests to the server that can be lost before
# the connection is declared dead. tcp_keepalive must be on.Default value
# of 0 means use operating system default
# tcp_keepalive_count = 0

# The number of seconds in between TCP keep alive requests. tcp_keepalive
# must be enabled. Default value of 0 means use operating system defaut
# tcp_keepalive_interval = 0
34 changes: 33 additions & 1 deletion src/backend/slony1_base.sql
Expand Up @@ -723,9 +723,41 @@ comment on column @NAMESPACE@.sl_components.co_eventtype is 'what kind of event
comment on column @NAMESPACE@.sl_components.co_event is 'which event have I started processing?';



--
-- we create a function + aggregate for string_agg to aggregate strings
-- some versions of PG (ie prior to 9.0) don't support this
CREATE OR replace function @NAMESPACE@.agg_text_sum(txt_before TEXT, txt_new TEXT) RETURNS TEXT AS
$BODY$
DECLARE
c_delim text;
BEGIN
c_delim = ',';
IF (txt_before IS NULL or txt_before='') THEN
RETURN txt_new;
END IF;
RETURN txt_before || c_delim || txt_new;
END;
$BODY$
LANGUAGE plpgsql;
comment on function @NAMESPACE@.agg_text_sum(text,text) is
'An accumulator function used by the slony string_agg function to
aggregate rows into a string';
--
-- create a string_agg function in the slony schema.
-- PG 8.3 does not have this function so we make our own
-- when slony stops supporting PG 8.3 we can switch to
-- the PG 9.0+ provided version of string_agg
--
CREATE AGGREGATE @NAMESPACE@.string_agg(text) (
SFUNC=@NAMESPACE@.agg_text_sum,
STYPE=text,
INITCOND=''
);


-- ----------------------------------------------------------------------
-- Last but not least grant USAGE to the replication schema objects.
-- ----------------------------------------------------------------------
grant usage on schema @NAMESPACE@ to public;


0 comments on commit 24a8b60

Please sign in to comment.