OSDN Git Service

Add merge TODO.detail item.
authorBruce Momjian <bruce@momjian.us>
Thu, 1 Dec 2005 22:12:06 +0000 (22:12 +0000)
committerBruce Momjian <bruce@momjian.us>
Thu, 1 Dec 2005 22:12:06 +0000 (22:12 +0000)
doc/TODO.detail/merge [new file with mode: 0644]

diff --git a/doc/TODO.detail/merge b/doc/TODO.detail/merge
new file mode 100644 (file)
index 0000000..276e252
--- /dev/null
@@ -0,0 +1,3390 @@
+From kleptog@svana.org Thu Nov 17 07:33:25 2005
+Return-path: <kleptog@svana.org>
+Received: from svana.org (mail@svana.org [203.20.62.76])
+       by candle.pha.pa.us (8.11.6/8.11.6) with ESMTP id jAHCXNu09324
+       for <pgman@candle.pha.pa.us>; Thu, 17 Nov 2005 07:33:25 -0500 (EST)
+Received: from kleptog by svana.org with local (Exim 3.35 #1 (Debian))
+       id 1Eciwk-0007Gd-00; Thu, 17 Nov 2005 23:32:58 +1100
+Date: Thu, 17 Nov 2005 13:32:57 +0100
+From: Martijn van Oosterhout <kleptog@svana.org>
+To: Csaba Nagy <nagy@ecircle-ag.com>
+cc: Zeugswetter Andreas DCP SD <ZeugswetterA@spardat.at>,
+   Dann Corbit <DCorbit@connx.com>, Simon Riggs <simon@2ndquadrant.com>,
+   Bruce Momjian <pgman@candle.pha.pa.us>,
+   Rick Gigger <rick@alpinenetworking.com>, Tom Lane <tgl@sss.pgh.pa.us>,
+   Christopher Kings-Lynne <chriskl@familyhealth.com.au>,
+   "Jim C. Nasby" <jnasby@pervasive.com>, josh@agliodbs.com,
+   pgsql-hackers@postgresql.org, Jaime Casanova <systemguards@gmail.com>,
+   Peter Eisentraut <peter_e@gmx.net>
+Subject: Re: [HACKERS] MERGE vs REPLACE
+Message-ID: <20051117123250.GC22933@svana.org>
+Reply-To: Martijn van Oosterhout <kleptog@svana.org>
+References: <E1539E0ED7043848906A8FF995BDA5799A524D@m0143.s-mxs.net> <1132228373.10890.313.camel@coppola.muc.ecircle.de>
+MIME-Version: 1.0
+Content-Type: multipart/signed; micalg=pgp-sha1;
+       protocol="application/pgp-signature"; boundary="raC6veAxrt5nqIoY"
+Content-Disposition: inline
+In-Reply-To: <1132228373.10890.313.camel@coppola.muc.ecircle.de>
+User-Agent: Mutt/1.3.28i
+X-PGP-Key-ID: Length=1024; ID=0x0DC67BE6
+X-PGP-Key-Fingerprint: 295F A899 A81A 156D B522  48A7 6394 F08A 0DC6 7BE6
+X-PGP-Key-URL: <http://svana.org/kleptog/0DC67BE6.pgp.asc>
+Status: OR
+
+
+--raC6veAxrt5nqIoY
+Content-Type: text/plain; charset=us-ascii
+Content-Disposition: inline
+Content-Transfer-Encoding: quoted-printable
+
+On Thu, Nov 17, 2005 at 12:52:53PM +0100, Csaba Nagy wrote:
+> Yes, these algorithms are clear to me, but they don't work for batch
+> updates in postgres without savepoints before each row insert/update,
+> which is not good for performance (not to mention on older postgres
+> versions without savepoint support it won't work at all). If there is a
+> way of no race condition, no performance penalty, that would be
+> something new and useful. I just guess the MERGE would provide that.
+
+Well, then you guess wrong. This isn't what MERGE is for. MERGE is just
+a neat way of specifying the UPDATE and INSERT cases in the same
+statement. It doesn't remove the possibility duplicate inserts and thus
+primary key violations.
+
+If someone wants to make extensions to MERGE so that it can avoid the
+race condition and avoid the duplicate key violations, that's fine. But
+be aware that this is outside of the spec. It may be a useful addition,
+but perhaps we should consider MERGE and REPLACE as completely seperate
+targets.
+
+MERGE has a whole join construction with subqueries that would be a
+pain to make work in a way that is truly serialisable. REPLACE deals
+with only one row and tries to solve the race for that case only. Much
+easier to consider them seperately, no?
+
+I guess what's really irritating is that this clearly exposes the case
+listed in the docs as "Why SERIALIZABLE isn't in all cases". If we
+could solve that for MERGE, we could probably solve it in the general
+case too.
+
+Have a nice day,
+--=20
+Martijn van Oosterhout   <kleptog@svana.org>   http://svana.org/kleptog/
+> Patent. n. Genius is 5% inspiration and 95% perspiration. A patent is a
+> tool for doing 5% of the work and then sitting around waiting for someone
+> else to do the other 95% so you can sue them.
+
+--raC6veAxrt5nqIoY
+Content-Type: application/pgp-signature
+Content-Disposition: inline
+
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v1.0.6 (GNU/Linux)
+Comment: For info see http://www.gnupg.org
+
+iD8DBQFDfHhxIB7bNG8LQkwRAhIwAJwPmzE2GHrqzPujkkj2I5r6OlVo5QCeN4st
+Ka50Vh0AnXuj4pBt27V6j7I=
+=7rb7
+-----END PGP SIGNATURE-----
+
+--raC6veAxrt5nqIoY--
+
+From pgsql-hackers-owner+M76186@postgresql.org Thu Nov 17 09:44:46 2005
+Return-path: <pgsql-hackers-owner+M76186@postgresql.org>
+Received: from ams.hub.org (ams.hub.org [200.46.204.13])
+       by candle.pha.pa.us (8.11.6/8.11.6) with ESMTP id jAHEihu07081
+       for <pgman@candle.pha.pa.us>; Thu, 17 Nov 2005 09:44:44 -0500 (EST)
+Received: from postgresql.org (svr1.postgresql.org [200.46.204.71])
+       by ams.hub.org (Postfix) with ESMTP id 84700C4B33D;
+       Thu, 17 Nov 2005 14:44:42 +0000 (GMT)
+X-Original-To: pgsql-hackers-postgresql.org@localhost.postgresql.org
+Received: from localhost (av.hub.org [200.46.204.144])
+       by svr1.postgresql.org (Postfix) with ESMTP id 84C6BD967F
+       for <pgsql-hackers-postgresql.org@localhost.postgresql.org>; Thu, 17 Nov 2005 10:41:57 -0400 (AST)
+Received: from svr1.postgresql.org ([200.46.204.71])
+       by localhost (av.hub.org [200.46.204.144]) (amavisd-new, port 10024)
+       with ESMTP id 47040-01
+       for <pgsql-hackers-postgresql.org@localhost.postgresql.org>;
+       Thu, 17 Nov 2005 14:42:00 +0000 (GMT)
+X-Greylist: from auto-whitelisted by SQLgrey-
+Received: from sss.pgh.pa.us (sss.pgh.pa.us [66.207.139.130])
+       by svr1.postgresql.org (Postfix) with ESMTP id ECB3CD963C
+       for <pgsql-hackers@postgresql.org>; Thu, 17 Nov 2005 10:41:53 -0400 (AST)
+Received: from sss2.sss.pgh.pa.us (tgl@localhost [127.0.0.1])
+       by sss.pgh.pa.us (8.13.1/8.13.1) with ESMTP id jAHEfAuK025850;
+       Thu, 17 Nov 2005 09:41:11 -0500 (EST)
+To: Csaba Nagy <nagy@ecircle-ag.com>
+cc: Martijn van Oosterhout <kleptog@svana.org>,
+   Zeugswetter Andreas DCP SD <ZeugswetterA@spardat.at>,
+   Dann Corbit <DCorbit@connx.com>, Simon Riggs <simon@2ndquadrant.com>,
+   Bruce Momjian <pgman@candle.pha.pa.us>,
+   Rick Gigger <rick@alpinenetworking.com>,
+   Christopher Kings-Lynne <chriskl@familyhealth.com.au>,
+   "Jim C. Nasby" <jnasby@pervasive.com>, josh@agliodbs.com,
+   pgsql-hackers@postgresql.org, Jaime Casanova <systemguards@gmail.com>,
+   Peter Eisentraut <peter_e@gmx.net>
+Subject: Re: [HACKERS] MERGE vs REPLACE 
+In-Reply-To: <1132231474.10890.317.camel@coppola.muc.ecircle.de> 
+References: <E1539E0ED7043848906A8FF995BDA5799A524D@m0143.s-mxs.net> <1132228373.10890.313.camel@coppola.muc.ecircle.de> <20051117123250.GC22933@svana.org> <1132231474.10890.317.camel@coppola.muc.ecircle.de>
+Comments: In-reply-to Csaba Nagy <nagy@ecircle-ag.com>
+       message dated "Thu, 17 Nov 2005 13:44:35 +0100"
+Date: Thu, 17 Nov 2005 09:41:10 -0500
+Message-ID: <25849.1132238470@sss.pgh.pa.us>
+From: Tom Lane <tgl@sss.pgh.pa.us>
+X-Virus-Scanned: by amavisd-new at hub.org
+X-Spam-Status: No, score=0.008 required=5 tests=[AWL=0.008]
+X-Spam-Score: 0.008
+X-Mailing-List: pgsql-hackers
+List-Archive: <http://archives.postgresql.org/pgsql-hackers>
+List-Help: <mailto:majordomo@postgresql.org?body=help>
+List-Id: <pgsql-hackers.postgresql.org>
+List-Owner: <mailto:pgsql-hackers-owner@postgresql.org>
+List-Post: <mailto:pgsql-hackers@postgresql.org>
+List-Subscribe: <mailto:majordomo@postgresql.org?body=sub%20pgsql-hackers>
+List-Unsubscribe: <mailto:majordomo@postgresql.org?body=unsub%20pgsql-hackers>
+Precedence: bulk
+Sender: pgsql-hackers-owner@postgresql.org
+Status: ORr
+
+Csaba Nagy <nagy@ecircle-ag.com> writes:
+> OK, in this case I don't care about either MERGE or REPLACE, but for an
+> UPSERT which does the locking :-)
+
+This is exactly the point --- pretty much nobody has come to us and
+asked for a feature that does what Peter and Martijn say MERGE does.
+(I haven't bothered to look at the 2003 spec, I'm assuming they read it
+correctly.)  What we *have* been asked for, over and over, is an
+insert-or-update feature that's not so tedious and inefficient as the
+savepoint-insert-rollback-update kluge.  That's what we ought to be
+concentrating on providing.
+
+                       regards, tom lane
+
+---------------------------(end of broadcast)---------------------------
+TIP 3: Have you checked our extensive FAQ?
+
+               http://www.postgresql.org/docs/faq
+
+From pgsql-hackers-owner+M76189@postgresql.org Thu Nov 17 10:17:57 2005
+Return-path: <pgsql-hackers-owner+M76189@postgresql.org>
+Received: from ams.hub.org (ams.hub.org [200.46.204.13])
+       by candle.pha.pa.us (8.11.6/8.11.6) with ESMTP id jAHFHvu12126
+       for <pgman@candle.pha.pa.us>; Thu, 17 Nov 2005 10:17:57 -0500 (EST)
+Received: from postgresql.org (svr1.postgresql.org [200.46.204.71])
+       by ams.hub.org (Postfix) with ESMTP id 9B0AFC4B33D;
+       Thu, 17 Nov 2005 15:17:55 +0000 (GMT)
+X-Original-To: pgsql-hackers-postgresql.org@localhost.postgresql.org
+Received: from localhost (av.hub.org [200.46.204.144])
+       by svr1.postgresql.org (Postfix) with ESMTP id 02FEFDB988
+       for <pgsql-hackers-postgresql.org@localhost.postgresql.org>; Thu, 17 Nov 2005 11:14:52 -0400 (AST)
+Received: from svr1.postgresql.org ([200.46.204.71])
+       by localhost (av.hub.org [200.46.204.144]) (amavisd-new, port 10024)
+       with ESMTP id 48136-10
+       for <pgsql-hackers-postgresql.org@localhost.postgresql.org>;
+       Thu, 17 Nov 2005 15:14:56 +0000 (GMT)
+X-Greylist: from auto-whitelisted by SQLgrey-
+Received: from svr2.postgresql.org (svr2.postgresql.org [65.19.161.25])
+       by svr1.postgresql.org (Postfix) with ESMTP id 34BD1DB97C
+       for <pgsql-hackers@postgresql.org>; Thu, 17 Nov 2005 11:14:50 -0400 (AST)
+Received: from ns.snowman.net (ns.snowman.net [66.92.160.21])
+       by svr2.postgresql.org (Postfix) with ESMTP id A8A8FF0BEF
+       for <pgsql-hackers@postgresql.org>; Thu, 17 Nov 2005 15:14:54 +0000 (GMT)
+Received: by ns.snowman.net (Postfix, from userid 1000)
+       id EDB5717AD6; Thu, 17 Nov 2005 10:15:30 -0500 (EST)
+Date: Thu, 17 Nov 2005 10:15:30 -0500
+From: Stephen Frost <sfrost@snowman.net>
+To: Tom Lane <tgl@sss.pgh.pa.us>
+cc: Csaba Nagy <nagy@ecircle-ag.com>,
+   Martijn van Oosterhout <kleptog@svana.org>,
+   Zeugswetter Andreas DCP SD <ZeugswetterA@spardat.at>,
+   Dann Corbit <DCorbit@connx.com>, Simon Riggs <simon@2ndquadrant.com>,
+   Bruce Momjian <pgman@candle.pha.pa.us>,
+   Rick Gigger <rick@alpinenetworking.com>,
+   Christopher Kings-Lynne <chriskl@familyhealth.com.au>,
+   "Jim C. Nasby" <jnasby@pervasive.com>, josh@agliodbs.com,
+   pgsql-hackers@postgresql.org, Jaime Casanova <systemguards@gmail.com>,
+   Peter Eisentraut <peter_e@gmx.net>
+Subject: Re: [HACKERS] MERGE vs REPLACE
+Message-ID: <20051117151530.GU6026@ns.snowman.net>
+Mail-Followup-To: Tom Lane <tgl@sss.pgh.pa.us>,
+       Csaba Nagy <nagy@ecircle-ag.com>,
+       Martijn van Oosterhout <kleptog@svana.org>,
+       Zeugswetter Andreas DCP SD <ZeugswetterA@spardat.at>,
+       Dann Corbit <DCorbit@connx.com>, Simon Riggs <simon@2ndquadrant.com>,
+       Bruce Momjian <pgman@candle.pha.pa.us>,
+       Rick Gigger <rick@alpinenetworking.com>,
+       Christopher Kings-Lynne <chriskl@familyhealth.com.au>,
+       "Jim C. Nasby" <jnasby@pervasive.com>, josh@agliodbs.com,
+       pgsql-hackers@postgresql.org,
+       Jaime Casanova <systemguards@gmail.com>,
+       Peter Eisentraut <peter_e@gmx.net>
+References: <E1539E0ED7043848906A8FF995BDA5799A524D@m0143.s-mxs.net> <1132228373.10890.313.camel@coppola.muc.ecircle.de> <20051117123250.GC22933@svana.org> <1132231474.10890.317.camel@coppola.muc.ecircle.de> <25849.1132238470@sss.pgh.pa.us>
+MIME-Version: 1.0
+Content-Type: multipart/signed; micalg=pgp-sha1;
+       protocol="application/pgp-signature"; boundary="aAYbr14jHAy2Yyau"
+Content-Disposition: inline
+In-Reply-To: <25849.1132238470@sss.pgh.pa.us>
+X-Editor: Vim http://www.vim.org/
+X-Info: http://www.snowman.net
+X-Operating-System: Linux/2.4.24ns.3.0 (i686)
+X-Uptime: 10:01:46 up 159 days,  7:15,  2 users,  load average: 0.31, 0.23, 0.13
+User-Agent: Mutt/1.5.9i
+X-Virus-Scanned: by amavisd-new at hub.org
+X-Spam-Status: No, score=0 required=5 tests=[none]
+X-Spam-Score: 0
+X-Mailing-List: pgsql-hackers
+List-Archive: <http://archives.postgresql.org/pgsql-hackers>
+List-Help: <mailto:majordomo@postgresql.org?body=help>
+List-Id: <pgsql-hackers.postgresql.org>
+List-Owner: <mailto:pgsql-hackers-owner@postgresql.org>
+List-Post: <mailto:pgsql-hackers@postgresql.org>
+List-Subscribe: <mailto:majordomo@postgresql.org?body=sub%20pgsql-hackers>
+List-Unsubscribe: <mailto:majordomo@postgresql.org?body=unsub%20pgsql-hackers>
+Precedence: bulk
+Sender: pgsql-hackers-owner@postgresql.org
+Status: OR
+
+
+--aAYbr14jHAy2Yyau
+Content-Type: text/plain; charset=us-ascii
+Content-Disposition: inline
+Content-Transfer-Encoding: quoted-printable
+
+* Tom Lane (tgl@sss.pgh.pa.us) wrote:
+> This is exactly the point --- pretty much nobody has come to us and
+> asked for a feature that does what Peter and Martijn say MERGE does.
+> (I haven't bothered to look at the 2003 spec, I'm assuming they read it
+> correctly.)  What we *have* been asked for, over and over, is an
+> insert-or-update feature that's not so tedious and inefficient as the
+> savepoint-insert-rollback-update kluge.  That's what we ought to be
+> concentrating on providing.
+
+I guess to be clear on what this distinction actually is, specifically:
+MERGE under SQL2003 doesn't appear to be intended to be used
+concurrently.  For data warehousing situations this can be just fine
+such as in my case where I get a monthly update of some information and
+need to merge that update in with the prior information.  In this case
+there's only one MERGE running and I'd hope it'd be faster than doing
+check for existance, insert/update on each row in plpgsql or something
+(since there'd be multiple index lookups, etc, I think).  Concurrent
+MERGEs running *can* fail, just like whole transactions which do the
+check/insert/update can fail.
+
+REPLACE/INSERT ON DUPLICATE UPDATE appears to essentially be a
+transaction which is supposed to not fail but instead do locking to
+ensure that it doesn't fail.  This requires predicate locking to be
+efficient because you want to tell the concurrent transaction "if you
+have the same key as me, just wait a second and you can do an update
+'cause I'm going to create the key if it doesn't exist before I'm done".
+
+I think REPLACE/INSERT ON DUPLICATE UPDATE is definitely harder to do
+than MERGE because of the idea that it isn't supposed to fail generally.
+I think SQL2003 MERGE would be reasonably easy to do and to get the
+efficiency benefits out of it (assuming there are some to be had in the
+end). =20
+
+I don't think MERGE can really be made to be both though, in which case
+it should really be the SQL2003 MERGE and we can make REPLACE/INSERT ON
+DUPLICATE UPDATE something else.  Perhaps a special form of MERGE where
+you know it's going to be doing that locking.  I really don't like the
+idea of making the SQL2003 version of MERGE be the MERGE special case
+(by requiring someone to take a table lock ahead of time or do something
+else odd).
+
+       Thanks,
+
+               Stephen
+
+--aAYbr14jHAy2Yyau
+Content-Type: application/pgp-signature; name="signature.asc"
+Content-Description: Digital signature
+Content-Disposition: inline
+
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v1.4.2 (GNU/Linux)
+
+iD8DBQFDfJ6SrzgMPqB3kigRAjXWAJ9R/50PoocURxvi74g7dwhIO4akgQCcDEDG
+4hGZAVR/9Age8pFtEOp4kfo=
+=F91e
+-----END PGP SIGNATURE-----
+
+--aAYbr14jHAy2Yyau--
+
+From sfrost@snowman.net Thu Nov 17 10:14:59 2005
+Return-path: <sfrost@snowman.net>
+Received: from ns.snowman.net (ns.snowman.net [66.92.160.21])
+       by candle.pha.pa.us (8.11.6/8.11.6) with ESMTP id jAHFEwu11635
+       for <pgman@candle.pha.pa.us>; Thu, 17 Nov 2005 10:14:58 -0500 (EST)
+Received: by ns.snowman.net (Postfix, from userid 1000)
+       id EDB5717AD6; Thu, 17 Nov 2005 10:15:30 -0500 (EST)
+Date: Thu, 17 Nov 2005 10:15:30 -0500
+From: Stephen Frost <sfrost@snowman.net>
+To: Tom Lane <tgl@sss.pgh.pa.us>
+cc: Csaba Nagy <nagy@ecircle-ag.com>,
+   Martijn van Oosterhout <kleptog@svana.org>,
+   Zeugswetter Andreas DCP SD <ZeugswetterA@spardat.at>,
+   Dann Corbit <DCorbit@connx.com>, Simon Riggs <simon@2ndquadrant.com>,
+   Bruce Momjian <pgman@candle.pha.pa.us>,
+   Rick Gigger <rick@alpinenetworking.com>,
+   Christopher Kings-Lynne <chriskl@familyhealth.com.au>,
+   "Jim C. Nasby" <jnasby@pervasive.com>, josh@agliodbs.com,
+   pgsql-hackers@postgresql.org, Jaime Casanova <systemguards@gmail.com>,
+   Peter Eisentraut <peter_e@gmx.net>
+Subject: Re: [HACKERS] MERGE vs REPLACE
+Message-ID: <20051117151530.GU6026@ns.snowman.net>
+Mail-Followup-To: Tom Lane <tgl@sss.pgh.pa.us>,
+       Csaba Nagy <nagy@ecircle-ag.com>,
+       Martijn van Oosterhout <kleptog@svana.org>,
+       Zeugswetter Andreas DCP SD <ZeugswetterA@spardat.at>,
+       Dann Corbit <DCorbit@connx.com>,
+       Simon Riggs <simon@2ndquadrant.com>,
+       Bruce Momjian <pgman@candle.pha.pa.us>,
+       Rick Gigger <rick@alpinenetworking.com>,
+       Christopher Kings-Lynne <chriskl@familyhealth.com.au>,
+       "Jim C. Nasby" <jnasby@pervasive.com>, josh@agliodbs.com,
+       pgsql-hackers@postgresql.org,
+       Jaime Casanova <systemguards@gmail.com>,
+       Peter Eisentraut <peter_e@gmx.net>
+References: <E1539E0ED7043848906A8FF995BDA5799A524D@m0143.s-mxs.net> <1132228373.10890.313.camel@coppola.muc.ecircle.de> <20051117123250.GC22933@svana.org> <1132231474.10890.317.camel@coppola.muc.ecircle.de> <25849.1132238470@sss.pgh.pa.us>
+MIME-Version: 1.0
+Content-Type: multipart/signed; micalg=pgp-sha1;
+       protocol="application/pgp-signature"; boundary="aAYbr14jHAy2Yyau"
+Content-Disposition: inline
+In-Reply-To: <25849.1132238470@sss.pgh.pa.us>
+X-Editor: Vim http://www.vim.org/
+X-Info: http://www.snowman.net
+X-Operating-System: Linux/2.4.24ns.3.0 (i686)
+X-Uptime: 10:01:46 up 159 days,  7:15,  2 users,  load average: 0.31, 0.23, 0.13
+User-Agent: Mutt/1.5.9i
+Status: OR
+
+
+--aAYbr14jHAy2Yyau
+Content-Type: text/plain; charset=us-ascii
+Content-Disposition: inline
+Content-Transfer-Encoding: quoted-printable
+
+* Tom Lane (tgl@sss.pgh.pa.us) wrote:
+> This is exactly the point --- pretty much nobody has come to us and
+> asked for a feature that does what Peter and Martijn say MERGE does.
+> (I haven't bothered to look at the 2003 spec, I'm assuming they read it
+> correctly.)  What we *have* been asked for, over and over, is an
+> insert-or-update feature that's not so tedious and inefficient as the
+> savepoint-insert-rollback-update kluge.  That's what we ought to be
+> concentrating on providing.
+
+I guess to be clear on what this distinction actually is, specifically:
+MERGE under SQL2003 doesn't appear to be intended to be used
+concurrently.  For data warehousing situations this can be just fine
+such as in my case where I get a monthly update of some information and
+need to merge that update in with the prior information.  In this case
+there's only one MERGE running and I'd hope it'd be faster than doing
+check for existance, insert/update on each row in plpgsql or something
+(since there'd be multiple index lookups, etc, I think).  Concurrent
+MERGEs running *can* fail, just like whole transactions which do the
+check/insert/update can fail.
+
+REPLACE/INSERT ON DUPLICATE UPDATE appears to essentially be a
+transaction which is supposed to not fail but instead do locking to
+ensure that it doesn't fail.  This requires predicate locking to be
+efficient because you want to tell the concurrent transaction "if you
+have the same key as me, just wait a second and you can do an update
+'cause I'm going to create the key if it doesn't exist before I'm done".
+
+I think REPLACE/INSERT ON DUPLICATE UPDATE is definitely harder to do
+than MERGE because of the idea that it isn't supposed to fail generally.
+I think SQL2003 MERGE would be reasonably easy to do and to get the
+efficiency benefits out of it (assuming there are some to be had in the
+end). =20
+
+I don't think MERGE can really be made to be both though, in which case
+it should really be the SQL2003 MERGE and we can make REPLACE/INSERT ON
+DUPLICATE UPDATE something else.  Perhaps a special form of MERGE where
+you know it's going to be doing that locking.  I really don't like the
+idea of making the SQL2003 version of MERGE be the MERGE special case
+(by requiring someone to take a table lock ahead of time or do something
+else odd).
+
+       Thanks,
+
+               Stephen
+
+--aAYbr14jHAy2Yyau
+Content-Type: application/pgp-signature; name="signature.asc"
+Content-Description: Digital signature
+Content-Disposition: inline
+
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v1.4.2 (GNU/Linux)
+
+iD8DBQFDfJ6SrzgMPqB3kigRAjXWAJ9R/50PoocURxvi74g7dwhIO4akgQCcDEDG
+4hGZAVR/9Age8pFtEOp4kfo=
+=F91e
+-----END PGP SIGNATURE-----
+
+--aAYbr14jHAy2Yyau--
+
+From pgsql-hackers-owner+M76234@postgresql.org Thu Nov 17 22:19:04 2005
+Return-path: <pgsql-hackers-owner+M76234@postgresql.org>
+Received: from ams.hub.org (ams.hub.org [200.46.204.13])
+       by candle.pha.pa.us (8.11.6/8.11.6) with ESMTP id jAI3J3O11471
+       for <pgman@candle.pha.pa.us>; Thu, 17 Nov 2005 22:19:04 -0500 (EST)
+Received: from postgresql.org (svr1.postgresql.org [200.46.204.71])
+       by ams.hub.org (Postfix) with ESMTP id CBDDBC4B337;
+       Fri, 18 Nov 2005 03:18:59 +0000 (GMT)
+X-Original-To: pgsql-hackers-postgresql.org@localhost.postgresql.org
+Received: from localhost (av.hub.org [200.46.204.144])
+       by svr1.postgresql.org (Postfix) with ESMTP id BB822DB600
+       for <pgsql-hackers-postgresql.org@localhost.postgresql.org>; Thu, 17 Nov 2005 23:12:08 -0400 (AST)
+Received: from svr1.postgresql.org ([200.46.204.71])
+       by localhost (av.hub.org [200.46.204.144]) (amavisd-new, port 10024)
+       with ESMTP id 30987-04
+       for <pgsql-hackers-postgresql.org@localhost.postgresql.org>;
+       Fri, 18 Nov 2005 03:12:11 +0000 (GMT)
+X-Greylist: from auto-whitelisted by SQLgrey-
+Received: from candle.pha.pa.us (candle.pha.pa.us [64.139.89.126])
+       by svr1.postgresql.org (Postfix) with ESMTP id 7CB16DB466
+       for <pgsql-hackers@postgresql.org>; Thu, 17 Nov 2005 23:12:05 -0400 (AST)
+Received: (from pgman@localhost)
+       by candle.pha.pa.us (8.11.6/8.11.6) id jAI3BXS10887;
+       Thu, 17 Nov 2005 22:11:33 -0500 (EST)
+From: Bruce Momjian <pgman@candle.pha.pa.us>
+Message-ID: <200511180311.jAI3BXS10887@candle.pha.pa.us>
+Subject: Re: [HACKERS] MERGE vs REPLACE
+In-Reply-To: <25849.1132238470@sss.pgh.pa.us>
+To: Tom Lane <tgl@sss.pgh.pa.us>
+Date: Thu, 17 Nov 2005 22:11:33 -0500 (EST)
+cc: Csaba Nagy <nagy@ecircle-ag.com>,
+   Martijn van Oosterhout <kleptog@svana.org>,
+   Zeugswetter Andreas DCP SD <ZeugswetterA@spardat.at>,
+   Dann Corbit <DCorbit@connx.com>, Simon Riggs <simon@2ndquadrant.com>,
+   Rick Gigger <rick@alpinenetworking.com>,
+   Christopher Kings-Lynne <chriskl@familyhealth.com.au>,
+   "Jim C. Nasby" <jnasby@pervasive.com>, josh@agliodbs.com,
+   pgsql-hackers@postgresql.org, Jaime Casanova <systemguards@gmail.com>,
+   Peter Eisentraut <peter_e@gmx.net>
+X-Mailer: ELM [version 2.4ME+ PL121 (25)]
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Content-Type: text/plain; charset=US-ASCII
+X-Virus-Scanned: by amavisd-new at hub.org
+X-Spam-Status: No, score=0.036 required=5 tests=[AWL=0.036]
+X-Spam-Score: 0.036
+X-Mailing-List: pgsql-hackers
+List-Archive: <http://archives.postgresql.org/pgsql-hackers>
+List-Help: <mailto:majordomo@postgresql.org?body=help>
+List-Id: <pgsql-hackers.postgresql.org>
+List-Owner: <mailto:pgsql-hackers-owner@postgresql.org>
+List-Post: <mailto:pgsql-hackers@postgresql.org>
+List-Subscribe: <mailto:majordomo@postgresql.org?body=sub%20pgsql-hackers>
+List-Unsubscribe: <mailto:majordomo@postgresql.org?body=unsub%20pgsql-hackers>
+Precedence: bulk
+Sender: pgsql-hackers-owner@postgresql.org
+Status: OR
+
+Tom Lane wrote:
+> Csaba Nagy <nagy@ecircle-ag.com> writes:
+> > OK, in this case I don't care about either MERGE or REPLACE, but for an
+> > UPSERT which does the locking :-)
+> 
+> This is exactly the point --- pretty much nobody has come to us and
+> asked for a feature that does what Peter and Martijn say MERGE does.
+> (I haven't bothered to look at the 2003 spec, I'm assuming they read it
+> correctly.)  What we *have* been asked for, over and over, is an
+> insert-or-update feature that's not so tedious and inefficient as the
+> savepoint-insert-rollback-update kluge.  That's what we ought to be
+> concentrating on providing.
+
+I am confused over the various options.  I have heard these syntaxes:
+
+       SQL2003 MERGE
+       MySQL REPLACE
+               http://dev.mysql.com/doc/refman/5.1/en/replace.html
+       MySQL INSERT VIOLATION ...
+       UPSERT
+
+So it seems MERGE does not have the use-case we most need, though it can
+be bent to do it.  (Given their MATCH syntax, it doesn't seem there is
+any logic that it tries INSERT first).
+
+Looking at the MySQL URL above, REPLACE has three possible syntaxes with
+normal (DELETE), SET (UPDATE), and SELECT.  Is this the direction we
+need to go?  I don't like INSERT ... VIOLATION because I would like a
+new keyword for this.  Is UPSERT the same as REPLACE?  Should we use
+UPSERT instead?
+       
+-- 
+  Bruce Momjian                        |  http://candle.pha.pa.us
+  pgman@candle.pha.pa.us               |  (610) 359-1001
+  +  If your life is a hard drive,     |  13 Roberts Road
+  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073
+
+---------------------------(end of broadcast)---------------------------
+TIP 4: Have you searched our list archives?
+
+               http://archives.postgresql.org
+
+From DCorbit@connx.com Thu Nov 17 22:43:54 2005
+Return-path: <DCorbit@connx.com>
+Received: from postal.corporate.connx.com (postal.corporate.connx.com [65.212.159.187])
+       by candle.pha.pa.us (8.11.6/8.11.6) with SMTP id jAI3hqO14288
+       for <pgman@candle.pha.pa.us>; Thu, 17 Nov 2005 22:43:52 -0500 (EST)
+content-class: urn:content-classes:message
+MIME-Version: 1.0
+Content-Type: multipart/mixed;
+       boundary="----_=_NextPart_001_01C5EBF2.45ACB7DC"
+X-MimeOLE: Produced By Microsoft Exchange V6.5.7226.0
+Subject: RE: [HACKERS] MERGE vs REPLACE
+Date: Thu, 17 Nov 2005 19:43:43 -0800
+Message-ID: <D425483C2C5C9F49B5B7A41F8944154757D2EB@postal.corporate.connx.com>
+Thread-Topic: [HACKERS] MERGE vs REPLACE
+Thread-Index: AcXr7dUIILx3WyhrREu/dEAzLwToBgABFVZw
+From: "Dann Corbit" <DCorbit@connx.com>
+To: "Bruce Momjian" <pgman@candle.pha.pa.us>, "Tom Lane" <tgl@sss.pgh.pa.us>
+cc: "Csaba Nagy" <nagy@ecircle-ag.com>,
+   "Martijn van Oosterhout" <kleptog@svana.org>,
+   "Zeugswetter Andreas DCP SD" <ZeugswetterA@spardat.at>,
+   "Simon Riggs" <simon@2ndquadrant.com>,
+   "Rick Gigger" <rick@alpinenetworking.com>,
+   "Christopher Kings-Lynne" <chriskl@familyhealth.com.au>,
+   "Jim C. Nasby" <jnasby@pervasive.com>, <josh@agliodbs.com>,
+   <pgsql-hackers@postgresql.org>, "Jaime Casanova" <systemguards@gmail.com>,
+   "Peter Eisentraut" <peter_e@gmx.net>
+Status: OR
+
+This is a multi-part message in MIME format.
+
+------_=_NextPart_001_01C5EBF2.45ACB7DC
+Content-Type: text/plain;
+       charset="us-ascii"
+Content-Transfer-Encoding: quoted-printable
+
+Attached web page is an extract from the SQL Standards working committee
+document on MERGE
+
+> -----Original Message-----
+> From: Bruce Momjian [mailto:pgman@candle.pha.pa.us]
+> Sent: Thursday, November 17, 2005 7:12 PM
+> To: Tom Lane
+> Cc: Csaba Nagy; Martijn van Oosterhout; Zeugswetter Andreas DCP SD;
+Dann
+> Corbit; Simon Riggs; Rick Gigger; Christopher Kings-Lynne; Jim C.
+Nasby;
+> josh@agliodbs.com; pgsql-hackers@postgresql.org; Jaime Casanova; Peter
+> Eisentraut
+> Subject: Re: [HACKERS] MERGE vs REPLACE
+>=20
+> Tom Lane wrote:
+> > Csaba Nagy <nagy@ecircle-ag.com> writes:
+> > > OK, in this case I don't care about either MERGE or REPLACE, but
+for
+> an
+> > > UPSERT which does the locking :-)
+> >
+> > This is exactly the point --- pretty much nobody has come to us and
+> > asked for a feature that does what Peter and Martijn say MERGE does.
+> > (I haven't bothered to look at the 2003 spec, I'm assuming they read
+it
+> > correctly.)  What we *have* been asked for, over and over, is an
+> > insert-or-update feature that's not so tedious and inefficient as
+the
+> > savepoint-insert-rollback-update kluge.  That's what we ought to be
+> > concentrating on providing.
+>=20
+> I am confused over the various options.  I have heard these syntaxes:
+>=20
+>      SQL2003 MERGE
+>      MySQL REPLACE
+>              http://dev.mysql.com/doc/refman/5.1/en/replace.html
+>      MySQL INSERT VIOLATION ...
+>      UPSERT
+>=20
+> So it seems MERGE does not have the use-case we most need, though it
+can
+> be bent to do it.  (Given their MATCH syntax, it doesn't seem there is
+> any logic that it tries INSERT first).
+>=20
+> Looking at the MySQL URL above, REPLACE has three possible syntaxes
+with
+> normal (DELETE), SET (UPDATE), and SELECT.  Is this the direction we
+> need to go?  I don't like INSERT ... VIOLATION because I would like a
+> new keyword for this.  Is UPSERT the same as REPLACE?  Should we use
+> UPSERT instead?
+>=20
+> --
+>   Bruce Momjian                        |  http://candle.pha.pa.us
+>   pgman@candle.pha.pa.us               |  (610) 359-1001
+>   +  If your life is a hard drive,     |  13 Roberts Road
+>   +  Christ can be your backup.        |  Newtown Square, Pennsylvania
+> 19073
+
+------_=_NextPart_001_01C5EBF2.45ACB7DC
+Content-Type: text/html;
+       name="merge.htm"
+Content-Transfer-Encoding: base64
+Content-Description: merge.htm
+Content-Disposition: attachment;
+       filename="merge.htm"
+
+PGh0bWwgeG1sbnM6bz0idXJuOnNjaGVtYXMtbWljcm9zb2Z0LWNvbTpvZmZpY2U6b2ZmaWNlIg0K
+eG1sbnM6dz0idXJuOnNjaGVtYXMtbWljcm9zb2Z0LWNvbTpvZmZpY2U6d29yZCINCnhtbG5zOng9
+InVybjpzY2hlbWFzLW1pY3Jvc29mdC1jb206b2ZmaWNlOmV4Y2VsIg0KeG1sbnM9Imh0dHA6Ly93
+d3cudzMub3JnL1RSL1JFQy1odG1sNDAiPg0KDQo8aGVhZD4NCjxtZXRhIGh0dHAtZXF1aXY9Q29u
+dGVudC1UeXBlIGNvbnRlbnQ9InRleHQvaHRtbDsgY2hhcnNldD13aW5kb3dzLTEyNTIiPg0KPG1l
+dGEgbmFtZT1Qcm9nSWQgY29udGVudD1Xb3JkLkRvY3VtZW50Pg0KPG1ldGEgbmFtZT1HZW5lcmF0
+b3IgY29udGVudD0iTWljcm9zb2Z0IFdvcmQgMTEiPg0KPG1ldGEgbmFtZT1PcmlnaW5hdG9yIGNv
+bnRlbnQ9Ik1pY3Jvc29mdCBXb3JkIDExIj4NCjxsaW5rIHJlbD1GaWxlLUxpc3QgaHJlZj0ibWVy
+Z2VfZmlsZXMvZmlsZWxpc3QueG1sIj4NCjx0aXRsZT4xNDwvdGl0bGU+DQo8IS0tW2lmIGd0ZSBt
+c28gOV0+PHhtbD4NCiA8bzpEb2N1bWVudFByb3BlcnRpZXM+DQogIDxvOkF1dGhvcj5EYW5uIENv
+cmJpdDwvbzpBdXRob3I+DQogIDxvOkxhc3RBdXRob3I+RGFubiBDb3JiaXQ8L286TGFzdEF1dGhv
+cj4NCiAgPG86UmV2aXNpb24+MTwvbzpSZXZpc2lvbj4NCiAgPG86VG90YWxUaW1lPjc8L286VG90
+YWxUaW1lPg0KICA8bzpDcmVhdGVkPjIwMDUtMTEtMThUMDM6MzU6MDBaPC9vOkNyZWF0ZWQ+DQog
+IDxvOkxhc3RTYXZlZD4yMDA1LTExLTE4VDAzOjQyOjAwWjwvbzpMYXN0U2F2ZWQ+DQogIDxvOlBh
+Z2VzPjE8L286UGFnZXM+DQogIDxvOldvcmRzPjIzODk8L286V29yZHM+DQogIDxvOkNoYXJhY3Rl
+cnM+MTM2MjE8L286Q2hhcmFjdGVycz4NCiAgPG86Q29tcGFueT5DT05OWCBTb2x1dGlvbnM8L286
+Q29tcGFueT4NCiAgPG86TGluZXM+MTEzPC9vOkxpbmVzPg0KICA8bzpQYXJhZ3JhcGhzPjMxPC9v
+OlBhcmFncmFwaHM+DQogIDxvOkNoYXJhY3RlcnNXaXRoU3BhY2VzPjE1OTc5PC9vOkNoYXJhY3Rl
+cnNXaXRoU3BhY2VzPg0KICA8bzpWZXJzaW9uPjExLjY1Njg8L286VmVyc2lvbj4NCiA8L286RG9j
+dW1lbnRQcm9wZXJ0aWVzPg0KPC94bWw+PCFbZW5kaWZdLS0+PCEtLVtpZiBndGUgbXNvIDldPjx4
+bWw+DQogPHc6V29yZERvY3VtZW50Pg0KICA8dzpTcGVsbGluZ1N0YXRlPkNsZWFuPC93OlNwZWxs
+aW5nU3RhdGU+DQogIDx3OkdyYW1tYXJTdGF0ZT5DbGVhbjwvdzpHcmFtbWFyU3RhdGU+DQogIDx3
+OlB1bmN0dWF0aW9uS2VybmluZy8+DQogIDx3OlZhbGlkYXRlQWdhaW5zdFNjaGVtYXMvPg0KICA8
+dzpTYXZlSWZYTUxJbnZhbGlkPmZhbHNlPC93OlNhdmVJZlhNTEludmFsaWQ+DQogIDx3Oklnbm9y
+ZU1peGVkQ29udGVudD5mYWxzZTwvdzpJZ25vcmVNaXhlZENvbnRlbnQ+DQogIDx3OkFsd2F5c1No
+b3dQbGFjZWhvbGRlclRleHQ+ZmFsc2U8L3c6QWx3YXlzU2hvd1BsYWNlaG9sZGVyVGV4dD4NCiAg
+PHc6Q29tcGF0aWJpbGl0eT4NCiAgIDx3OkJyZWFrV3JhcHBlZFRhYmxlcy8+DQogICA8dzpTbmFw
+VG9HcmlkSW5DZWxsLz4NCiAgIDx3OldyYXBUZXh0V2l0aFB1bmN0Lz4NCiAgIDx3OlVzZUFzaWFu
+QnJlYWtSdWxlcy8+DQogICA8dzpEb250R3Jvd0F1dG9maXQvPg0KICA8L3c6Q29tcGF0aWJpbGl0
+eT4NCiAgPHc6QnJvd3NlckxldmVsPk1pY3Jvc29mdEludGVybmV0RXhwbG9yZXI0PC93OkJyb3dz
+ZXJMZXZlbD4NCiA8L3c6V29yZERvY3VtZW50Pg0KPC94bWw+PCFbZW5kaWZdLS0+PCEtLVtpZiBn
+dGUgbXNvIDldPjx4bWw+DQogPHc6TGF0ZW50U3R5bGVzIERlZkxvY2tlZFN0YXRlPSJmYWxzZSIg
+TGF0ZW50U3R5bGVDb3VudD0iMTU2Ij4NCiA8L3c6TGF0ZW50U3R5bGVzPg0KPC94bWw+PCFbZW5k
+aWZdLS0+DQo8c3R5bGU+DQo8IS0tDQogLyogRm9udCBEZWZpbml0aW9ucyAqLw0KIEBmb250LWZh
+Y2UNCgl7Zm9udC1mYW1pbHk6Q291cmllcjsNCglwYW5vc2UtMToyIDcgNCA5IDIgMiA1IDIgNCA0
+Ow0KCW1zby1mb250LWNoYXJzZXQ6MDsNCgltc28tZ2VuZXJpYy1mb250LWZhbWlseTptb2Rlcm47
+DQoJbXNvLWZvbnQtZm9ybWF0Om90aGVyOw0KCW1zby1mb250LXBpdGNoOmZpeGVkOw0KCW1zby1m
+b250LXNpZ25hdHVyZTozIDAgMCAwIDEgMDt9DQogLyogU3R5bGUgRGVmaW5pdGlvbnMgKi8NCiBw
+Lk1zb05vcm1hbCwgbGkuTXNvTm9ybWFsLCBkaXYuTXNvTm9ybWFsDQoJe21zby1zdHlsZS1wYXJl
+bnQ6IiI7DQoJbWFyZ2luOjBpbjsNCgltYXJnaW4tYm90dG9tOi4wMDAxcHQ7DQoJbXNvLXBhZ2lu
+YXRpb246d2lkb3ctb3JwaGFuOw0KCWZvbnQtc2l6ZToxMi4wcHQ7DQoJZm9udC1mYW1pbHk6IlRp
+bWVzIE5ldyBSb21hbiI7DQoJbXNvLWZhcmVhc3QtZm9udC1mYW1pbHk6IlRpbWVzIE5ldyBSb21h
+biI7fQ0Kc3Bhbi5TcGVsbEUNCgl7bXNvLXN0eWxlLW5hbWU6IiI7DQoJbXNvLXNwbC1lOnllczt9
+DQpzcGFuLkdyYW1FDQoJe21zby1zdHlsZS1uYW1lOiIiOw0KCW1zby1ncmFtLWU6eWVzO30NCkBw
+YWdlIFNlY3Rpb24xDQoJe3NpemU6OC41aW4gMTEuMGluOw0KCW1hcmdpbjouNzVpbiAuNzVpbiAu
+NzVpbiAuNzVpbjsNCgltc28taGVhZGVyLW1hcmdpbjouNWluOw0KCW1zby1mb290ZXItbWFyZ2lu
+Oi41aW47DQoJbXNvLXBhcGVyLXNvdXJjZTowO30NCmRpdi5TZWN0aW9uMQ0KCXtwYWdlOlNlY3Rp
+b24xO30NCi0tPg0KPC9zdHlsZT4NCjwhLS1baWYgZ3RlIG1zbyAxMF0+DQo8c3R5bGU+DQogLyog
+U3R5bGUgRGVmaW5pdGlvbnMgKi8NCiB0YWJsZS5Nc29Ob3JtYWxUYWJsZQ0KCXttc28tc3R5bGUt
+bmFtZToiVGFibGUgTm9ybWFsIjsNCgltc28tdHN0eWxlLXJvd2JhbmQtc2l6ZTowOw0KCW1zby10
+c3R5bGUtY29sYmFuZC1zaXplOjA7DQoJbXNvLXN0eWxlLW5vc2hvdzp5ZXM7DQoJbXNvLXN0eWxl
+LXBhcmVudDoiIjsNCgltc28tcGFkZGluZy1hbHQ6MGluIDUuNHB0IDBpbiA1LjRwdDsNCgltc28t
+cGFyYS1tYXJnaW46MGluOw0KCW1zby1wYXJhLW1hcmdpbi1ib3R0b206LjAwMDFwdDsNCgltc28t
+cGFnaW5hdGlvbjp3aWRvdy1vcnBoYW47DQoJZm9udC1zaXplOjEwLjBwdDsNCglmb250LWZhbWls
+eToiVGltZXMgTmV3IFJvbWFuIjsNCgltc28tYW5zaS1sYW5ndWFnZTojMDQwMDsNCgltc28tZmFy
+ZWFzdC1sYW5ndWFnZTojMDQwMDsNCgltc28tYmlkaS1sYW5ndWFnZTojMDQwMDt9DQo8L3N0eWxl
+Pg0KPCFbZW5kaWZdLS0+DQo8L2hlYWQ+DQoNCjxib2R5IGxhbmc9RU4tVVMgc3R5bGU9J3RhYi1p
+bnRlcnZhbDouNWluJz4NCg0KPGRpdiBjbGFzcz1TZWN0aW9uMT4NCg0KPHAgY2xhc3M9TXNvTm9y
+bWFsIHN0eWxlPSdtc28tbGF5b3V0LWdyaWQtYWxpZ246bm9uZTt0ZXh0LWF1dG9zcGFjZTpub25l
+Jz48Yj48c3Bhbg0Kc3R5bGU9J2ZvbnQtc2l6ZToxNC4wcHQ7Y29sb3I6YmxhY2snPjE0LjkgJmx0
+O21lcmdlIHN0YXRlbWVudCZndDs8bzpwPjwvbzpwPjwvc3Bhbj48L2I+PC9wPg0KDQo8cCBjbGFz
+cz1Nc29Ob3JtYWwgc3R5bGU9J21zby1sYXlvdXQtZ3JpZC1hbGlnbjpub25lO3RleHQtYXV0b3Nw
+YWNlOm5vbmUnPjxiPjxzcGFuDQpzdHlsZT0nZm9udC1zaXplOjE0LjBwdDtjb2xvcjpibGFjayc+
+RnVuY3Rpb248bzpwPjwvbzpwPjwvc3Bhbj48L2I+PC9wPg0KDQo8cCBjbGFzcz1Nc29Ob3JtYWwg
+c3R5bGU9J21zby1sYXlvdXQtZ3JpZC1hbGlnbjpub25lO3RleHQtYXV0b3NwYWNlOm5vbmUnPjxz
+cGFuDQpzdHlsZT0nZm9udC1zaXplOjExLjBwdDtjb2xvcjpibGFjayc+Q29uZGl0aW9uYWxseSB1
+cGRhdGUgcm93cyBvZiBhIHRhYmxlLCBvcg0KaW5zZXJ0IG5ldyByb3dzIGludG8gYSB0YWJsZSwg
+b3IgYm90aC48bzpwPjwvbzpwPjwvc3Bhbj48L3A+DQoNCjxwIGNsYXNzPU1zb05vcm1hbCBzdHls
+ZT0nbXNvLWxheW91dC1ncmlkLWFsaWduOm5vbmU7dGV4dC1hdXRvc3BhY2U6bm9uZSc+PGI+PHNw
+YW4NCnN0eWxlPSdmb250LXNpemU6MTQuMHB0O2NvbG9yOmJsYWNrJz5Gb3JtYXQ8bzpwPjwvbzpw
+Pjwvc3Bhbj48L2I+PC9wPg0KDQo8cCBjbGFzcz1Nc29Ob3JtYWwgc3R5bGU9J21zby1sYXlvdXQt
+Z3JpZC1hbGlnbjpub25lO3RleHQtYXV0b3NwYWNlOm5vbmUnPjxzcGFuDQpzdHlsZT0nZm9udC1z
+aXplOjkuMHB0O2ZvbnQtZmFtaWx5OkNvdXJpZXI7bXNvLWJpZGktZm9udC1mYW1pbHk6Q291cmll
+cjsNCmNvbG9yOmJsYWNrJz4mbHQ7PHNwYW4gY2xhc3M9R3JhbUU+bWVyZ2U8L3NwYW4+IHN0YXRl
+bWVudCZndDsgOjo9PG86cD48L286cD48L3NwYW4+PC9wPg0KDQo8cCBjbGFzcz1Nc29Ob3JtYWwg
+c3R5bGU9J21zby1sYXlvdXQtZ3JpZC1hbGlnbjpub25lO3RleHQtYXV0b3NwYWNlOm5vbmUnPjxz
+cGFuDQpzdHlsZT0nZm9udC1zaXplOjkuMHB0O2ZvbnQtZmFtaWx5OkNvdXJpZXI7bXNvLWJpZGkt
+Zm9udC1mYW1pbHk6Q291cmllcjsNCmNvbG9yOmJsYWNrJz5NRVJHRSBJTlRPICZsdDt0YXJnZXQg
+dGFibGUmZ3Q7IDxzcGFuIGNsYXNzPUdyYW1FPlsgWzwvc3Bhbj4gQVMgXQ0KJmx0O21lcmdlIGNv
+cnJlbGF0aW9uIG5hbWUmZ3Q7IF08bzpwPjwvbzpwPjwvc3Bhbj48L3A+DQoNCjxwIGNsYXNzPU1z
+b05vcm1hbCBzdHlsZT0nbXNvLWxheW91dC1ncmlkLWFsaWduOm5vbmU7dGV4dC1hdXRvc3BhY2U6
+bm9uZSc+PHNwYW4NCnN0eWxlPSdmb250LXNpemU6OS4wcHQ7Zm9udC1mYW1pbHk6Q291cmllcjtt
+c28tYmlkaS1mb250LWZhbWlseTpDb3VyaWVyOw0KY29sb3I6YmxhY2snPlVTSU5HICZsdDt0YWJs
+ZSByZWZlcmVuY2UmZ3Q7PG86cD48L286cD48L3NwYW4+PC9wPg0KDQo8cCBjbGFzcz1Nc29Ob3Jt
+YWwgc3R5bGU9J21zby1sYXlvdXQtZ3JpZC1hbGlnbjpub25lO3RleHQtYXV0b3NwYWNlOm5vbmUn
+PjxzcGFuDQpzdHlsZT0nZm9udC1zaXplOjkuMHB0O2ZvbnQtZmFtaWx5OkNvdXJpZXI7bXNvLWJp
+ZGktZm9udC1mYW1pbHk6Q291cmllcjsNCmNvbG9yOmJsYWNrJz5PTiAmbHQ7c2VhcmNoIGNvbmRp
+dGlvbiZndDsgJmx0O21lcmdlIG9wZXJhdGlvbiBzcGVjaWZpY2F0aW9uJmd0OzxvOnA+PC9vOnA+
+PC9zcGFuPjwvcD4NCg0KPHAgY2xhc3M9TXNvTm9ybWFsIHN0eWxlPSdtc28tbGF5b3V0LWdyaWQt
+YWxpZ246bm9uZTt0ZXh0LWF1dG9zcGFjZTpub25lJz48c3Bhbg0Kc3R5bGU9J2ZvbnQtc2l6ZTo5
+LjBwdDtmb250LWZhbWlseTpDb3VyaWVyO21zby1iaWRpLWZvbnQtZmFtaWx5OkNvdXJpZXI7DQpj
+b2xvcjpibGFjayc+Jmx0OzxzcGFuIGNsYXNzPUdyYW1FPm1lcmdlPC9zcGFuPiBjb3JyZWxhdGlv
+biBuYW1lJmd0OyA6Oj0NCiZsdDtjb3JyZWxhdGlvbiBuYW1lJmd0OzxvOnA+PC9vOnA+PC9zcGFu
+PjwvcD4NCg0KPHAgY2xhc3M9TXNvTm9ybWFsIHN0eWxlPSdtc28tbGF5b3V0LWdyaWQtYWxpZ246
+bm9uZTt0ZXh0LWF1dG9zcGFjZTpub25lJz48c3Bhbg0Kc3R5bGU9J2ZvbnQtc2l6ZTo5LjBwdDtm
+b250LWZhbWlseTpDb3VyaWVyO21zby1iaWRpLWZvbnQtZmFtaWx5OkNvdXJpZXI7DQpjb2xvcjpi
+bGFjayc+Jmx0OzxzcGFuIGNsYXNzPUdyYW1FPm1lcmdlPC9zcGFuPiBvcGVyYXRpb24gc3BlY2lm
+aWNhdGlvbiZndDsgOjo9DQombHQ7bWVyZ2Ugd2hlbiBjbGF1c2UmZ3Q7Li4uPG86cD48L286cD48
+L3NwYW4+PC9wPg0KDQo8cCBjbGFzcz1Nc29Ob3JtYWwgc3R5bGU9J21zby1sYXlvdXQtZ3JpZC1h
+bGlnbjpub25lO3RleHQtYXV0b3NwYWNlOm5vbmUnPjxzcGFuDQpzdHlsZT0nZm9udC1zaXplOjku
+MHB0O2ZvbnQtZmFtaWx5OkNvdXJpZXI7bXNvLWJpZGktZm9udC1mYW1pbHk6Q291cmllcjsNCmNv
+bG9yOmJsYWNrJz4mbHQ7bWVyZ2Ugd2hlbiBjbGF1c2U8c3BhbiBjbGFzcz1HcmFtRT4mZ3Q7IDo8
+L3NwYW4+Oj08bzpwPjwvbzpwPjwvc3Bhbj48L3A+DQoNCjxwIGNsYXNzPU1zb05vcm1hbCBzdHls
+ZT0nbXNvLWxheW91dC1ncmlkLWFsaWduOm5vbmU7dGV4dC1hdXRvc3BhY2U6bm9uZSc+PHNwYW4N
+CnN0eWxlPSdmb250LXNpemU6OS4wcHQ7Zm9udC1mYW1pbHk6Q291cmllcjttc28tYmlkaS1mb250
+LWZhbWlseTpDb3VyaWVyOw0KY29sb3I6YmxhY2snPiZsdDttZXJnZSB3aGVuIG1hdGNoZWQgY2xh
+dXNlJmd0OzxvOnA+PC9vOnA+PC9zcGFuPjwvcD4NCg0KPHAgY2xhc3M9TXNvTm9ybWFsIHN0eWxl
+PSdtc28tbGF5b3V0LWdyaWQtYWxpZ246bm9uZTt0ZXh0LWF1dG9zcGFjZTpub25lJz48c3Bhbg0K
+c3R5bGU9J2ZvbnQtc2l6ZTo5LjBwdDtmb250LWZhbWlseTpDb3VyaWVyO21zby1iaWRpLWZvbnQt
+ZmFtaWx5OkNvdXJpZXI7DQpjb2xvcjpibGFjayc+fCAmbHQ7bWVyZ2Ugd2hlbiBub3QgbWF0Y2hl
+ZCBjbGF1c2UmZ3Q7PG86cD48L286cD48L3NwYW4+PC9wPg0KDQo8cCBjbGFzcz1Nc29Ob3JtYWwg
+c3R5bGU9J21zby1sYXlvdXQtZ3JpZC1hbGlnbjpub25lO3RleHQtYXV0b3NwYWNlOm5vbmUnPjxz
+cGFuDQpzdHlsZT0nZm9udC1zaXplOjkuMHB0O2ZvbnQtZmFtaWx5OkNvdXJpZXI7bXNvLWJpZGkt
+Zm9udC1mYW1pbHk6Q291cmllcjsNCmNvbG9yOmJsYWNrJz4mbHQ7bWVyZ2Ugd2hlbiBtYXRjaGVk
+IGNsYXVzZTxzcGFuIGNsYXNzPUdyYW1FPiZndDsgOjwvc3Bhbj46PTxvOnA+PC9vOnA+PC9zcGFu
+PjwvcD4NCg0KPHAgY2xhc3M9TXNvTm9ybWFsIHN0eWxlPSdtc28tbGF5b3V0LWdyaWQtYWxpZ246
+bm9uZTt0ZXh0LWF1dG9zcGFjZTpub25lJz48c3Bhbg0Kc3R5bGU9J2ZvbnQtc2l6ZTo5LjBwdDtm
+b250LWZhbWlseTpDb3VyaWVyO21zby1iaWRpLWZvbnQtZmFtaWx5OkNvdXJpZXI7DQpjb2xvcjpi
+bGFjayc+V0hFTiBNQVRDSEVEIFRIRU4gJmx0O21lcmdlIHVwZGF0ZSBzcGVjaWZpY2F0aW9uJmd0
+OzxvOnA+PC9vOnA+PC9zcGFuPjwvcD4NCg0KPHAgY2xhc3M9TXNvTm9ybWFsIHN0eWxlPSdtc28t
+bGF5b3V0LWdyaWQtYWxpZ246bm9uZTt0ZXh0LWF1dG9zcGFjZTpub25lJz48c3Bhbg0Kc3R5bGU9
+J2ZvbnQtc2l6ZTo5LjBwdDtmb250LWZhbWlseTpDb3VyaWVyO21zby1iaWRpLWZvbnQtZmFtaWx5
+OkNvdXJpZXI7DQpjb2xvcjpibGFjayc+Jmx0OzxzcGFuIGNsYXNzPUdyYW1FPm1lcmdlPC9zcGFu
+PiB3aGVuIG5vdCBtYXRjaGVkIGNsYXVzZSZndDsgOjo9PG86cD48L286cD48L3NwYW4+PC9wPg0K
+DQo8cCBjbGFzcz1Nc29Ob3JtYWwgc3R5bGU9J21zby1sYXlvdXQtZ3JpZC1hbGlnbjpub25lO3Rl
+eHQtYXV0b3NwYWNlOm5vbmUnPjxzcGFuDQpzdHlsZT0nZm9udC1zaXplOjkuMHB0O2ZvbnQtZmFt
+aWx5OkNvdXJpZXI7bXNvLWJpZGktZm9udC1mYW1pbHk6Q291cmllcjsNCmNvbG9yOmJsYWNrJz5X
+SEVOIE5PVCBNQVRDSEVEIFRIRU4gJmx0O21lcmdlIGluc2VydCBzcGVjaWZpY2F0aW9uJmd0Ozxv
+OnA+PC9vOnA+PC9zcGFuPjwvcD4NCg0KPHAgY2xhc3M9TXNvTm9ybWFsIHN0eWxlPSdtc28tbGF5
+b3V0LWdyaWQtYWxpZ246bm9uZTt0ZXh0LWF1dG9zcGFjZTpub25lJz48c3Bhbg0Kc3R5bGU9J2Zv
+bnQtc2l6ZTo5LjBwdDtmb250LWZhbWlseTpDb3VyaWVyO21zby1iaWRpLWZvbnQtZmFtaWx5OkNv
+dXJpZXI7DQpjb2xvcjpibGFjayc+Jmx0OzxzcGFuIGNsYXNzPUdyYW1FPm1lcmdlPC9zcGFuPiB1
+cGRhdGUgc3BlY2lmaWNhdGlvbiZndDsgOjo9DQpVUERBVEUgU0VUICZsdDtzZXQgY2xhdXNlIGxp
+c3QmZ3Q7PG86cD48L286cD48L3NwYW4+PC9wPg0KDQo8cCBjbGFzcz1Nc29Ob3JtYWwgc3R5bGU9
+J21zby1sYXlvdXQtZ3JpZC1hbGlnbjpub25lO3RleHQtYXV0b3NwYWNlOm5vbmUnPjxzcGFuDQpz
+dHlsZT0nZm9udC1zaXplOjkuMHB0O2ZvbnQtZmFtaWx5OkNvdXJpZXI7bXNvLWJpZGktZm9udC1m
+YW1pbHk6Q291cmllcjsNCmNvbG9yOmJsYWNrJz4mbHQ7PHNwYW4gY2xhc3M9R3JhbUU+bWVyZ2U8
+L3NwYW4+IGluc2VydCBzcGVjaWZpY2F0aW9uJmd0OyA6Oj08bzpwPjwvbzpwPjwvc3Bhbj48L3A+
+DQoNCjxwIGNsYXNzPU1zb05vcm1hbCBzdHlsZT0nbXNvLWxheW91dC1ncmlkLWFsaWduOm5vbmU7
+dGV4dC1hdXRvc3BhY2U6bm9uZSc+PHNwYW4NCnN0eWxlPSdmb250LXNpemU6OS4wcHQ7Zm9udC1m
+YW1pbHk6Q291cmllcjttc28tYmlkaS1mb250LWZhbWlseTpDb3VyaWVyOw0KY29sb3I6YmxhY2sn
+PklOU0VSVCA8c3BhbiBjbGFzcz1HcmFtRT5bICZsdDs8L3NwYW4+bGVmdCA8c3BhbiBjbGFzcz1T
+cGVsbEU+cGFyZW48L3NwYW4+Jmd0Ow0KJmx0O2luc2VydCBjb2x1bW4gbGlzdCZndDsgJmx0O3Jp
+Z2h0IDxzcGFuIGNsYXNzPVNwZWxsRT5wYXJlbjwvc3Bhbj4mZ3Q7IF08bzpwPjwvbzpwPjwvc3Bh
+bj48L3A+DQoNCjxwIGNsYXNzPU1zb05vcm1hbCBzdHlsZT0nbXNvLWxheW91dC1ncmlkLWFsaWdu
+Om5vbmU7dGV4dC1hdXRvc3BhY2U6bm9uZSc+PHNwYW4NCmNsYXNzPUdyYW1FPjxzcGFuIHN0eWxl
+PSdmb250LXNpemU6OS4wcHQ7Zm9udC1mYW1pbHk6Q291cmllcjttc28tYmlkaS1mb250LWZhbWls
+eToNCkNvdXJpZXI7Y29sb3I6YmxhY2snPlsgJmx0Ozwvc3Bhbj48L3NwYW4+PHNwYW4gc3R5bGU9
+J2ZvbnQtc2l6ZTo5LjBwdDsNCmZvbnQtZmFtaWx5OkNvdXJpZXI7bXNvLWJpZGktZm9udC1mYW1p
+bHk6Q291cmllcjtjb2xvcjpibGFjayc+b3ZlcnJpZGUNCmNsYXVzZSZndDsgXTxvOnA+PC9vOnA+
+PC9zcGFuPjwvcD4NCg0KPHAgY2xhc3M9TXNvTm9ybWFsIHN0eWxlPSdtc28tbGF5b3V0LWdyaWQt
+YWxpZ246bm9uZTt0ZXh0LWF1dG9zcGFjZTpub25lJz48c3Bhbg0Kc3R5bGU9J2ZvbnQtc2l6ZTo5
+LjBwdDtmb250LWZhbWlseTpDb3VyaWVyO21zby1iaWRpLWZvbnQtZmFtaWx5OkNvdXJpZXI7DQpj
+b2xvcjpibGFjayc+VkFMVUVTICZsdDttZXJnZSBpbnNlcnQgdmFsdWUgbGlzdCZndDs8bzpwPjwv
+bzpwPjwvc3Bhbj48L3A+DQoNCjxwIGNsYXNzPU1zb05vcm1hbCBzdHlsZT0nbXNvLWxheW91dC1n
+cmlkLWFsaWduOm5vbmU7dGV4dC1hdXRvc3BhY2U6bm9uZSc+PHNwYW4NCnN0eWxlPSdmb250LXNp
+emU6OS4wcHQ7Zm9udC1mYW1pbHk6Q291cmllcjttc28tYmlkaS1mb250LWZhbWlseTpDb3VyaWVy
+Ow0KY29sb3I6YmxhY2snPiZsdDs8c3BhbiBjbGFzcz1HcmFtRT5tZXJnZTwvc3Bhbj4gaW5zZXJ0
+IHZhbHVlIGxpc3QmZ3Q7IDo6PTxvOnA+PC9vOnA+PC9zcGFuPjwvcD4NCg0KPHAgY2xhc3M9TXNv
+Tm9ybWFsIHN0eWxlPSdtc28tbGF5b3V0LWdyaWQtYWxpZ246bm9uZTt0ZXh0LWF1dG9zcGFjZTpu
+b25lJz48c3Bhbg0Kc3R5bGU9J2ZvbnQtc2l6ZTo5LjBwdDtmb250LWZhbWlseTpDb3VyaWVyO21z
+by1iaWRpLWZvbnQtZmFtaWx5OkNvdXJpZXI7DQpjb2xvcjpibGFjayc+Jmx0OzxzcGFuIGNsYXNz
+PUdyYW1FPmxlZnQ8L3NwYW4+IDxzcGFuIGNsYXNzPVNwZWxsRT5wYXJlbjwvc3Bhbj4mZ3Q7PG86
+cD48L286cD48L3NwYW4+PC9wPg0KDQo8cCBjbGFzcz1Nc29Ob3JtYWwgc3R5bGU9J21zby1sYXlv
+dXQtZ3JpZC1hbGlnbjpub25lO3RleHQtYXV0b3NwYWNlOm5vbmUnPjxzcGFuDQpzdHlsZT0nZm9u
+dC1zaXplOjkuMHB0O2ZvbnQtZmFtaWx5OkNvdXJpZXI7bXNvLWJpZGktZm9udC1mYW1pbHk6Q291
+cmllcjsNCmNvbG9yOmJsYWNrJz4mbHQ7PHNwYW4gY2xhc3M9R3JhbUU+bWVyZ2U8L3NwYW4+IGlu
+c2VydCB2YWx1ZSBlbGVtZW50Jmd0OyBbIHsNCiZsdDtjb21tYSZndDsgJmx0O21lcmdlIGluc2Vy
+dCB2YWx1ZSBlbGVtZW50Jmd0OyB9Li4uIF08bzpwPjwvbzpwPjwvc3Bhbj48L3A+DQoNCjxwIGNs
+YXNzPU1zb05vcm1hbCBzdHlsZT0nbXNvLWxheW91dC1ncmlkLWFsaWduOm5vbmU7dGV4dC1hdXRv
+c3BhY2U6bm9uZSc+PHNwYW4NCnN0eWxlPSdmb250LXNpemU6OS4wcHQ7Zm9udC1mYW1pbHk6Q291
+cmllcjttc28tYmlkaS1mb250LWZhbWlseTpDb3VyaWVyOw0KY29sb3I6YmxhY2snPiZsdDs8c3Bh
+biBjbGFzcz1HcmFtRT5yaWdodDwvc3Bhbj4gPHNwYW4gY2xhc3M9U3BlbGxFPnBhcmVuPC9zcGFu
+PiZndDs8bzpwPjwvbzpwPjwvc3Bhbj48L3A+DQoNCjxwIGNsYXNzPU1zb05vcm1hbCBzdHlsZT0n
+bXNvLWxheW91dC1ncmlkLWFsaWduOm5vbmU7dGV4dC1hdXRvc3BhY2U6bm9uZSc+PHNwYW4NCnN0
+eWxlPSdmb250LXNpemU6OS4wcHQ7Zm9udC1mYW1pbHk6Q291cmllcjttc28tYmlkaS1mb250LWZh
+bWlseTpDb3VyaWVyOw0KY29sb3I6YmxhY2snPiZsdDs8c3BhbiBjbGFzcz1HcmFtRT5tZXJnZTwv
+c3Bhbj4gaW5zZXJ0IHZhbHVlIGVsZW1lbnQmZ3Q7IDo6PTxvOnA+PC9vOnA+PC9zcGFuPjwvcD4N
+Cg0KPHAgY2xhc3M9TXNvTm9ybWFsIHN0eWxlPSdtc28tbGF5b3V0LWdyaWQtYWxpZ246bm9uZTt0
+ZXh0LWF1dG9zcGFjZTpub25lJz48c3Bhbg0Kc3R5bGU9J2ZvbnQtc2l6ZTo5LjBwdDtmb250LWZh
+bWlseTpDb3VyaWVyO21zby1iaWRpLWZvbnQtZmFtaWx5OkNvdXJpZXI7DQpjb2xvcjpibGFjayc+
+Jmx0OzxzcGFuIGNsYXNzPUdyYW1FPnZhbHVlPC9zcGFuPiBleHByZXNzaW9uJmd0OzxvOnA+PC9v
+OnA+PC9zcGFuPjwvcD4NCg0KPHAgY2xhc3M9TXNvTm9ybWFsIHN0eWxlPSdtc28tbGF5b3V0LWdy
+aWQtYWxpZ246bm9uZTt0ZXh0LWF1dG9zcGFjZTpub25lJz48c3Bhbg0Kc3R5bGU9J2ZvbnQtc2l6
+ZTo5LjBwdDtmb250LWZhbWlseTpDb3VyaWVyO21zby1iaWRpLWZvbnQtZmFtaWx5OkNvdXJpZXI7
+DQpjb2xvcjpibGFjayc+fCAmbHQ7Y29udGV4dHVhbGx5IHR5cGVkIHZhbHVlIHNwZWNpZmljYXRp
+b24mZ3Q7PG86cD48L286cD48L3NwYW4+PC9wPg0KDQo8cCBjbGFzcz1Nc29Ob3JtYWwgc3R5bGU9
+J21zby1sYXlvdXQtZ3JpZC1hbGlnbjpub25lO3RleHQtYXV0b3NwYWNlOm5vbmUnPjxiPjxzcGFu
+DQpzdHlsZT0nZm9udC1zaXplOjE0LjBwdDtjb2xvcjpibGFjayc+U3ludGF4IFJ1bGVzPG86cD48
+L286cD48L3NwYW4+PC9iPjwvcD4NCg0KPHAgY2xhc3M9TXNvTm9ybWFsIHN0eWxlPSdtc28tbGF5
+b3V0LWdyaWQtYWxpZ246bm9uZTt0ZXh0LWF1dG9zcGFjZTpub25lJz48c3Bhbg0Kc3R5bGU9J2Zv
+bnQtc2l6ZToxMS4wcHQ7Y29sb3I6YmxhY2snPjEpIE5laXRoZXIgJmx0O21lcmdlIHdoZW4gbWF0
+Y2hlZA0KY2xhdXNlJmd0OyBub3IgJmx0O21lcmdlIHdoZW4gbm90IG1hdGNoZWQgY2xhdXNlJmd0
+OyBzaGFsbCBiZSBzcGVjaWZpZWQgbW9yZQ0KdGhhbiBvbmNlLjxvOnA+PC9vOnA+PC9zcGFuPjwv
+cD4NCg0KPHAgY2xhc3M9TXNvTm9ybWFsIHN0eWxlPSdtc28tbGF5b3V0LWdyaWQtYWxpZ246bm9u
+ZTt0ZXh0LWF1dG9zcGFjZTpub25lJz48c3Bhbg0Kc3R5bGU9J2ZvbnQtc2l6ZToxMS4wcHQ7Y29s
+b3I6YmxhY2snPjIpIExldCA8aT5UTiA8L2k+YmUgdGhlICZsdDt0YWJsZSBuYW1lJmd0Ow0KY29u
+dGFpbmVkIGluICZsdDt0YXJnZXQgdGFibGUmZ3Q7IGFuZCBsZXQgPGk+VCA8L2k+YmUgdGhlIHRh
+YmxlIGlkZW50aWZpZWQgYnkgPGk+VE48L2k+Lg0KPGk+VCA8L2k+aXMgdGhlIDxpPnN1YmplY3Qg
+dGFibGUgPC9pPm9mIHRoZSAmbHQ7bWVyZ2Ugc3RhdGVtZW50Jmd0Oy48bzpwPjwvbzpwPjwvc3Bh
+bj48L3A+DQoNCjxwIGNsYXNzPU1zb05vcm1hbCBzdHlsZT0nbXNvLWxheW91dC1ncmlkLWFsaWdu
+Om5vbmU7dGV4dC1hdXRvc3BhY2U6bm9uZSc+PHNwYW4NCnN0eWxlPSdmb250LXNpemU6MTEuMHB0
+O2NvbG9yOmJsYWNrJz4zKSA8aT5UIDwvaT5zaGFsbCBiZSA8c3BhbiBjbGFzcz1TcGVsbEU+aW5z
+ZXJ0YWJsZTwvc3Bhbj4taW50by48bzpwPjwvbzpwPjwvc3Bhbj48L3A+DQoNCjxwIGNsYXNzPU1z
+b05vcm1hbCBzdHlsZT0nbXNvLWxheW91dC1ncmlkLWFsaWduOm5vbmU7dGV4dC1hdXRvc3BhY2U6
+bm9uZSc+PHNwYW4NCnN0eWxlPSdmb250LXNpemU6MTEuMHB0O2NvbG9yOmJsYWNrJz40KSA8aT5U
+IDwvaT5zaGFsbCBub3QgYmUgYW4gb2xkIHRyYW5zaXRpb24NCnRhYmxlIG9yIGEgbmV3IHRyYW5z
+aXRpb24gdGFibGUuPG86cD48L286cD48L3NwYW4+PC9wPg0KDQo8cCBjbGFzcz1Nc29Ob3JtYWwg
+c3R5bGU9J21zby1sYXlvdXQtZ3JpZC1hbGlnbjpub25lO3RleHQtYXV0b3NwYWNlOm5vbmUnPjxi
+PjxzcGFuDQpzdHlsZT0nZm9udC1zaXplOjEwLjBwdDtjb2xvcjpibGFjayc+RGF0YSBtYW5pcHVs
+YXRpb24gODA1PG86cD48L286cD48L3NwYW4+PC9iPjwvcD4NCg0KPHAgY2xhc3M9TXNvTm9ybWFs
+IHN0eWxlPSdtc28tbGF5b3V0LWdyaWQtYWxpZ246bm9uZTt0ZXh0LWF1dG9zcGFjZTpub25lJz48
+Yj48c3Bhbg0Kc3R5bGU9J2ZvbnQtc2l6ZToxMC4wcHQ7Y29sb3I6YmxhY2snPldEIElTTy9JRUMg
+OTA3NS0yOjIwMDcgKEUpPG86cD48L286cD48L3NwYW4+PC9iPjwvcD4NCg0KPHAgY2xhc3M9TXNv
+Tm9ybWFsIHN0eWxlPSdtc28tbGF5b3V0LWdyaWQtYWxpZ246bm9uZTt0ZXh0LWF1dG9zcGFjZTpu
+b25lJz48Yj48c3Bhbg0Kc3R5bGU9J2ZvbnQtc2l6ZToxMC4wcHQ7Y29sb3I6YmxhY2snPjE0Ljkg
+Jmx0O21lcmdlIHN0YXRlbWVudCZndDs8bzpwPjwvbzpwPjwvc3Bhbj48L2I+PC9wPg0KDQo8cCBj
+bGFzcz1Nc29Ob3JtYWwgc3R5bGU9J21zby1sYXlvdXQtZ3JpZC1hbGlnbjpub25lO3RleHQtYXV0
+b3NwYWNlOm5vbmUnPjxzcGFuDQpzdHlsZT0nZm9udC1zaXplOjExLjBwdDtjb2xvcjpibGFjayc+
+NSkgRm9yIGVhY2ggbGVhZiBnZW5lcmFsbHkgdW5kZXJseWluZw0KdGFibGUgb2YgPGk+VCA8L2k+
+d2hvc2UgZGVzY3JpcHRvciBpbmNsdWRlcyBhIHVzZXItZGVmaW5lZCB0eXBlIG5hbWUgPGk+VURU
+TjwvaT4sDQp0aGUgZGF0YSB0eXBlIGRlc2NyaXB0b3Igb2YgdGhlIHVzZXItZGVmaW5lZCB0eXBl
+IDxpPlVEVCA8L2k+aWRlbnRpZmllZCBieSA8aT5VRFRODQo8L2k+c2hhbGwgaW5kaWNhdGUgdGhh
+dCA8aT5VRFQgPC9pPmlzIDxzcGFuIGNsYXNzPVNwZWxsRT5pbnN0YW50aWFibGU8L3NwYW4+Ljxv
+OnA+PC9vOnA+PC9zcGFuPjwvcD4NCg0KPHAgY2xhc3M9TXNvTm9ybWFsIHN0eWxlPSdtc28tbGF5
+b3V0LWdyaWQtYWxpZ246bm9uZTt0ZXh0LWF1dG9zcGFjZTpub25lJz48c3Bhbg0Kc3R5bGU9J2Zv
+bnQtc2l6ZToxMS4wcHQ7Y29sb3I6YmxhY2snPjYpIElmIDxpPlQgPC9pPmlzIGEgdmlldywgdGhl
+biAmbHQ7dGFyZ2V0DQp0YWJsZSZndDsgaXMgZWZmZWN0aXZlbHkgcmVwbGFjZWQgYnk6PG86cD48
+L286cD48L3NwYW4+PC9wPg0KDQo8cCBjbGFzcz1Nc29Ob3JtYWwgc3R5bGU9J21zby1sYXlvdXQt
+Z3JpZC1hbGlnbjpub25lO3RleHQtYXV0b3NwYWNlOm5vbmUnPjxzcGFuDQpzdHlsZT0nZm9udC1z
+aXplOjkuMHB0O2ZvbnQtZmFtaWx5OkNvdXJpZXI7bXNvLWJpZGktZm9udC1mYW1pbHk6Q291cmll
+cjsNCmNvbG9yOmJsYWNrJz5PTkxZIDxzcGFuIGNsYXNzPUdyYW1FPiggPGk+VE48L2k+PC9zcGFu
+PjxpPiA8L2k+KTxvOnA+PC9vOnA+PC9zcGFuPjwvcD4NCg0KPHAgY2xhc3M9TXNvTm9ybWFsIHN0
+eWxlPSdtc28tbGF5b3V0LWdyaWQtYWxpZ246bm9uZTt0ZXh0LWF1dG9zcGFjZTpub25lJz48c3Bh
+bg0Kc3R5bGU9J2ZvbnQtc2l6ZToxMS4wcHQ7Y29sb3I6YmxhY2snPjcpIENhc2U6PG86cD48L286
+cD48L3NwYW4+PC9wPg0KDQo8cCBjbGFzcz1Nc29Ob3JtYWwgc3R5bGU9J21zby1sYXlvdXQtZ3Jp
+ZC1hbGlnbjpub25lO3RleHQtYXV0b3NwYWNlOm5vbmUnPjxzcGFuDQpzdHlsZT0nZm9udC1zaXpl
+OjExLjBwdDtjb2xvcjpibGFjayc+YSkgSWYgJmx0O21lcmdlIGNvcnJlbGF0aW9uIG5hbWUmZ3Q7
+IGlzDQpzcGVjaWZpZWQsIHRoZW4gbGV0IDxpPkNOIDwvaT5iZSB0aGUgJmx0O2NvcnJlbGF0aW9u
+IG5hbWUmZ3Q7IGNvbnRhaW5lZCBpbg0KJmx0O21lcmdlIGNvcnJlbGF0aW9uIG5hbWUmZ3Q7Ljxv
+OnA+PC9vOnA+PC9zcGFuPjwvcD4NCg0KPHAgY2xhc3M9TXNvTm9ybWFsIHN0eWxlPSdtc28tbGF5
+b3V0LWdyaWQtYWxpZ246bm9uZTt0ZXh0LWF1dG9zcGFjZTpub25lJz48c3Bhbg0Kc3R5bGU9J2Zv
+bnQtc2l6ZToxMS4wcHQ7Y29sb3I6YmxhY2snPmIpIE90aGVyd2lzZSwgbGV0IDxpPkNOIDwvaT5i
+ZSB0aGUNCiZsdDt0YWJsZSBuYW1lJmd0OyBjb250YWluZWQgaW4gJmx0O3RhcmdldCB0YWJsZSZn
+dDsuPG86cD48L286cD48L3NwYW4+PC9wPg0KDQo8cCBjbGFzcz1Nc29Ob3JtYWwgc3R5bGU9J21z
+by1sYXlvdXQtZ3JpZC1hbGlnbjpub25lO3RleHQtYXV0b3NwYWNlOm5vbmUnPjxzcGFuDQpzdHls
+ZT0nZm9udC1zaXplOjExLjBwdDtjb2xvcjpibGFjayc+OCkgVGhlIHNjb3BlIG9mIDxpPkNOIDwv
+aT5pcyAmbHQ7c2VhcmNoDQpjb25kaXRpb24mZ3Q7IGFuZCAmbHQ7c2V0IGNsYXVzZSBsaXN0Jmd0
+Oy48bzpwPjwvbzpwPjwvc3Bhbj48L3A+DQoNCjxwIGNsYXNzPU1zb05vcm1hbCBzdHlsZT0nbXNv
+LWxheW91dC1ncmlkLWFsaWduOm5vbmU7dGV4dC1hdXRvc3BhY2U6bm9uZSc+PHNwYW4NCnN0eWxl
+PSdmb250LXNpemU6MTEuMHB0O2NvbG9yOmJsYWNrJz45KSBMZXQgPGk+VFIgPC9pPmJlIHRoZSAm
+bHQ7dGFibGUNCnJlZmVyZW5jZSZndDsgaW1tZWRpYXRlbHkgY29udGFpbmVkIGluICZsdDttZXJn
+ZSBzdGF0ZW1lbnQmZ3Q7LiA8aT5UUiA8L2k+c2hhbGwNCm5vdCBkaXJlY3RseSBjb250YWluIGEg
+Jmx0O2pvaW5lZCB0YWJsZSZndDsuPG86cD48L286cD48L3NwYW4+PC9wPg0KDQo8cCBjbGFzcz1N
+c29Ob3JtYWwgc3R5bGU9J21zby1sYXlvdXQtZ3JpZC1hbGlnbjpub25lO3RleHQtYXV0b3NwYWNl
+Om5vbmUnPjxzcGFuDQpzdHlsZT0nZm9udC1zaXplOjExLjBwdDtjb2xvcjpibGFjayc+MTApIFRo
+ZSAmbHQ7Y29ycmVsYXRpb24gbmFtZSZndDsgb3INCmV4cG9zZWQgJmx0O3RhYmxlIG5hbWUmZ3Q7
+IHRoYXQgaXMgZXhwb3NlZCBieSA8aT5UUiA8L2k+c2hhbGwgbm90IGJlIGVxdWl2YWxlbnQNCnRv
+IDxpPkNOPC9pPi48bzpwPjwvbzpwPjwvc3Bhbj48L3A+DQoNCjxwIGNsYXNzPU1zb05vcm1hbCBz
+dHlsZT0nbXNvLWxheW91dC1ncmlkLWFsaWduOm5vbmU7dGV4dC1hdXRvc3BhY2U6bm9uZSc+PHNw
+YW4NCnN0eWxlPSdmb250LXNpemU6MTEuMHB0O2NvbG9yOmJsYWNrJz4xMSkgSWYgdGhlICZsdDtp
+bnNlcnQgY29sdW1uIGxpc3QmZ3Q7IGlzDQpvbWl0dGVkLCB0aGVuIGFuICZsdDtpbnNlcnQgY29s
+dW1uIGxpc3QmZ3Q7IHRoYXQgaWRlbnRpZmllcyBhbGwgY29sdW1ucyBvZiA8aT5UDQo8L2k+aW4g
+dGhlIGFzY2VuZGluZyBzZXF1ZW5jZSBvZiB0aGVpciBvcmRpbmFsIHBvc2l0aW9uIHdpdGhpbiA8
+aT5UIDwvaT5pcw0KaW1wbGljaXQuPG86cD48L286cD48L3NwYW4+PC9wPg0KDQo8cCBjbGFzcz1N
+c29Ob3JtYWwgc3R5bGU9J21zby1sYXlvdXQtZ3JpZC1hbGlnbjpub25lO3RleHQtYXV0b3NwYWNl
+Om5vbmUnPjxzcGFuDQpzdHlsZT0nZm9udC1zaXplOjExLjBwdDtjb2xvcjpibGFjayc+MTIpIENh
+c2U6PG86cD48L286cD48L3NwYW4+PC9wPg0KDQo8cCBjbGFzcz1Nc29Ob3JtYWwgc3R5bGU9J21z
+by1sYXlvdXQtZ3JpZC1hbGlnbjpub25lO3RleHQtYXV0b3NwYWNlOm5vbmUnPjxzcGFuDQpzdHls
+ZT0nZm9udC1zaXplOjExLjBwdDtjb2xvcjpibGFjayc+YSkgSWYgPGk+VCA8L2k+aXMgYSA8c3Bh
+biBjbGFzcz1TcGVsbEU+cmVmZXJlbmNlYWJsZTwvc3Bhbj4NCnRhYmxlIG9yIGEgdGFibGUgaGF2
+aW5nIGFuIGlkZW50aXR5IGNvbHVtbiB3aG9zZSBkZXNjcmlwdG9yIGluY2x1ZGVzIGFuDQppbmRp
+Y2F0aW9uIHRoYXQgdmFsdWVzIGFyZSBhbHdheXMgZ2VuZXJhdGVkLCB0aGVuOjxvOnA+PC9vOnA+
+PC9zcGFuPjwvcD4NCg0KPHAgY2xhc3M9TXNvTm9ybWFsIHN0eWxlPSdtc28tbGF5b3V0LWdyaWQt
+YWxpZ246bm9uZTt0ZXh0LWF1dG9zcGFjZTpub25lJz48c3Bhbg0KY2xhc3M9U3BlbGxFPjxzcGFu
+IHN0eWxlPSdmb250LXNpemU6MTEuMHB0O2NvbG9yOmJsYWNrJz5pPC9zcGFuPjwvc3Bhbj48c3Bh
+bg0Kc3R5bGU9J2ZvbnQtc2l6ZToxMS4wcHQ7Y29sb3I6YmxhY2snPikgTGV0IDxpPkMgPC9pPmJl
+IHRoZSBzZWxmLXJlZmVyZW5jaW5nDQpjb2x1bW4gb3IgaWRlbnRpdHkgY29sdW1uIG9mIDxpPlQ8
+L2k+LjxvOnA+PC9vOnA+PC9zcGFuPjwvcD4NCg0KPHAgY2xhc3M9TXNvTm9ybWFsIHN0eWxlPSdt
+c28tbGF5b3V0LWdyaWQtYWxpZ246bm9uZTt0ZXh0LWF1dG9zcGFjZTpub25lJz48c3Bhbg0Kc3R5
+bGU9J2ZvbnQtc2l6ZToxMS4wcHQ7Y29sb3I6YmxhY2snPmlpKSBJZiA8aT5DIDwvaT5pcyBhbiBp
+ZGVudGl0eSBjb2x1bW4sIGENCnN5c3RlbS1nZW5lcmF0ZWQgc2VsZi1yZWZlcmVuY2luZyBjb2x1
+bW4gb3IgYSBkZXJpdmVkIHNlbGYtcmVmZXJlbmNpbmcgY29sdW1uDQphbmQgPGk+QyA8L2k+aXMg
+Y29udGFpbmVkIGluICZsdDtpbnNlcnQgY29sdW1uIGxpc3QmZ3Q7LCB0aGVuICZsdDtvdmVycmlk
+ZQ0KY2xhdXNlJmd0OyBzaGFsbCBiZSBzcGVjaWZpZWQ7IG90aGVyd2lzZSwgJmx0O292ZXJyaWRl
+IGNsYXVzZSZndDsgc2hhbGwgbm90IGJlDQpzcGVjaWZpZWQuPG86cD48L286cD48L3NwYW4+PC9w
+Pg0KDQo8cCBjbGFzcz1Nc29Ob3JtYWwgc3R5bGU9J21zby1sYXlvdXQtZ3JpZC1hbGlnbjpub25l
+O3RleHQtYXV0b3NwYWNlOm5vbmUnPjxzcGFuDQpjbGFzcz1HcmFtRT48c3BhbiBzdHlsZT0nZm9u
+dC1zaXplOjExLjBwdDtjb2xvcjpibGFjayc+Yjwvc3Bhbj48L3NwYW4+PHNwYW4NCnN0eWxlPSdm
+b250LXNpemU6MTEuMHB0O2NvbG9yOmJsYWNrJz4pIE90aGVyd2lzZSwgJmx0O292ZXJyaWRlIGNs
+YXVzZSZndDsgc2hhbGwNCm5vdCBiZSBzcGVjaWZpZWQuPG86cD48L286cD48L3NwYW4+PC9wPg0K
+DQo8cCBjbGFzcz1Nc29Ob3JtYWwgc3R5bGU9J21zby1sYXlvdXQtZ3JpZC1hbGlnbjpub25lO3Rl
+eHQtYXV0b3NwYWNlOm5vbmUnPjxzcGFuDQpzdHlsZT0nZm9udC1zaXplOjExLjBwdDtjb2xvcjpi
+bGFjayc+MTMpIFRoZSAmbHQ7c2VhcmNoIGNvbmRpdGlvbiZndDsgc2hhbGwgbm90DQpnZW5lcmFs
+bHkgY29udGFpbiBhICZsdDtyb3V0aW5lIGludm9jYXRpb24mZ3Q7IHdob3NlIHN1YmplY3Qgcm91
+dGluZSBpcyBhIDxzcGFuDQpjbGFzcz1TcGVsbEU+U1FMaW52b2tlZDwvc3Bhbj4gcm91dGluZSB0
+aGF0IHBvc3NpYmx5IG1vZGlmaWVzIFNRTC1kYXRhLjxvOnA+PC9vOnA+PC9zcGFuPjwvcD4NCg0K
+PHAgY2xhc3M9TXNvTm9ybWFsIHN0eWxlPSdtc28tbGF5b3V0LWdyaWQtYWxpZ246bm9uZTt0ZXh0
+LWF1dG9zcGFjZTpub25lJz48c3Bhbg0Kc3R5bGU9J2ZvbnQtc2l6ZToxMS4wcHQ7Y29sb3I6Ymxh
+Y2snPjE0KSBFYWNoIGNvbHVtbiBpZGVudGlmaWVkIGJ5IGFuDQombHQ7b2JqZWN0IGNvbHVtbiZn
+dDsgaW4gdGhlICZsdDtzZXQgY2xhdXNlIGxpc3QmZ3Q7IGlzIGFuIDxpPnVwZGF0ZSBvYmplY3QN
+CmNvbHVtbjwvaT4uIEVhY2ggY29sdW1uIGlkZW50aWZpZWQgYnkgYSAmbHQ7Y29sdW1uIG5hbWUm
+Z3Q7IGluIHRoZSBpbXBsaWNpdCBvcg0KZXhwbGljaXQgJmx0O2luc2VydCBjb2x1bW4gbGlzdCZn
+dDsgaXMgYW4gPGk+aW5zZXJ0IG9iamVjdCBjb2x1bW48L2k+LiBFYWNoDQp1cGRhdGUgb2JqZWN0
+IGNvbHVtbiBhbmQgZWFjaCBpbnNlcnQgb2JqZWN0IGNvbHVtbiBpcyBhbiA8aT5vYmplY3QgY29s
+dW1uPC9pPi48bzpwPjwvbzpwPjwvc3Bhbj48L3A+DQoNCjxwIGNsYXNzPU1zb05vcm1hbCBzdHls
+ZT0nbXNvLWxheW91dC1ncmlkLWFsaWduOm5vbmU7dGV4dC1hdXRvc3BhY2U6bm9uZSc+PHNwYW4N
+CnN0eWxlPSdmb250LXNpemU6MTEuMHB0O2NvbG9yOmJsYWNrJz4xNSkgRXZlcnkgb2JqZWN0IGNv
+bHVtbiBzaGFsbCBpZGVudGlmeSBhbg0KdXBkYXRhYmxlIGNvbHVtbiBvZiA8aT5UPC9pPi48bzpw
+PjwvbzpwPjwvc3Bhbj48L3A+DQoNCjxwIGNsYXNzPU1zb05vcm1hbCBzdHlsZT0nbXNvLWxheW91
+dC1ncmlkLWFsaWduOm5vbmU7dGV4dC1hdXRvc3BhY2U6bm9uZSc+PHNwYW4NCnN0eWxlPSdmb250
+LXNpemU6OS4wcHQ7Y29sb3I6YmxhY2snPk5PVEUgMzc5IJcgPHNwYW4gY2xhc3M9R3JhbUU+VGhl
+PC9zcGFuPg0Kbm90aW9uIG9mIHVwZGF0YWJsZSBjb2x1bW5zIG9mIGJhc2UgdGFibGVzIGlzIGRl
+ZmluZWQgaW4gPC9zcGFuPjxzcGFuDQpjbGFzcz1TcGVsbEU+PHNwYW4gc3R5bGU9J2ZvbnQtc2l6
+ZTo5LjBwdDtjb2xvcjojMDAwMDcwJz5TdWJjbGF1c2U8L3NwYW4+PC9zcGFuPjxzcGFuDQpzdHls
+ZT0nZm9udC1zaXplOjkuMHB0O2NvbG9yOiMwMDAwNzAnPiA0LjE0LCCTVGFibGVzlDwvc3Bhbj48
+c3Bhbg0Kc3R5bGU9J2ZvbnQtc2l6ZTo5LjBwdDtjb2xvcjpibGFjayc+LiBUaGUgbm90aW9uIG9m
+IHVwZGF0YWJsZSBjb2x1bW5zIG9mIHZpZXdlZA0KdGFibGVzIGlzIGRlZmluZWQgaW4gPC9zcGFu
+PjxzcGFuIGNsYXNzPVNwZWxsRT48c3BhbiBzdHlsZT0nZm9udC1zaXplOjkuMHB0Ow0KY29sb3I6
+IzAwMDA3MCc+U3ViY2xhdXNlPC9zcGFuPjwvc3Bhbj48c3BhbiBzdHlsZT0nZm9udC1zaXplOjku
+MHB0O2NvbG9yOiMwMDAwNzAnPg0KMTEuMjIsIJMmbHQ7dmlldyBkZWZpbml0aW9uJmd0O5Q8L3Nw
+YW4+PHNwYW4gc3R5bGU9J2ZvbnQtc2l6ZTo5LjBwdDtjb2xvcjpibGFjayc+LjxvOnA+PC9vOnA+
+PC9zcGFuPjwvcD4NCg0KPHAgY2xhc3M9TXNvTm9ybWFsIHN0eWxlPSdtc28tbGF5b3V0LWdyaWQt
+YWxpZ246bm9uZTt0ZXh0LWF1dG9zcGFjZTpub25lJz48c3Bhbg0Kc3R5bGU9J2ZvbnQtc2l6ZTox
+MS4wcHQ7Y29sb3I6YmxhY2snPjE2KSBObyAmbHQ7Y29sdW1uIG5hbWUmZ3Q7IG9mIDxpPlQgPC9p
+PnNoYWxsDQpiZSBpZGVudGlmaWVkIG1vcmUgdGhhbiBvbmNlIGluIDxzcGFuIGNsYXNzPVNwZWxs
+RT5pbjwvc3Bhbj4gYW4gJmx0O2luc2VydA0KY29sdW1uIGxpc3QmZ3Q7LjxvOnA+PC9vOnA+PC9z
+cGFuPjwvcD4NCg0KPHAgY2xhc3M9TXNvTm9ybWFsIHN0eWxlPSdtc28tbGF5b3V0LWdyaWQtYWxp
+Z246bm9uZTt0ZXh0LWF1dG9zcGFjZTpub25lJz48c3Bhbg0Kc3R5bGU9J2ZvbnQtc2l6ZToxMS4w
+cHQ7Y29sb3I6YmxhY2snPjE3KSBMZXQgPGk+TkkgPC9pPmJlIHRoZSBudW1iZXIgb2YNCiZsdDtt
+ZXJnZSBpbnNlcnQgdmFsdWUgZWxlbWVudCZndDtzIGNvbnRhaW5lZCBpbiAmbHQ7bWVyZ2UgaW5z
+ZXJ0IHZhbHVlDQpsaXN0Jmd0Oy4gTGV0IDxpPkVYUDwvaT48L3NwYW4+PHNwYW4gc3R5bGU9J2Zv
+bnQtc2l6ZTo5LjBwdDtjb2xvcjpibGFjayc+MTwvc3Bhbj48c3Bhbg0Kc3R5bGU9J2ZvbnQtc2l6
+ZToxMS4wcHQ7Y29sb3I6YmxhY2snPiwgPGk+RVhQPC9pPjwvc3Bhbj48c3BhbiBzdHlsZT0nZm9u
+dC1zaXplOg0KOS4wcHQ7Y29sb3I6YmxhY2snPjI8L3NwYW4+PHNwYW4gc3R5bGU9J2ZvbnQtc2l6
+ZToxMS4wcHQ7Y29sb3I6YmxhY2snPiwgPHNwYW4NCmNsYXNzPUdyYW1FPi4uLiAsPC9zcGFuPiA8
+aT5FWFA8L2k+PC9zcGFuPjxpPjxzcGFuIHN0eWxlPSdmb250LXNpemU6OS4wcHQ7DQpjb2xvcjpi
+bGFjayc+TkkgPC9zcGFuPjwvaT48c3BhbiBzdHlsZT0nZm9udC1zaXplOjExLjBwdDtjb2xvcjpi
+bGFjayc+YmUgdGhvc2UNCiZsdDttZXJnZSBpbnNlcnQgdmFsdWUgZWxlbWVudCZndDtzLjxvOnA+
+PC9vOnA+PC9zcGFuPjwvcD4NCg0KPHAgY2xhc3M9TXNvTm9ybWFsIHN0eWxlPSdtc28tbGF5b3V0
+LWdyaWQtYWxpZ246bm9uZTt0ZXh0LWF1dG9zcGFjZTpub25lJz48c3Bhbg0Kc3R5bGU9J2ZvbnQt
+c2l6ZToxMS4wcHQ7Y29sb3I6YmxhY2snPjE4KSBUaGUgbnVtYmVyIG9mICZsdDtjb2x1bW4gbmFt
+ZSZndDtzIGluDQp0aGUgJmx0O2luc2VydCBjb2x1bW4gbGlzdCZndDsgc2hhbGwgYmUgZXF1YWwg
+dG8gPGk+Tkk8L2k+LjxvOnA+PC9vOnA+PC9zcGFuPjwvcD4NCg0KPHAgY2xhc3M9TXNvTm9ybWFs
+IHN0eWxlPSdtc28tbGF5b3V0LWdyaWQtYWxpZ246bm9uZTt0ZXh0LWF1dG9zcGFjZTpub25lJz48
+c3Bhbg0Kc3R5bGU9J2ZvbnQtc2l6ZToxMS4wcHQ7Y29sb3I6YmxhY2snPjE5KSBUaGUgZGVjbGFy
+ZWQgdHlwZSBvZiBldmVyeQ0KJmx0O2NvbnRleHR1YWxseSB0eXBlZCB2YWx1ZSBzcGVjaWZpY2F0
+aW9uJmd0OyA8aT5DVlMgPC9pPmluIGEgJmx0O21lcmdlIGluc2VydA0KdmFsdWUgbGlzdCZndDsg
+aXMgdGhlIGRhdGEgdHlwZSA8aT5EVCA8L2k+aW5kaWNhdGVkIGluIHRoZSBjb2x1bW4gZGVzY3Jp
+cHRvcg0KZm9yIHRoZSA8c3BhbiBjbGFzcz1TcGVsbEU+cG9zaXRpb25hbGx5PC9zcGFuPiBjb3Jy
+ZXNwb25kaW5nIGNvbHVtbiBpbiB0aGUNCmV4cGxpY2l0IG9yIGltcGxpY2l0ICZsdDtpbnNlcnQg
+Y29sdW1uIGxpc3QmZ3Q7LiBJZiA8aT5DVlMgPC9pPmlzIGFuICZsdDtlbXB0eQ0Kc3BlY2lmaWNh
+dGlvbiZndDsgdGhhdCBzcGVjaWZpZXMgQVJSQVksIHRoZW4gPGk+RFQgPC9pPnNoYWxsIGJlIGFu
+IGFycmF5IHR5cGUuDQpJZiA8aT5DVlMgPC9pPmlzIGFuICZsdDtlbXB0eSBzcGVjaWZpY2F0aW9u
+Jmd0OyB0aGF0IHNwZWNpZmllcyBNVUxUSVNFVCwgdGhlbiA8aT5EVA0KPC9pPnNoYWxsIGJlIGEg
+PHNwYW4gY2xhc3M9U3BlbGxFPm11bHRpc2V0PC9zcGFuPiB0eXBlLjxvOnA+PC9vOnA+PC9zcGFu
+PjwvcD4NCg0KPHAgY2xhc3M9TXNvTm9ybWFsIHN0eWxlPSdtc28tbGF5b3V0LWdyaWQtYWxpZ246
+bm9uZTt0ZXh0LWF1dG9zcGFjZTpub25lJz48c3Bhbg0Kc3R5bGU9J2ZvbnQtc2l6ZToxMS4wcHQ7
+Y29sb3I6YmxhY2snPjIwKSBFdmVyeSAmbHQ7bWVyZ2UgaW5zZXJ0IHZhbHVlDQplbGVtZW50Jmd0
+OyB3aG9zZSA8c3BhbiBjbGFzcz1TcGVsbEU+cG9zaXRpb25hbGx5PC9zcGFuPiBjb3JyZXNwb25k
+aW5nDQombHQ7Y29sdW1uIG5hbWUmZ3Q7IGluICZsdDtpbnNlcnQgY29sdW1uIGxpc3QmZ3Q7IHJl
+ZmVyZW5jZXMgYSBjb2x1bW4gb2Ygd2hpY2gNCnNvbWUgdW5kZXJseWluZyBjb2x1bW4gaXMgYSBn
+ZW5lcmF0ZWQgY29sdW1uIHNoYWxsIGJlIGEgJmx0O2RlZmF1bHQgc3BlY2lmaWNhdGlvbiZndDsu
+PG86cD48L286cD48L3NwYW4+PC9wPg0KDQo8cCBjbGFzcz1Nc29Ob3JtYWwgc3R5bGU9J21zby1s
+YXlvdXQtZ3JpZC1hbGlnbjpub25lO3RleHQtYXV0b3NwYWNlOm5vbmUnPjxzcGFuDQpzdHlsZT0n
+Zm9udC1zaXplOjExLjBwdDtjb2xvcjpibGFjayc+MjEpIEZvciAxIChvbmUpIDwvc3Bhbj48c3Bh
+bg0Kc3R5bGU9J2ZvbnQtc2l6ZToxMS4wcHQ7Zm9udC1mYW1pbHk6U3ltYm9sO21zby1iaWRpLWZv
+bnQtZmFtaWx5OlN5bWJvbDsNCmNvbG9yOmJsYWNrJz4mIzg4MDQ7IDwvc3Bhbj48c3BhbiBjbGFz
+cz1TcGVsbEU+PGk+PHNwYW4gc3R5bGU9J2ZvbnQtc2l6ZToxMS4wcHQ7DQpjb2xvcjpibGFjayc+
+aTwvc3Bhbj48L2k+PC9zcGFuPjxpPjxzcGFuIHN0eWxlPSdmb250LXNpemU6MTEuMHB0O2NvbG9y
+OmJsYWNrJz4NCk5JPC9zcGFuPjwvaT48c3BhbiBzdHlsZT0nZm9udC1zaXplOjExLjBwdDtjb2xv
+cjpibGFjayc+LCB0aGUgU3ludGF4IFJ1bGVzIG9mIDwvc3Bhbj48c3Bhbg0KY2xhc3M9U3BlbGxF
+PjxzcGFuIHN0eWxlPSdmb250LXNpemU6MTEuMHB0O2NvbG9yOiMwMDAwNzAnPlN1YmNsYXVzZTwv
+c3Bhbj48L3NwYW4+PHNwYW4NCnN0eWxlPSdmb250LXNpemU6MTEuMHB0O2NvbG9yOiMwMDAwNzAn
+PiA5LjIsIJNTdG9yZSBhc3NpZ25tZW50lDwvc3Bhbj48c3Bhbg0Kc3R5bGU9J2ZvbnQtc2l6ZTox
+MS4wcHQ7Y29sb3I6YmxhY2snPiwgYXBwbHkgdG8gdGhlIGNvbHVtbiBvZiB0YWJsZSA8aT5UIDwv
+aT5pZGVudGlmaWVkDQpieSB0aGUgPHNwYW4gY2xhc3M9U3BlbGxFPjxpPmk8L2k+LXRoPC9zcGFu
+PiAmbHQ7Y29sdW1uIG5hbWUmZ3Q7IGluIHRoZQ0KJmx0O2luc2VydCBjb2x1bW4gbGlzdCZndDsg
+YW5kIDxzcGFuIGNsYXNzPVNwZWxsRT48aT5FWFA8L2k+PGk+PHNwYW4NCnN0eWxlPSdmb250LXNp
+emU6OS4wcHQnPmk8L3NwYW4+PC9pPjwvc3Bhbj48L3NwYW4+PGk+PHNwYW4gc3R5bGU9J2ZvbnQt
+c2l6ZToNCjkuMHB0O2NvbG9yOmJsYWNrJz4gPC9zcGFuPjwvaT48c3BhbiBzdHlsZT0nZm9udC1z
+aXplOjExLjBwdDtjb2xvcjpibGFjayc+YXMgPGk+VEFSR0VUDQo8L2k+YW5kIDxpPlZBTFVFPC9p
+PiwgcmVzcGVjdGl2ZWx5LjxvOnA+PC9vOnA+PC9zcGFuPjwvcD4NCg0KPHAgY2xhc3M9TXNvTm9y
+bWFsIHN0eWxlPSdtc28tbGF5b3V0LWdyaWQtYWxpZ246bm9uZTt0ZXh0LWF1dG9zcGFjZTpub25l
+Jz48Yj48c3Bhbg0Kc3R5bGU9J2ZvbnQtc2l6ZToxNC4wcHQ7Y29sb3I6YmxhY2snPkFjY2VzcyBS
+dWxlczxvOnA+PC9vOnA+PC9zcGFuPjwvYj48L3A+DQoNCjxwIGNsYXNzPU1zb05vcm1hbCBzdHls
+ZT0nbXNvLWxheW91dC1ncmlkLWFsaWduOm5vbmU7dGV4dC1hdXRvc3BhY2U6bm9uZSc+PHNwYW4N
+CnN0eWxlPSdmb250LXNpemU6MTEuMHB0O2NvbG9yOmJsYWNrJz4xKSBDYXNlOjxvOnA+PC9vOnA+
+PC9zcGFuPjwvcD4NCg0KPHAgY2xhc3M9TXNvTm9ybWFsIHN0eWxlPSdtc28tbGF5b3V0LWdyaWQt
+YWxpZ246bm9uZTt0ZXh0LWF1dG9zcGFjZTpub25lJz48c3Bhbg0Kc3R5bGU9J2ZvbnQtc2l6ZTox
+MS4wcHQ7Y29sb3I6YmxhY2snPmEpIElmICZsdDttZXJnZSBzdGF0ZW1lbnQmZ3Q7IGlzDQpjb250
+YWluZWQsIHdpdGhvdXQgYW4gaW50ZXJ2ZW5pbmcgJmx0O1NRTCByb3V0aW5lIHNwZWMmZ3Q7IHRo
+YXQgc3BlY2lmaWVzIFNRTCBTRUNVUklUWQ0KSU5WT0tFUiwgaW4gYW4gJmx0O1NRTCBzY2hlbWEg
+c3RhdGVtZW50Jmd0OywgdGhlbiBsZXQgPGk+QSA8L2k+YmUgdGhlDQombHQ7YXV0aG9yaXphdGlv
+biBpZGVudGlmaWVyJmd0OyB0aGF0IG93bnMgdGhhdCBzY2hlbWEuPG86cD48L286cD48L3NwYW4+
+PC9wPg0KDQo8cCBjbGFzcz1Nc29Ob3JtYWwgc3R5bGU9J21zby1sYXlvdXQtZ3JpZC1hbGlnbjpu
+b25lO3RleHQtYXV0b3NwYWNlOm5vbmUnPjxzcGFuDQpjbGFzcz1TcGVsbEU+PHNwYW4gc3R5bGU9
+J2ZvbnQtc2l6ZToxMS4wcHQ7Y29sb3I6YmxhY2snPmk8L3NwYW4+PC9zcGFuPjxzcGFuDQpzdHls
+ZT0nZm9udC1zaXplOjExLjBwdDtjb2xvcjpibGFjayc+KSBUaGUgYXBwbGljYWJsZSBwcml2aWxl
+Z2VzIGZvciA8aT5BIDwvaT5zaGFsbA0KaW5jbHVkZSBVUERBVEUgZm9yIGVhY2ggdXBkYXRlIG9i
+amVjdCBjb2x1bW4uPG86cD48L286cD48L3NwYW4+PC9wPg0KDQo8cCBjbGFzcz1Nc29Ob3JtYWwg
+c3R5bGU9J21zby1sYXlvdXQtZ3JpZC1hbGlnbjpub25lO3RleHQtYXV0b3NwYWNlOm5vbmUnPjxz
+cGFuDQpzdHlsZT0nZm9udC1zaXplOjExLjBwdDtjb2xvcjpibGFjayc+aWkpIFRoZSBhcHBsaWNh
+YmxlIHByaXZpbGVnZXMgZm9yIDxpPkEgPC9pPnNoYWxsDQppbmNsdWRlIElOU0VSVCBmb3IgZWFj
+aCBpbnNlcnQgb2JqZWN0IGNvbHVtbi48bzpwPjwvbzpwPjwvc3Bhbj48L3A+DQoNCjxwIGNsYXNz
+PU1zb05vcm1hbCBzdHlsZT0nbXNvLWxheW91dC1ncmlkLWFsaWduOm5vbmU7dGV4dC1hdXRvc3Bh
+Y2U6bm9uZSc+PHNwYW4NCnN0eWxlPSdmb250LXNpemU6MTEuMHB0O2NvbG9yOmJsYWNrJz5paWkp
+IElmICZsdDt0YXJnZXQgdGFibGUmZ3Q7IGltbWVkaWF0ZWx5DQpjb250YWlucyBPTkxZLCB0aGVu
+IHRoZSBhcHBsaWNhYmxlIHByaXZpbGVnZXMgZm9yIDxpPkEgPC9pPnNoYWxsIGluY2x1ZGUgU0VM
+RUNUDQpXSVRIIEhJRVJBUkNIWSBPUFRJT04gb24gYXQgbGVhc3Qgb25lIDxzcGFuIGNsYXNzPVNw
+ZWxsRT5zdXBlcnRhYmxlPC9zcGFuPiBvZiA8aT5UPC9pPi48bzpwPjwvbzpwPjwvc3Bhbj48L3A+
+DQoNCjxwIGNsYXNzPU1zb05vcm1hbCBzdHlsZT0nbXNvLWxheW91dC1ncmlkLWFsaWduOm5vbmU7
+dGV4dC1hdXRvc3BhY2U6bm9uZSc+PHNwYW4NCnN0eWxlPSdmb250LXNpemU6MTEuMHB0O2NvbG9y
+OmJsYWNrJz5iKSBPdGhlcndpc2UsPG86cD48L286cD48L3NwYW4+PC9wPg0KDQo8cCBjbGFzcz1N
+c29Ob3JtYWwgc3R5bGU9J21zby1sYXlvdXQtZ3JpZC1hbGlnbjpub25lO3RleHQtYXV0b3NwYWNl
+Om5vbmUnPjxzcGFuDQpjbGFzcz1TcGVsbEU+PHNwYW4gc3R5bGU9J2ZvbnQtc2l6ZToxMS4wcHQ7
+Y29sb3I6YmxhY2snPmk8L3NwYW4+PC9zcGFuPjxzcGFuDQpzdHlsZT0nZm9udC1zaXplOjExLjBw
+dDtjb2xvcjpibGFjayc+KSBUaGUgY3VycmVudCBwcml2aWxlZ2VzIHNoYWxsIGluY2x1ZGUNClVQ
+REFURSBmb3IgZWFjaCB1cGRhdGUgb2JqZWN0IGNvbHVtbi48bzpwPjwvbzpwPjwvc3Bhbj48L3A+
+DQoNCjxwIGNsYXNzPU1zb05vcm1hbCBzdHlsZT0nbXNvLWxheW91dC1ncmlkLWFsaWduOm5vbmU7
+dGV4dC1hdXRvc3BhY2U6bm9uZSc+PHNwYW4NCnN0eWxlPSdmb250LXNpemU6MTEuMHB0O2NvbG9y
+OmJsYWNrJz5paSkgVGhlIGN1cnJlbnQgcHJpdmlsZWdlcyBzaGFsbCBpbmNsdWRlDQpJTlNFUlQg
+Zm9yIGVhY2ggaW5zZXJ0IG9iamVjdCBjb2x1bW4uPG86cD48L286cD48L3NwYW4+PC9wPg0KDQo8
+cCBjbGFzcz1Nc29Ob3JtYWwgc3R5bGU9J21zby1sYXlvdXQtZ3JpZC1hbGlnbjpub25lO3RleHQt
+YXV0b3NwYWNlOm5vbmUnPjxzcGFuDQpzdHlsZT0nZm9udC1zaXplOjExLjBwdDtjb2xvcjpibGFj
+ayc+aWlpKSBJZiAmbHQ7dGFyZ2V0IHRhYmxlJmd0OyBpbW1lZGlhdGVseQ0KY29udGFpbnMgT05M
+WSwgdGhlbiB0aGUgY3VycmVudCBwcml2aWxlZ2VzIHNoYWxsIGluY2x1ZGUgU0VMRUNUIFdJVEgg
+SElFUkFSQ0hZDQpPUFRJT04gb24gYXQgbGVhc3Qgb25lIDxzcGFuIGNsYXNzPVNwZWxsRT5zdXBl
+cnRhYmxlPC9zcGFuPiBvZiA8aT5UPC9pPi48bzpwPjwvbzpwPjwvc3Bhbj48L3A+DQoNCjxwIGNs
+YXNzPU1zb05vcm1hbCBzdHlsZT0nbXNvLWxheW91dC1ncmlkLWFsaWduOm5vbmU7dGV4dC1hdXRv
+c3BhY2U6bm9uZSc+PGI+PHNwYW4NCnN0eWxlPSdmb250LXNpemU6MTQuMHB0O2NvbG9yOmJsYWNr
+Jz5HZW5lcmFsIFJ1bGVzPG86cD48L286cD48L3NwYW4+PC9iPjwvcD4NCg0KPHAgY2xhc3M9TXNv
+Tm9ybWFsIHN0eWxlPSdtc28tbGF5b3V0LWdyaWQtYWxpZ246bm9uZTt0ZXh0LWF1dG9zcGFjZTpu
+b25lJz48c3Bhbg0Kc3R5bGU9J2ZvbnQtc2l6ZToxMS4wcHQ7Y29sb3I6YmxhY2snPjEpIElmIHRo
+ZSBhY2Nlc3MgbW9kZSBvZiB0aGUgY3VycmVudA0KU1FMLXRyYW5zYWN0aW9uIG9yIHRoZSBhY2Nl
+c3MgbW9kZSBvZiB0aGUgYnJhbmNoIG9mIHRoZSBjdXJyZW50IDxzcGFuDQpjbGFzcz1TcGVsbEU+
+U1FMdHJhbnNhY3Rpb248L3NwYW4+IGF0IHRoZSBjdXJyZW50IFNRTC1jb25uZWN0aW9uIGlzIHJl
+YWQtb25seSwNCmFuZCA8aT5UIDwvaT5pcyBub3QgYSB0ZW1wb3JhcnkgdGFibGUsIHRoZW4gYW4g
+ZXhjZXB0aW9uIGNvbmRpdGlvbiBpcyByYWlzZWQ6IDxpPmludmFsaWQNCnRyYW5zYWN0aW9uIHN0
+YXRlIJcgcmVhZC1vbmx5IFNRTC10cmFuc2FjdGlvbjwvaT4uPG86cD48L286cD48L3NwYW4+PC9w
+Pg0KDQo8cCBjbGFzcz1Nc29Ob3JtYWwgc3R5bGU9J21zby1sYXlvdXQtZ3JpZC1hbGlnbjpub25l
+O3RleHQtYXV0b3NwYWNlOm5vbmUnPjxzcGFuDQpzdHlsZT0nZm9udC1zaXplOjExLjBwdDtjb2xv
+cjpibGFjayc+MikgSWYgdGhlcmUgaXMgYW55IHNlbnNpdGl2ZSBjdXJzb3IgPGk+Q1IgPC9pPnRo
+YXQNCmlzIGN1cnJlbnRseSBvcGVuIGluIHRoZSBTUUwtdHJhbnNhY3Rpb24gaW4gd2hpY2ggdGhp
+cyBTUUwtc3RhdGVtZW50IGlzIGJlaW5nDQpleGVjdXRlZCwgdGhlbjxvOnA+PC9vOnA+PC9zcGFu
+PjwvcD4NCg0KPHAgY2xhc3M9TXNvTm9ybWFsIHN0eWxlPSdtc28tbGF5b3V0LWdyaWQtYWxpZ246
+bm9uZTt0ZXh0LWF1dG9zcGFjZTpub25lJz48c3Bhbg0Kc3R5bGU9J2ZvbnQtc2l6ZToxMS4wcHQ7
+Y29sb3I6YmxhY2snPkNhc2U6PG86cD48L286cD48L3NwYW4+PC9wPg0KDQo8cCBjbGFzcz1Nc29O
+b3JtYWwgc3R5bGU9J21zby1sYXlvdXQtZ3JpZC1hbGlnbjpub25lO3RleHQtYXV0b3NwYWNlOm5v
+bmUnPjxzcGFuDQpzdHlsZT0nZm9udC1zaXplOjExLjBwdDtjb2xvcjpibGFjayc+YSkgSWYgPGk+
+Q1IgPC9pPmhhcyBub3QgYmVlbiBoZWxkIGludG8gYQ0Kc3Vic2VxdWVudCBTUUwtdHJhbnNhY3Rp
+b24sIHRoZW4gZWl0aGVyIHRoZSBjaGFuZ2UgcmVzdWx0aW5nIGZyb20gdGhlIHN1Y2Nlc3NmdWwN
+CmV4ZWN1dGlvbiBvZiB0aGlzIHN0YXRlbWVudCBzaGFsbCBiZSBtYWRlIHZpc2libGUgdG8gPGk+
+Q1IgPC9pPm9yIGFuIGV4Y2VwdGlvbg0KY29uZGl0aW9uIGlzIHJhaXNlZDo8bzpwPjwvbzpwPjwv
+c3Bhbj48L3A+DQoNCjxwIGNsYXNzPU1zb05vcm1hbCBzdHlsZT0nbXNvLWxheW91dC1ncmlkLWFs
+aWduOm5vbmU7dGV4dC1hdXRvc3BhY2U6bm9uZSc+PHNwYW4NCmNsYXNzPUdyYW1FPjxpPjxzcGFu
+IHN0eWxlPSdmb250LXNpemU6MTEuMHB0O2NvbG9yOmJsYWNrJz5jdXJzb3I8L3NwYW4+PC9pPjwv
+c3Bhbj48aT48c3Bhbg0Kc3R5bGU9J2ZvbnQtc2l6ZToxMS4wcHQ7Y29sb3I6YmxhY2snPiBzZW5z
+aXRpdml0eSBleGNlcHRpb24glyByZXF1ZXN0IGZhaWxlZDwvc3Bhbj48L2k+PHNwYW4NCnN0eWxl
+PSdmb250LXNpemU6MTEuMHB0O2NvbG9yOmJsYWNrJz4uPG86cD48L286cD48L3NwYW4+PC9wPg0K
+DQo8cCBjbGFzcz1Nc29Ob3JtYWwgc3R5bGU9J21zby1sYXlvdXQtZ3JpZC1hbGlnbjpub25lO3Rl
+eHQtYXV0b3NwYWNlOm5vbmUnPjxzcGFuDQpzdHlsZT0nZm9udC1zaXplOjExLjBwdDtjb2xvcjpi
+bGFjayc+YikgT3RoZXJ3aXNlLCB3aGV0aGVyIHRoZSBjaGFuZ2UgcmVzdWx0aW5nDQpmcm9tIHRo
+ZSBzdWNjZXNzZnVsIGV4ZWN1dGlvbiBvZiB0aGlzIFNRTC1zdGF0ZW1lbnQgaXMgbWFkZSB2aXNp
+YmxlIHRvIDxpPkNSIDwvaT5pcw0KaW1wbGVtZW50YXRpb24tZGVmaW5lZC48bzpwPjwvbzpwPjwv
+c3Bhbj48L3A+DQoNCjxwIGNsYXNzPU1zb05vcm1hbCBzdHlsZT0nbXNvLWxheW91dC1ncmlkLWFs
+aWduOm5vbmU7dGV4dC1hdXRvc3BhY2U6bm9uZSc+PHNwYW4NCnN0eWxlPSdmb250LXNpemU6MTEu
+MHB0O2NvbG9yOmJsYWNrJz4zKSBJZiB0aGVyZSBpcyBhbnkgY3Vyc29yIDxpPkNSIDwvaT50aGF0
+DQppcyBjdXJyZW50bHkgPHNwYW4gY2xhc3M9R3JhbUU+b3Blbjwvc3Bhbj4gYW5kIHdob3NlICZs
+dDtkZWNsYXJlIGN1cnNvciZndDsNCmNvbnRhaW5lZCBJTlNFTlNJVElWRSwgdGhlbiBlaXRoZXIg
+dGhlIGNoYW5nZSByZXN1bHRpbmcgZnJvbSB0aGUgc3VjY2Vzc2Z1bA0KZXhlY3V0aW9uIG9mIHRo
+aXMgc3RhdGVtZW50IHNoYWxsIGJlIGludmlzaWJsZSB0byA8aT5DUjwvaT4sIG9yIGFuIGV4Y2Vw
+dGlvbg0KY29uZGl0aW9uIGlzIHJhaXNlZDogPGk+Y3Vyc29yIHNlbnNpdGl2aXR5IGV4Y2VwdGlv
+biCXIHJlcXVlc3QgZmFpbGVkPC9pPi48bzpwPjwvbzpwPjwvc3Bhbj48L3A+DQoNCjxwIGNsYXNz
+PU1zb05vcm1hbCBzdHlsZT0nbXNvLWxheW91dC1ncmlkLWFsaWduOm5vbmU7dGV4dC1hdXRvc3Bh
+Y2U6bm9uZSc+PHNwYW4NCnN0eWxlPSdmb250LXNpemU6MTEuMHB0O2NvbG9yOmJsYWNrJz40KSBU
+aGUgZXh0ZW50IHRvIHdoaWNoIGFuDQpTUUwtaW1wbGVtZW50YXRpb24gbWF5IGRpc2FsbG93IGlu
+ZGVwZW5kZW50IGNoYW5nZXMgdGhhdCBhcmUgbm90IHNpZ25pZmljYW50IGlzDQppbXBsZW1lbnRh
+dGlvbi1kZWZpbmVkLjxvOnA+PC9vOnA+PC9zcGFuPjwvcD4NCg0KPHAgY2xhc3M9TXNvTm9ybWFs
+IHN0eWxlPSdtc28tbGF5b3V0LWdyaWQtYWxpZ246bm9uZTt0ZXh0LWF1dG9zcGFjZTpub25lJz48
+c3Bhbg0Kc3R5bGU9J2ZvbnQtc2l6ZToxMS4wcHQ7Y29sb3I6YmxhY2snPjUpIExldCA8aT5RVCA8
+L2k+YmUgdGhlIHRhYmxlIHNwZWNpZmllZCBieQ0KdGhlICZsdDt0YWJsZSByZWZlcmVuY2UmZ3Q7
+LiA8aT5RVCA8L2k+aXMgZWZmZWN0aXZlbHkgZXZhbHVhdGVkIGJlZm9yZSB1cGRhdGUNCm9yIGlu
+c2VydGlvbiBvZiBhbnkgcm93cyBpbiA8aT5UPC9pPi4gTGV0IDxpPlEgPC9pPmJlIHRoZSByZXN1
+bHQgb2YgZXZhbHVhdGluZyA8aT5RVDwvaT4uPG86cD48L286cD48L3NwYW4+PC9wPg0KDQo8cCBj
+bGFzcz1Nc29Ob3JtYWwgc3R5bGU9J21zby1sYXlvdXQtZ3JpZC1hbGlnbjpub25lO3RleHQtYXV0
+b3NwYWNlOm5vbmUnPjxzcGFuDQpzdHlsZT0nZm9udC1zaXplOjExLjBwdDtjb2xvcjpibGFjayc+
+NikgRm9yIGVhY2ggJmx0O21lcmdlIHdoZW4gY2xhdXNlJmd0Oyw8bzpwPjwvbzpwPjwvc3Bhbj48
+L3A+DQoNCjxwIGNsYXNzPU1zb05vcm1hbCBzdHlsZT0nbXNvLWxheW91dC1ncmlkLWFsaWduOm5v
+bmU7dGV4dC1hdXRvc3BhY2U6bm9uZSc+PHNwYW4NCnN0eWxlPSdmb250LXNpemU6MTEuMHB0O2Nv
+bG9yOmJsYWNrJz5DYXNlOjxvOnA+PC9vOnA+PC9zcGFuPjwvcD4NCg0KPHAgY2xhc3M9TXNvTm9y
+bWFsIHN0eWxlPSdtc28tbGF5b3V0LWdyaWQtYWxpZ246bm9uZTt0ZXh0LWF1dG9zcGFjZTpub25l
+Jz48c3Bhbg0Kc3R5bGU9J2ZvbnQtc2l6ZToxMS4wcHQ7Y29sb3I6YmxhY2snPmEpIElmICZsdDtt
+ZXJnZSB3aGVuIG1hdGNoZWQgY2xhdXNlJmd0OyBpcw0Kc3BlY2lmaWVkLCB0aGVuOjxvOnA+PC9v
+OnA+PC9zcGFuPjwvcD4NCg0KPHAgY2xhc3M9TXNvTm9ybWFsIHN0eWxlPSdtc28tbGF5b3V0LWdy
+aWQtYWxpZ246bm9uZTt0ZXh0LWF1dG9zcGFjZTpub25lJz48c3Bhbg0KY2xhc3M9U3BlbGxFPjxz
+cGFuIHN0eWxlPSdmb250LXNpemU6MTEuMHB0O2NvbG9yOmJsYWNrJz5pPC9zcGFuPjwvc3Bhbj48
+c3Bhbg0Kc3R5bGU9J2ZvbnQtc2l6ZToxMS4wcHQ7Y29sb3I6YmxhY2snPikgRm9yIGVhY2ggcm93
+IDxpPlIxIDwvaT5vZiA8aT5UPC9pPjo8bzpwPjwvbzpwPjwvc3Bhbj48L3A+DQoNCjxwIGNsYXNz
+PU1zb05vcm1hbCBzdHlsZT0nbXNvLWxheW91dC1ncmlkLWFsaWduOm5vbmU7dGV4dC1hdXRvc3Bh
+Y2U6bm9uZSc+PHNwYW4NCnN0eWxlPSdmb250LXNpemU6MTEuMHB0O2NvbG9yOmJsYWNrJz4xKSBU
+aGUgJmx0O3NlYXJjaCBjb25kaXRpb24mZ3Q7IGlzIGFwcGxpZWQNCnRvIDxpPlIxIDwvaT53aXRo
+IHRoZSBleHBvc2VkICZsdDt0YWJsZSBuYW1lJmd0OyBvZiB0aGUgJmx0O3RhcmdldCB0YWJsZSZn
+dDsgYm91bmQNCnRvIDxpPlIxIDwvaT5hbmQgdG8gZWFjaCByb3cgb2YgPGk+USA8L2k+d2l0aCB0
+aGUgZXhwb3NlZCAmbHQ7Y29ycmVsYXRpb24NCm5hbWUmZ3Q7cyBvciAmbHQ7dGFibGUgb3IgcXVl
+cnkgbmFtZSZndDtzIG9mIHRoZSAmbHQ7dGFibGUgcmVmZXJlbmNlJmd0OyBib3VuZA0KdG8gdGhh
+dCByb3cuIFRoZSAmbHQ7c2VhcmNoIGNvbmRpdGlvbiZndDsgaXMgZWZmZWN0aXZlbHkgZXZhbHVh
+dGVkIGZvciA8aT5SMSA8L2k+YmVmb3JlDQp1cGRhdGluZyBhbnkgcm93IG9mIDxpPlQgPC9pPmFu
+ZCBwcmlvciB0byB0aGUgaW52b2NhdGlvbiBvZiBhbnkgJmx0O3RyaWdnZXJlZCBhY3Rpb24mZ3Q7
+DQpjYXVzZWQgYnkgdGhlIHVwZGF0ZSBvZiBhbnkgcm93IG9mIDxpPlQgPC9pPmFuZCBiZWZvcmUg
+aW5zZXJ0aW5nIGFueSByb3dzIGludG8gPGk+VA0KPC9pPmFuZCBwcmlvciB0byB0aGUgaW52b2Nh
+dGlvbiBvZiBhbnkgJmx0O3RyaWdnZXJlZCBhY3Rpb24mZ3Q7IGNhdXNlZCBieSB0aGUNCmluc2Vy
+dCBvZiBhbnkgcm93IG9mIDxpPlQ8L2k+LiBFYWNoICZsdDs8c3BhbiBjbGFzcz1TcGVsbEU+c3Vi
+cXVlcnk8L3NwYW4+Jmd0Ow0KaW4gdGhlICZsdDtzZWFyY2ggY29uZGl0aW9uJmd0OyBpcyBlZmZl
+Y3RpdmVseSBleGVjdXRlZCBmb3IgPGk+UjEgPC9pPmFuZCBmb3INCmVhY2ggcm93IG9mIDxpPlEg
+PC9pPmFuZCB0aGUgcmVzdWx0cyB1c2VkIGluIHRoZSBhcHBsaWNhdGlvbiBvZiB0aGUgJmx0O3Nl
+YXJjaA0KY29uZGl0aW9uJmd0OyB0byA8aT5SMSA8L2k+YW5kIHRoZSBnaXZlbiByb3cgb2YgPGk+
+UTwvaT4uIElmIGFueSBleGVjdXRlZCAmbHQ7PHNwYW4NCmNsYXNzPVNwZWxsRT5zdWJxdWVyeTwv
+c3Bhbj4mZ3Q7IGNvbnRhaW5zIGFuIG91dGVyIHJlZmVyZW5jZSB0byBhIGNvbHVtbiBvZiA8aT5U
+PC9pPiwNCnRoZW4gdGhlIHJlZmVyZW5jZSBpcyB0byB0aGUgdmFsdWUgb2YgdGhhdCBjb2x1bW4g
+aW4gdGhlIGdpdmVuIHJvdyBvZiA8aT5UPC9pPi48bzpwPjwvbzpwPjwvc3Bhbj48L3A+DQoNCjxw
+IGNsYXNzPU1zb05vcm1hbCBzdHlsZT0nbXNvLWxheW91dC1ncmlkLWFsaWduOm5vbmU7dGV4dC1h
+dXRvc3BhY2U6bm9uZSc+PHNwYW4NCnN0eWxlPSdmb250LXNpemU6MTEuMHB0O2NvbG9yOmJsYWNr
+Jz5DYXNlOjxvOnA+PC9vOnA+PC9zcGFuPjwvcD4NCg0KPHAgY2xhc3M9TXNvTm9ybWFsIHN0eWxl
+PSdtc28tbGF5b3V0LWdyaWQtYWxpZ246bm9uZTt0ZXh0LWF1dG9zcGFjZTpub25lJz48c3Bhbg0K
+c3R5bGU9J2ZvbnQtc2l6ZToxMS4wcHQ7Y29sb3I6YmxhY2snPkEpIElmICZsdDt0YXJnZXQgdGFi
+bGUmZ3Q7IGNvbnRhaW5zIE9OTFksDQp0aGVuIDxpPlIxIDwvaT5pcyBhIHN1YmplY3Qgcm93IGlm
+IDxpPlIxIDwvaT5oYXMgbm8gPHNwYW4gY2xhc3M9U3BlbGxFPnN1YnJvdzwvc3Bhbj4NCmluIGEg
+cHJvcGVyIDxzcGFuIGNsYXNzPVNwZWxsRT5zdWJ0YWJsZTwvc3Bhbj4gb2YgPGk+VCA8L2k+YW5k
+IHRoZSByZXN1bHQgb2YNCnRoZSAmbHQ7c2VhcmNoIGNvbmRpdGlvbiZndDsgaXMgPGk+VHJ1ZSA8
+L2k+Zm9yIHNvbWUgcm93IDxpPlIyIDwvaT5vZiA8aT5RPC9pPi4NCjxpPlIyIDwvaT5pcyB0aGUg
+bWF0Y2hpbmcgcm93LjxvOnA+PC9vOnA+PC9zcGFuPjwvcD4NCg0KPHAgY2xhc3M9TXNvTm9ybWFs
+IHN0eWxlPSdtc28tbGF5b3V0LWdyaWQtYWxpZ246bm9uZTt0ZXh0LWF1dG9zcGFjZTpub25lJz48
+c3Bhbg0Kc3R5bGU9J2ZvbnQtc2l6ZToxMS4wcHQ7Y29sb3I6YmxhY2snPkIpIE90aGVyd2lzZSwg
+PGk+UjEgPC9pPmlzIGEgc3ViamVjdCByb3cNCmlmIHRoZSByZXN1bHQgb2YgdGhlICZsdDtzZWFy
+Y2ggY29uZGl0aW9uJmd0OyBpcyA8aT5UcnVlIDwvaT5mb3Igc29tZSByb3cgPGk+UjINCjwvaT5v
+ZiA8aT5RPC9pPi4gPGk+UjIgPC9pPmlzIHRoZSBtYXRjaGluZyByb3cuPG86cD48L286cD48L3Nw
+YW4+PC9wPg0KDQo8cCBjbGFzcz1Nc29Ob3JtYWwgc3R5bGU9J21zby1sYXlvdXQtZ3JpZC1hbGln
+bjpub25lO3RleHQtYXV0b3NwYWNlOm5vbmUnPjxzcGFuDQpzdHlsZT0nZm9udC1zaXplOjkuMHB0
+O2NvbG9yOmJsYWNrJz5OT1RFIDM4MCCXIJNvdXRlciByZWZlcmVuY2WUIGlzIGRlZmluZWQgaW4g
+PC9zcGFuPjxzcGFuDQpjbGFzcz1TcGVsbEU+PHNwYW4gc3R5bGU9J2ZvbnQtc2l6ZTo5LjBwdDtj
+b2xvcjojMDAwMDcwJz5TdWJjbGF1c2U8L3NwYW4+PC9zcGFuPjxzcGFuDQpzdHlsZT0nZm9udC1z
+aXplOjkuMHB0O2NvbG9yOiMwMDAwNzAnPiA2LjcsIJMmbHQ7Y29sdW1uIHJlZmVyZW5jZSZndDuU
+PC9zcGFuPjxzcGFuDQpzdHlsZT0nZm9udC1zaXplOjkuMHB0O2NvbG9yOmJsYWNrJz4uPG86cD48
+L286cD48L3NwYW4+PC9wPg0KDQo8cCBjbGFzcz1Nc29Ob3JtYWwgc3R5bGU9J21zby1sYXlvdXQt
+Z3JpZC1hbGlnbjpub25lO3RleHQtYXV0b3NwYWNlOm5vbmUnPjxzcGFuDQpzdHlsZT0nZm9udC1z
+aXplOjExLjBwdDtjb2xvcjpibGFjayc+MikgSWYgPGk+UjEgPC9pPmlzIGEgc3ViamVjdCByb3cs
+IHRoZW46PG86cD48L286cD48L3NwYW4+PC9wPg0KDQo8cCBjbGFzcz1Nc29Ob3JtYWwgc3R5bGU9
+J21zby1sYXlvdXQtZ3JpZC1hbGlnbjpub25lO3RleHQtYXV0b3NwYWNlOm5vbmUnPjxzcGFuDQpz
+dHlsZT0nZm9udC1zaXplOjExLjBwdDtjb2xvcjpibGFjayc+QSkgTGV0IDxpPk0gPC9pPmJlIHRo
+ZSBudW1iZXIgb2YgbWF0Y2hpbmcNCnJvd3MgaW4gPGk+USA8L2k+Zm9yIDxpPlIxPC9pPi48bzpw
+PjwvbzpwPjwvc3Bhbj48L3A+DQoNCjxwIGNsYXNzPU1zb05vcm1hbCBzdHlsZT0nbXNvLWxheW91
+dC1ncmlkLWFsaWduOm5vbmU7dGV4dC1hdXRvc3BhY2U6bm9uZSc+PHNwYW4NCnN0eWxlPSdmb250
+LXNpemU6MTEuMHB0O2NvbG9yOmJsYWNrJz5CKSBJZiA8aT5NIDwvaT5pcyBncmVhdGVyIHRoYW4g
+MSAob25lKSwNCnRoZW4gYW4gZXhjZXB0aW9uIGNvbmRpdGlvbiBpcyByYWlzZWQ6IDxpPmNhcmRp
+bmFsaXR5IHZpb2xhdGlvbjwvaT4uPG86cD48L286cD48L3NwYW4+PC9wPg0KDQo8cCBjbGFzcz1N
+c29Ob3JtYWwgc3R5bGU9J21zby1sYXlvdXQtZ3JpZC1hbGlnbjpub25lO3RleHQtYXV0b3NwYWNl
+Om5vbmUnPjxzcGFuDQpzdHlsZT0nZm9udC1zaXplOjExLjBwdDtjb2xvcjpibGFjayc+QykgVGhl
+ICZsdDt1cGRhdGUgc291cmNlJmd0OyBvZiBlYWNoDQombHQ7c2V0IGNsYXVzZSZndDsgaXMgZWZm
+ZWN0aXZlbHkgZXZhbHVhdGVkIGZvciA8aT5SMSA8L2k+YmVmb3JlIGFueSByb3cgb2YgPGk+VA0K
+PC9pPmlzIHVwZGF0ZWQgYW5kIHByaW9yIHRvIHRoZSBpbnZvY2F0aW9uIG9mIGFueSAmbHQ7dHJp
+Z2dlcmVkIGFjdGlvbiZndDsNCmNhdXNlZCBieSB0aGUgdXBkYXRlIG9mIGFueSByb3cgb2YgPGk+
+VDwvaT4uIFRoZSByZXN1bHRpbmcgdmFsdWUgaXMgdGhlIHVwZGF0ZQ0KdmFsdWUuPG86cD48L286
+cD48L3NwYW4+PC9wPg0KDQo8cCBjbGFzcz1Nc29Ob3JtYWwgc3R5bGU9J21zby1sYXlvdXQtZ3Jp
+ZC1hbGlnbjpub25lO3RleHQtYXV0b3NwYWNlOm5vbmUnPjxzcGFuDQpzdHlsZT0nZm9udC1zaXpl
+OjExLjBwdDtjb2xvcjpibGFjayc+RCkgQSBjYW5kaWRhdGUgbmV3IHJvdyBpcyBjb25zdHJ1Y3Rl
+ZCBieQ0KY29weWluZyB0aGUgc3ViamVjdCByb3cgYW5kIHVwZGF0aW5nIGl0IGFzIHNwZWNpZmll
+ZCBieSBlYWNoICZsdDtzZXQgY2xhdXNlJmd0Ow0KYnkgYXBwbHlpbmcgdGhlIEdlbmVyYWwgUnVs
+ZXMgb2YgPC9zcGFuPjxzcGFuIGNsYXNzPVNwZWxsRT48c3Bhbg0Kc3R5bGU9J2ZvbnQtc2l6ZTox
+MS4wcHQ7Y29sb3I6IzAwMDA3MCc+U3ViY2xhdXNlPC9zcGFuPjwvc3Bhbj48c3Bhbg0Kc3R5bGU9
+J2ZvbnQtc2l6ZToxMS4wcHQ7Y29sb3I6IzAwMDA3MCc+IDE0LjEyLCCTJmx0O3NldCBjbGF1c2Ug
+bGlzdCZndDuUPC9zcGFuPjxzcGFuDQpzdHlsZT0nZm9udC1zaXplOjExLjBwdDtjb2xvcjpibGFj
+ayc+LjxvOnA+PC9vOnA+PC9zcGFuPjwvcD4NCg0KPHAgY2xhc3M9TXNvTm9ybWFsIHN0eWxlPSdt
+c28tbGF5b3V0LWdyaWQtYWxpZ246bm9uZTt0ZXh0LWF1dG9zcGFjZTpub25lJz48c3Bhbg0Kc3R5
+bGU9J2ZvbnQtc2l6ZToxMS4wcHQ7Y29sb3I6YmxhY2snPmlpKSBJZiA8aT5UIDwvaT5pcyBhIGJh
+c2UgdGFibGUsIHRoZW4gZWFjaA0Kc3ViamVjdCByb3cgaXMgYWxzbyBhbiBvYmplY3Qgcm93OyBv
+dGhlcndpc2UsIGFuIG9iamVjdCByb3cgaXMgYW55IHJvdyBvZiBhDQpsZWFmIGdlbmVyYWxseSB1
+bmRlcmx5aW5nIHRhYmxlIG9mIDxpPlQgPC9pPmZyb20gd2hpY2ggYSBzdWJqZWN0IHJvdyBpcw0K
+ZGVyaXZlZC48bzpwPjwvbzpwPjwvc3Bhbj48L3A+DQoNCjxwIGNsYXNzPU1zb05vcm1hbCBzdHls
+ZT0nbXNvLWxheW91dC1ncmlkLWFsaWduOm5vbmU7dGV4dC1hdXRvc3BhY2U6bm9uZSc+PHNwYW4N
+CnN0eWxlPSdmb250LXNpemU6OS4wcHQ7Y29sb3I6YmxhY2snPk5PVEUgMzgxIJcgPHNwYW4gY2xh
+c3M9R3JhbUU+VGhlPC9zcGFuPg0KZGF0YSB2YWx1ZXMgYWxsb3dhYmxlIGluIHRoZSBvYmplY3Qg
+cm93cyBtYXkgYmUgY29uc3RyYWluZWQgYnkgYSBXSVRIIENIRUNLDQpPUFRJT04gY29uc3RyYWlu
+dC4gVGhlIGVmZmVjdCBvZiBhIFdJVEggQ0hFQ0sgT1BUSU9OIGNvbnN0cmFpbnQgaXMgZGVmaW5l
+ZCBpbg0KdGhlIEdlbmVyYWwgUnVsZXMgb2YgPC9zcGFuPjxzcGFuIGNsYXNzPVNwZWxsRT48c3Bh
+biBzdHlsZT0nZm9udC1zaXplOjkuMHB0Ow0KY29sb3I6IzAwMDA3MCc+U3ViY2xhdXNlPC9zcGFu
+Pjwvc3Bhbj48c3BhbiBzdHlsZT0nZm9udC1zaXplOjkuMHB0O2NvbG9yOiMwMDAwNzAnPg0KMTQu
+MjQsIJNFZmZlY3Qgb2YgcmVwbGFjaW5nIHNvbWUgcm93cyBpbiBhIHZpZXdlZCB0YWJsZZQ8L3Nw
+YW4+PHNwYW4NCnN0eWxlPSdmb250LXNpemU6OS4wcHQ7Y29sb3I6YmxhY2snPi48bzpwPjwvbzpw
+Pjwvc3Bhbj48L3A+DQoNCjxwIGNsYXNzPU1zb05vcm1hbCBzdHlsZT0nbXNvLWxheW91dC1ncmlk
+LWFsaWduOm5vbmU7dGV4dC1hdXRvc3BhY2U6bm9uZSc+PHNwYW4NCnN0eWxlPSdmb250LXNpemU6
+MTEuMHB0O2NvbG9yOmJsYWNrJz5paWkpIElmIGFueSByb3cgaW4gdGhlIHNldCBvZiBvYmplY3Qg
+cm93cw0KaGFzIGJlZW4gbWFya2VkIGZvciBkZWxldGlvbiBieSBhbnkgJmx0O2RlbGV0ZSBzdGF0
+ZW1lbnQ6IHBvc2l0aW9uZWQmZ3Q7IHRoYXQNCmlkZW50aWZpZXMgc29tZSBjdXJzb3IgPGk+Q1Ig
+PC9pPnRoYXQgaXMgc3RpbGwgb3BlbiBvciB1cGRhdGVkIGJ5IGFueQ0KJmx0O3VwZGF0ZSBzdGF0
+ZW1lbnQ6IHBvc2l0aW9uZWQmZ3Q7IHRoYXQgaWRlbnRpZmllcyBzb21lIGN1cnNvciA8aT5DUiA8
+L2k+dGhhdA0KaXMgc3RpbGwgb3BlbiwgdGhlbiBhIGNvbXBsZXRpb24gY29uZGl0aW9uIGlzIHJh
+aXNlZDogPGk+d2FybmluZyCXIGN1cnNvcg0Kb3BlcmF0aW9uIGNvbmZsaWN0PC9pPi48bzpwPjwv
+bzpwPjwvc3Bhbj48L3A+DQoNCjxwIGNsYXNzPU1zb05vcm1hbCBzdHlsZT0nbXNvLWxheW91dC1n
+cmlkLWFsaWduOm5vbmU7dGV4dC1hdXRvc3BhY2U6bm9uZSc+PHNwYW4NCmNsYXNzPUdyYW1FPjxz
+cGFuIHN0eWxlPSdmb250LXNpemU6MTEuMHB0O2NvbG9yOmJsYWNrJz5pdikgTGV0PC9zcGFuPjwv
+c3Bhbj48c3Bhbg0Kc3R5bGU9J2ZvbnQtc2l6ZToxMS4wcHQ7Y29sb3I6YmxhY2snPiA8aT5DTCA8
+L2k+YmUgdGhlIGNvbHVtbnMgb2YgPGk+VCA8L2k+aWRlbnRpZmllZA0KYnkgdGhlICZsdDtvYmpl
+Y3QgY29sdW1uJmd0O3MgY29udGFpbmVkIGluIHRoZSAmbHQ7c2V0IGNsYXVzZSBsaXN0Jmd0Oy48
+bzpwPjwvbzpwPjwvc3Bhbj48L3A+DQoNCjxwIGNsYXNzPU1zb05vcm1hbCBzdHlsZT0nbXNvLWxh
+eW91dC1ncmlkLWFsaWduOm5vbmU7dGV4dC1hdXRvc3BhY2U6bm9uZSc+PHNwYW4NCnN0eWxlPSdm
+b250LXNpemU6MTEuMHB0O2NvbG9yOmJsYWNrJz52KSBFYWNoIHN1YmplY3Qgcm93IDxpPlNSIDwv
+aT5pcw0KaWRlbnRpZmllZCBmb3IgcmVwbGFjZW1lbnQsIGJ5IGl0cyBjb3JyZXNwb25kaW5nIGNh
+bmRpZGF0ZSBuZXcgcm93IDxpPkNOUjwvaT4sIGluDQo8aT5UPC9pPi4gVGhlIHNldCBvZiAoPGk+
+U1I8L2k+LCA8aT5DTlI8L2k+KSA8c3BhbiBjbGFzcz1HcmFtRT5wYWlycyBpczwvc3Bhbj4NCnRo
+ZSByZXBsYWNlbWVudCBzZXQgZm9yIDxpPlQ8L2k+LjxvOnA+PC9vOnA+PC9zcGFuPjwvcD4NCg0K
+PHAgY2xhc3M9TXNvTm9ybWFsIHN0eWxlPSdtc28tbGF5b3V0LWdyaWQtYWxpZ246bm9uZTt0ZXh0
+LWF1dG9zcGFjZTpub25lJz48c3Bhbg0Kc3R5bGU9J2ZvbnQtc2l6ZTo5LjBwdDtjb2xvcjpibGFj
+ayc+Tk9URSAzODIglyBJZGVudGlmeWluZyBhIHJvdyBmb3INCnJlcGxhY2VtZW50LCBhc3NvY2lh
+dGluZyBhIHJlcGxhY2VtZW50IHJvdyB3aXRoIGFuIGlkZW50aWZpZWQgcm93LCBhbmQNCmFzc29j
+aWF0aW5nIGEgcmVwbGFjZW1lbnQgc2V0IHdpdGggYSB0YWJsZSBhcmUgaW1wbGVtZW50YXRpb24t
+ZGVwZW5kZW50DQpvcGVyYXRpb25zLjxvOnA+PC9vOnA+PC9zcGFuPjwvcD4NCg0KPHAgY2xhc3M9
+TXNvTm9ybWFsIHN0eWxlPSdtc28tbGF5b3V0LWdyaWQtYWxpZ246bm9uZTt0ZXh0LWF1dG9zcGFj
+ZTpub25lJz48c3Bhbg0KY2xhc3M9R3JhbUU+PHNwYW4gc3R5bGU9J2ZvbnQtc2l6ZToxMS4wcHQ7
+Y29sb3I6YmxhY2snPnZpKSBDYXNlPC9zcGFuPjwvc3Bhbj48c3Bhbg0Kc3R5bGU9J2ZvbnQtc2l6
+ZToxMS4wcHQ7Y29sb3I6YmxhY2snPjo8bzpwPjwvbzpwPjwvc3Bhbj48L3A+DQoNCjxwIGNsYXNz
+PU1zb05vcm1hbCBzdHlsZT0nbXNvLWxheW91dC1ncmlkLWFsaWduOm5vbmU7dGV4dC1hdXRvc3Bh
+Y2U6bm9uZSc+PHNwYW4NCnN0eWxlPSdmb250LXNpemU6MTEuMHB0O2NvbG9yOmJsYWNrJz4xKSBJ
+ZiA8aT5UIDwvaT5pcyBhIGJhc2UgdGFibGUsIHRoZW46PG86cD48L286cD48L3NwYW4+PC9wPg0K
+DQo8cCBjbGFzcz1Nc29Ob3JtYWwgc3R5bGU9J21zby1sYXlvdXQtZ3JpZC1hbGlnbjpub25lO3Rl
+eHQtYXV0b3NwYWNlOm5vbmUnPjxzcGFuDQpzdHlsZT0nZm9udC1zaXplOjExLjBwdDtjb2xvcjpi
+bGFjayc+QSkgQ2FzZTo8bzpwPjwvbzpwPjwvc3Bhbj48L3A+DQoNCjxwIGNsYXNzPU1zb05vcm1h
+bCBzdHlsZT0nbXNvLWxheW91dC1ncmlkLWFsaWduOm5vbmU7dGV4dC1hdXRvc3BhY2U6bm9uZSc+
+PHNwYW4NCnN0eWxlPSdmb250LXNpemU6MTEuMHB0O2NvbG9yOmJsYWNrJz5JKSBJZiAmbHQ7dGFy
+Z2V0IHRhYmxlJmd0OyBzcGVjaWZpZXMgT05MWSwNCnRoZW4gPGk+VCA8L2k+aXMgaWRlbnRpZmll
+ZCBmb3IgcmVwbGFjZW1lbnQgcHJvY2Vzc2luZyB3aXRob3V0IDxzcGFuDQpjbGFzcz1TcGVsbEU+
+c3VidGFibGVzPC9zcGFuPiB3aXRoIHJlc3BlY3QgdG8gb2JqZWN0IGNvbHVtbnMgPGk+Q0w8L2k+
+LjxvOnA+PC9vOnA+PC9zcGFuPjwvcD4NCg0KPHAgY2xhc3M9TXNvTm9ybWFsIHN0eWxlPSdtc28t
+bGF5b3V0LWdyaWQtYWxpZ246bm9uZTt0ZXh0LWF1dG9zcGFjZTpub25lJz48c3Bhbg0Kc3R5bGU9
+J2ZvbnQtc2l6ZToxMS4wcHQ7Y29sb3I6YmxhY2snPklJKSBPdGhlcndpc2UsIDxpPlQgPC9pPmlz
+IGlkZW50aWZpZWQgZm9yDQpyZXBsYWNlbWVudCBwcm9jZXNzaW5nIHdpdGggPHNwYW4gY2xhc3M9
+U3BlbGxFPnN1YnRhYmxlczwvc3Bhbj4gd2l0aCByZXNwZWN0IHRvDQpvYmplY3QgY29sdW1ucyA8
+aT5DTDwvaT4uPG86cD48L286cD48L3NwYW4+PC9wPg0KDQo8cCBjbGFzcz1Nc29Ob3JtYWwgc3R5
+bGU9J21zby1sYXlvdXQtZ3JpZC1hbGlnbjpub25lO3RleHQtYXV0b3NwYWNlOm5vbmUnPjxzcGFu
+DQpzdHlsZT0nZm9udC1zaXplOjkuMHB0O2NvbG9yOmJsYWNrJz5OT1RFIDM4MyCXIDxzcGFuIGNs
+YXNzPUdyYW1FPklkZW50aWZ5aW5nPC9zcGFuPg0KYSBiYXNlIHRhYmxlIGZvciByZXBsYWNlbWVu
+dCBwcm9jZXNzaW5nLCB3aXRoIG9yIHdpdGhvdXQgPHNwYW4gY2xhc3M9U3BlbGxFPnN1YnRhYmxl
+czwvc3Bhbj4sDQppcyBhbiBpbXBsZW1lbnRhdGlvbi1kZXBlbmRlbnQgbWVjaGFuaXNtLiBJbiBn
+ZW5lcmFsLCB0aG91Z2ggbm90IGhlcmUsIHRoZSBsaXN0DQpvZiBvYmplY3QgY29sdW1ucyBjYW4g
+YmUgZW1wdHkuPG86cD48L286cD48L3NwYW4+PC9wPg0KDQo8cCBjbGFzcz1Nc29Ob3JtYWwgc3R5
+bGU9J21zby1sYXlvdXQtZ3JpZC1hbGlnbjpub25lO3RleHQtYXV0b3NwYWNlOm5vbmUnPjxzcGFu
+DQpzdHlsZT0nZm9udC1zaXplOjExLjBwdDtjb2xvcjpibGFjayc+QikgVGhlIEdlbmVyYWwgUnVs
+ZXMgb2YgPC9zcGFuPjxzcGFuDQpjbGFzcz1TcGVsbEU+PHNwYW4gc3R5bGU9J2ZvbnQtc2l6ZTox
+MS4wcHQ7Y29sb3I6IzAwMDA3MCc+U3ViY2xhdXNlPC9zcGFuPjwvc3Bhbj48c3Bhbg0Kc3R5bGU9
+J2ZvbnQtc2l6ZToxMS4wcHQ7Y29sb3I6IzAwMDA3MCc+IDE0LjIyLCCTRWZmZWN0IG9mIHJlcGxh
+Y2luZyByb3dzIGluDQpiYXNlIHRhYmxlc5Q8L3NwYW4+PHNwYW4gc3R5bGU9J2ZvbnQtc2l6ZTox
+MS4wcHQ7Y29sb3I6YmxhY2snPiwgYXJlIGFwcGxpZWQuPG86cD48L286cD48L3NwYW4+PC9wPg0K
+DQo8cCBjbGFzcz1Nc29Ob3JtYWwgc3R5bGU9J21zby1sYXlvdXQtZ3JpZC1hbGlnbjpub25lO3Rl
+eHQtYXV0b3NwYWNlOm5vbmUnPjxzcGFuDQpzdHlsZT0nZm9udC1zaXplOjExLjBwdDtjb2xvcjpi
+bGFjayc+MikgSWYgPGk+VCA8L2k+aXMgYSB2aWV3ZWQgdGFibGUsIHRoZW4gdGhlDQpHZW5lcmFs
+IFJ1bGVzIG9mIDwvc3Bhbj48c3BhbiBjbGFzcz1TcGVsbEU+PHNwYW4gc3R5bGU9J2ZvbnQtc2l6
+ZToxMS4wcHQ7DQpjb2xvcjojMDAwMDcwJz5TdWJjbGF1c2U8L3NwYW4+PC9zcGFuPjxzcGFuIHN0
+eWxlPSdmb250LXNpemU6MTEuMHB0O2NvbG9yOiMwMDAwNzAnPg0KMTQuMjQsIJNFZmZlY3Qgb2Yg
+cmVwbGFjaW5nIHNvbWUgcm93cyBpbiBhIHZpZXdlZCB0YWJsZZQ8L3NwYW4+PHNwYW4NCnN0eWxl
+PSdmb250LXNpemU6MTEuMHB0O2NvbG9yOmJsYWNrJz4sIGFyZSBhcHBsaWVkIHdpdGggJmx0O3Rh
+cmdldCB0YWJsZSZndDsgYXMNCjxpPlZJRVcgTkFNRTwvaT4uPG86cD48L286cD48L3NwYW4+PC9w
+Pg0KDQo8cCBjbGFzcz1Nc29Ob3JtYWwgc3R5bGU9J21zby1sYXlvdXQtZ3JpZC1hbGlnbjpub25l
+O3RleHQtYXV0b3NwYWNlOm5vbmUnPjxzcGFuDQpzdHlsZT0nZm9udC1zaXplOjExLjBwdDtjb2xv
+cjpibGFjayc+YikgSWYgJmx0O21lcmdlIHdoZW4gbm90IG1hdGNoZWQNCmNsYXVzZSZndDsgaXMg
+c3BlY2lmaWVkLCB0aGVuOjxvOnA+PC9vOnA+PC9zcGFuPjwvcD4NCg0KPHAgY2xhc3M9TXNvTm9y
+bWFsIHN0eWxlPSdtc28tbGF5b3V0LWdyaWQtYWxpZ246bm9uZTt0ZXh0LWF1dG9zcGFjZTpub25l
+Jz48c3Bhbg0KY2xhc3M9U3BlbGxFPjxzcGFuIHN0eWxlPSdmb250LXNpemU6MTEuMHB0O2NvbG9y
+OmJsYWNrJz5pPC9zcGFuPjwvc3Bhbj48c3Bhbg0Kc3R5bGU9J2ZvbnQtc2l6ZToxMS4wcHQ7Y29s
+b3I6YmxhY2snPikgTGV0IDxpPlRSMSA8L2k+YmUgdGhlICZsdDt0YXJnZXQNCnRhYmxlJmd0OyBp
+bW1lZGlhdGVseSBjb250YWluZWQgaW4gJmx0O21lcmdlIHN0YXRlbWVudCZndDssIGxldCA8aT5U
+UjIgPC9pPmJlDQp0aGUgJmx0O3RhYmxlIHJlZmVyZW5jZSZndDsgaW1tZWRpYXRlbHkgY29udGFp
+bmVkIGluICZsdDttZXJnZSBzdGF0ZW1lbnQmZ3Q7LA0KYW5kIGxldCA8aT5TQzEgPC9pPmJlIHRo
+ZSAmbHQ7c2VhcmNoIGNvbmRpdGlvbiZndDsgaW1tZWRpYXRlbHkgY29udGFpbmVkIGluDQombHQ7
+bWVyZ2Ugc3RhdGVtZW50Jmd0Oy4gSWYgJmx0O21lcmdlIGNvcnJlbGF0aW9uIG5hbWUmZ3Q7IGlz
+IHNwZWNpZmllZCwgbGV0IDxpPk1DTg0KPC9pPmJlIJNBUyAmbHQ7bWVyZ2UgY29ycmVsYXRpb24g
+bmFtZSZndDuUOyBvdGhlcndpc2UsIGxldCA8aT5NQ04gPC9pPmJlIGENCnplcm8tbGVuZ3RoIHN0
+cmluZy4gTGV0IDxpPlMxIDwvaT5iZSB0aGUgcmVzdWx0IG9mPG86cD48L286cD48L3NwYW4+PC9w
+Pg0KDQo8cCBjbGFzcz1Nc29Ob3JtYWwgc3R5bGU9J21zby1sYXlvdXQtZ3JpZC1hbGlnbjpub25l
+O3RleHQtYXV0b3NwYWNlOm5vbmUnPjxzcGFuDQpzdHlsZT0nZm9udC1zaXplOjkuMHB0O2ZvbnQt
+ZmFtaWx5OkNvdXJpZXI7bXNvLWJpZGktZm9udC1mYW1pbHk6Q291cmllcjsNCmNvbG9yOmJsYWNr
+Jz5TRUxFQ1QgKjxvOnA+PC9vOnA+PC9zcGFuPjwvcD4NCg0KPHAgY2xhc3M9TXNvTm9ybWFsIHN0
+eWxlPSdtc28tbGF5b3V0LWdyaWQtYWxpZ246bm9uZTt0ZXh0LWF1dG9zcGFjZTpub25lJz48c3Bh
+bg0Kc3R5bGU9J2ZvbnQtc2l6ZTo5LjBwdDtmb250LWZhbWlseTpDb3VyaWVyO21zby1iaWRpLWZv
+bnQtZmFtaWx5OkNvdXJpZXI7DQpjb2xvcjpibGFjayc+RlJPTSA8aT5UUjEgTUNOPC9pPiwgPGk+
+VFIyPG86cD48L286cD48L2k+PC9zcGFuPjwvcD4NCg0KPHAgY2xhc3M9TXNvTm9ybWFsIHN0eWxl
+PSdtc28tbGF5b3V0LWdyaWQtYWxpZ246bm9uZTt0ZXh0LWF1dG9zcGFjZTpub25lJz48c3Bhbg0K
+c3R5bGU9J2ZvbnQtc2l6ZTo5LjBwdDtmb250LWZhbWlseTpDb3VyaWVyO21zby1iaWRpLWZvbnQt
+ZmFtaWx5OkNvdXJpZXI7DQpjb2xvcjpibGFjayc+V0hFUkUgPGk+U0MxPG86cD48L286cD48L2k+
+PC9zcGFuPjwvcD4NCg0KPHAgY2xhc3M9TXNvTm9ybWFsIHN0eWxlPSdtc28tbGF5b3V0LWdyaWQt
+YWxpZ246bm9uZTt0ZXh0LWF1dG9zcGFjZTpub25lJz48c3Bhbg0Kc3R5bGU9J2ZvbnQtc2l6ZTox
+MS4wcHQ7Y29sb3I6YmxhY2snPmlpKSBMZXQgPGk+UzIgPC9pPmJlIHRoZSBjb2xsZWN0aW9uIG9m
+DQpyb3dzIG9mIDxpPlEgPC9pPmZvciB3aGljaCB0aGVyZSBleGlzdHMgaW4gPGk+UzEgPC9pPnNv
+bWUgcm93IHRoYXQgaXMgdGhlDQpjb25jYXRlbmF0aW9uIG9mIHNvbWUgcm93IDxpPlIxIDwvaT5v
+ZiA8aT5UIDwvaT5hbmQgc29tZSByb3cgPGk+UjIgPC9pPm9mIDxpPlE8L2k+LjxvOnA+PC9vOnA+
+PC9zcGFuPjwvcD4NCg0KPHAgY2xhc3M9TXNvTm9ybWFsIHN0eWxlPSdtc28tbGF5b3V0LWdyaWQt
+YWxpZ246bm9uZTt0ZXh0LWF1dG9zcGFjZTpub25lJz48c3Bhbg0Kc3R5bGU9J2ZvbnQtc2l6ZTox
+MS4wcHQ7Y29sb3I6YmxhY2snPmlpaSkgTGV0IDxpPlMzIDwvaT5iZSB0aGUgY29sbGVjdGlvbiBv
+Zg0Kcm93cyBvZiA8aT5RIDwvaT50aGF0IGFyZSBub3QgaW4gPGk+UzI8L2k+LiBMZXQgPGk+U04z
+IDwvaT5iZSB0aGUgZWZmZWN0aXZlDQpkaXN0aW5jdCBuYW1lIGZvciA8aT5TMzwvaT4uIExldCA8
+aT5FTiA8L2k+YmUgdGhlIGV4cG9zZWQgJmx0O2NvcnJlbGF0aW9uDQpuYW1lJmd0OyBvciAmbHQ7
+dGFibGUgb3IgcXVlcnkgbmFtZSZndDsgb2YgPGk+VFIyPC9pPi48bzpwPjwvbzpwPjwvc3Bhbj48
+L3A+DQoNCjxwIGNsYXNzPU1zb05vcm1hbCBzdHlsZT0nbXNvLWxheW91dC1ncmlkLWFsaWduOm5v
+bmU7dGV4dC1hdXRvc3BhY2U6bm9uZSc+PHNwYW4NCmNsYXNzPUdyYW1FPjxzcGFuIHN0eWxlPSdm
+b250LXNpemU6MTEuMHB0O2NvbG9yOmJsYWNrJz5pdikgTGV0PC9zcGFuPjwvc3Bhbj48c3Bhbg0K
+c3R5bGU9J2ZvbnQtc2l6ZToxMS4wcHQ7Y29sb3I6YmxhY2snPiA8aT5TNCA8L2k+YmUgdGhlIHJl
+c3VsdCBvZjo8bzpwPjwvbzpwPjwvc3Bhbj48L3A+DQoNCjxwIGNsYXNzPU1zb05vcm1hbCBzdHls
+ZT0nbXNvLWxheW91dC1ncmlkLWFsaWduOm5vbmU7dGV4dC1hdXRvc3BhY2U6bm9uZSc+PHNwYW4N
+CnN0eWxlPSdmb250LXNpemU6OS4wcHQ7Zm9udC1mYW1pbHk6Q291cmllcjttc28tYmlkaS1mb250
+LWZhbWlseTpDb3VyaWVyOw0KY29sb3I6YmxhY2snPlNFTEVDVCA8aT5FWFA8L2k+PC9zcGFuPjxz
+cGFuIHN0eWxlPSdmb250LXNpemU6Ny41cHQ7Zm9udC1mYW1pbHk6DQpDb3VyaWVyO21zby1iaWRp
+LWZvbnQtZmFtaWx5OkNvdXJpZXI7Y29sb3I6YmxhY2snPjE8L3NwYW4+PHNwYW4NCnN0eWxlPSdm
+b250LXNpemU6OS4wcHQ7Zm9udC1mYW1pbHk6Q291cmllcjttc28tYmlkaS1mb250LWZhbWlseTpD
+b3VyaWVyOw0KY29sb3I6YmxhY2snPiwgPGk+RVhQPC9pPjwvc3Bhbj48c3BhbiBzdHlsZT0nZm9u
+dC1zaXplOjcuNXB0O2ZvbnQtZmFtaWx5OkNvdXJpZXI7DQptc28tYmlkaS1mb250LWZhbWlseTpD
+b3VyaWVyO2NvbG9yOmJsYWNrJz4yPC9zcGFuPjxzcGFuIHN0eWxlPSdmb250LXNpemU6OS4wcHQ7
+DQpmb250LWZhbWlseTpDb3VyaWVyO21zby1iaWRpLWZvbnQtZmFtaWx5OkNvdXJpZXI7Y29sb3I6
+YmxhY2snPiwgPHNwYW4NCmNsYXNzPUdyYW1FPi4uLiAsPC9zcGFuPiA8aT5FWFA8L2k+PC9zcGFu
+PjxpPjxzcGFuIHN0eWxlPSdmb250LXNpemU6Ny41cHQ7DQpmb250LWZhbWlseTpDb3VyaWVyO21z
+by1iaWRpLWZvbnQtZmFtaWx5OkNvdXJpZXI7Y29sb3I6YmxhY2snPk5JPG86cD48L286cD48L3Nw
+YW4+PC9pPjwvcD4NCg0KPHAgY2xhc3M9TXNvTm9ybWFsIHN0eWxlPSdtc28tbGF5b3V0LWdyaWQt
+YWxpZ246bm9uZTt0ZXh0LWF1dG9zcGFjZTpub25lJz48c3Bhbg0Kc3R5bGU9J2ZvbnQtc2l6ZTo5
+LjBwdDtmb250LWZhbWlseTpDb3VyaWVyO21zby1iaWRpLWZvbnQtZmFtaWx5OkNvdXJpZXI7DQpj
+b2xvcjpibGFjayc+RlJPTSA8aT5TTjMgPC9pPkFTIDxpPkVOPG86cD48L286cD48L2k+PC9zcGFu
+PjwvcD4NCg0KPHAgY2xhc3M9TXNvTm9ybWFsIHN0eWxlPSdtc28tbGF5b3V0LWdyaWQtYWxpZ246
+bm9uZTt0ZXh0LWF1dG9zcGFjZTpub25lJz48c3Bhbg0Kc3R5bGU9J2ZvbnQtc2l6ZToxMS4wcHQ7
+Y29sb3I6YmxhY2snPnYpIDxpPlM0IDwvaT5pcyBlZmZlY3RpdmVseSBldmFsdWF0ZWQNCmJlZm9y
+ZSBpbnNlcnRpb24gb2YgYW55IHJvd3MgaW50byBvciB1cGRhdGUgb2YgYW55IHJvd3MgaW4gPGk+
+VDwvaT4uPG86cD48L286cD48L3NwYW4+PC9wPg0KDQo8cCBjbGFzcz1Nc29Ob3JtYWwgc3R5bGU9
+J21zby1sYXlvdXQtZ3JpZC1hbGlnbjpub25lO3RleHQtYXV0b3NwYWNlOm5vbmUnPjxzcGFuDQpj
+bGFzcz1HcmFtRT48c3BhbiBzdHlsZT0nZm9udC1zaXplOjExLjBwdDtjb2xvcjpibGFjayc+dmkp
+IEZvcjwvc3Bhbj48L3NwYW4+PHNwYW4NCnN0eWxlPSdmb250LXNpemU6MTEuMHB0O2NvbG9yOmJs
+YWNrJz4gZWFjaCByb3cgPGk+UiA8L2k+b2YgPGk+UzQ8L2k+OjxvOnA+PC9vOnA+PC9zcGFuPjwv
+cD4NCg0KPHAgY2xhc3M9TXNvTm9ybWFsIHN0eWxlPSdtc28tbGF5b3V0LWdyaWQtYWxpZ246bm9u
+ZTt0ZXh0LWF1dG9zcGFjZTpub25lJz48c3Bhbg0Kc3R5bGU9J2ZvbnQtc2l6ZToxMS4wcHQ7Y29s
+b3I6YmxhY2snPjEpIEEgY2FuZGlkYXRlIHJvdyBvZiA8aT5UIDwvaT5pcw0KZWZmZWN0aXZlbHkg
+Y3JlYXRlZCBpbiB3aGljaCB0aGUgdmFsdWUgb2YgZWFjaCBjb2x1bW4gaXMgaXRzIGRlZmF1bHQg
+dmFsdWUsIGFzDQpzcGVjaWZpZWQgaW4gdGhlIEdlbmVyYWwgUnVsZXMgb2YgPC9zcGFuPjxzcGFu
+IGNsYXNzPVNwZWxsRT48c3Bhbg0Kc3R5bGU9J2ZvbnQtc2l6ZToxMS4wcHQ7Y29sb3I6IzAwMDA3
+MCc+U3ViY2xhdXNlPC9zcGFuPjwvc3Bhbj48c3Bhbg0Kc3R5bGU9J2ZvbnQtc2l6ZToxMS4wcHQ7
+Y29sb3I6IzAwMDA3MCc+IDExLjUsIJMmbHQ7ZGVmYXVsdCBjbGF1c2UmZ3Q7lDwvc3Bhbj48c3Bh
+bg0Kc3R5bGU9J2ZvbnQtc2l6ZToxMS4wcHQ7Y29sb3I6YmxhY2snPi4gVGhlIGNhbmRpZGF0ZSBy
+b3cgY29uc2lzdHMgb2YgZXZlcnkNCmNvbHVtbiBvZiA8aT5UPC9pPi48bzpwPjwvbzpwPjwvc3Bh
+bj48L3A+DQoNCjxwIGNsYXNzPU1zb05vcm1hbCBzdHlsZT0nbXNvLWxheW91dC1ncmlkLWFsaWdu
+Om5vbmU7dGV4dC1hdXRvc3BhY2U6bm9uZSc+PHNwYW4NCnN0eWxlPSdmb250LXNpemU6MTEuMHB0
+O2NvbG9yOmJsYWNrJz4yKSBJZiA8aT5UIDwvaT5oYXMgYSBjb2x1bW4gPGk+UkMgPC9pPm9mDQp3
+aGljaCBzb21lIHVuZGVybHlpbmcgY29sdW1uIGlzIGEgc2VsZi1yZWZlcmVuY2luZyBjb2x1bW4s
+IHRoZW4gPG86cD48L286cD48L3NwYW4+PC9wPg0KDQo8cCBjbGFzcz1Nc29Ob3JtYWwgc3R5bGU9
+J21zby1sYXlvdXQtZ3JpZC1hbGlnbjpub25lO3RleHQtYXV0b3NwYWNlOm5vbmUnPjxzcGFuDQpz
+dHlsZT0nZm9udC1zaXplOjExLjBwdDtjb2xvcjpibGFjayc+Q2FzZTo8bzpwPjwvbzpwPjwvc3Bh
+bj48L3A+DQoNCjxwIGNsYXNzPU1zb05vcm1hbCBzdHlsZT0nbXNvLWxheW91dC1ncmlkLWFsaWdu
+Om5vbmU7dGV4dC1hdXRvc3BhY2U6bm9uZSc+PHNwYW4NCnN0eWxlPSdmb250LXNpemU6MTEuMHB0
+O2NvbG9yOmJsYWNrJz5BKSBJZiA8aT5SQyA8L2k+aXMgYSBzeXN0ZW0tZ2VuZXJhdGVkDQpzZWxm
+LXJlZmVyZW5jaW5nIGNvbHVtbiwgdGhlbiB0aGUgdmFsdWUgb2YgPGk+UkMgPC9pPmlzIGVmZmVj
+dGl2ZWx5IHJlcGxhY2VkIGJ5DQp0aGUgUkVGIHZhbHVlIG9mIHRoZSBjYW5kaWRhdGUgcm93Ljxv
+OnA+PC9vOnA+PC9zcGFuPjwvcD4NCg0KPHAgY2xhc3M9TXNvTm9ybWFsIHN0eWxlPSdtc28tbGF5
+b3V0LWdyaWQtYWxpZ246bm9uZTt0ZXh0LWF1dG9zcGFjZTpub25lJz48c3Bhbg0Kc3R5bGU9J2Zv
+bnQtc2l6ZToxMS4wcHQ7Y29sb3I6YmxhY2snPkIpIElmIDxpPlJDIDwvaT5pcyBhIGRlcml2ZWQN
+CnNlbGYtcmVmZXJlbmNpbmcgY29sdW1uLCB0aGVuIHRoZSB2YWx1ZSBvZiA8aT5SQyA8L2k+aXMg
+ZWZmZWN0aXZlbHkgcmVwbGFjZWQgYnkNCmEgdmFsdWUgZGVyaXZlZCBmcm9tIHRoZSBjb2x1bW5z
+IGluIHRoZSBjYW5kaWRhdGUgcm93IHRoYXQgY29ycmVzcG9uZCB0byB0aGUNCmxpc3Qgb2YgYXR0
+cmlidXRlcyBvZiB0aGUgZGVyaXZlZCByZXByZXNlbnRhdGlvbiBvZiB0aGUgcmVmZXJlbmNlIHR5
+cGUgb2YgPGk+UkMNCjwvaT5pbiBhbiBpbXBsZW1lbnRhdGlvbiBkZXBlbmRlbnQgbWFubmVyLjxv
+OnA+PC9vOnA+PC9zcGFuPjwvcD4NCg0KPHAgY2xhc3M9TXNvTm9ybWFsIHN0eWxlPSdtc28tbGF5
+b3V0LWdyaWQtYWxpZ246bm9uZTt0ZXh0LWF1dG9zcGFjZTpub25lJz48c3Bhbg0Kc3R5bGU9J2Zv
+bnQtc2l6ZToxMS4wcHQ7Y29sb3I6YmxhY2snPjMpIEZvciBlYWNoIG9iamVjdCBjb2x1bW4gaW4g
+dGhlIGNhbmRpZGF0ZQ0Kcm93LCBsZXQgPHNwYW4gY2xhc3M9U3BlbGxFPjxpPkM8L2k+PGk+PHNw
+YW4gc3R5bGU9J2ZvbnQtc2l6ZTo5LjBwdCc+aTwvc3Bhbj48L2k+PC9zcGFuPjwvc3Bhbj48aT48
+c3Bhbg0Kc3R5bGU9J2ZvbnQtc2l6ZTo5LjBwdDtjb2xvcjpibGFjayc+IDwvc3Bhbj48L2k+PHNw
+YW4gc3R5bGU9J2ZvbnQtc2l6ZToxMS4wcHQ7DQpjb2xvcjpibGFjayc+YmUgdGhlIG9iamVjdCBj
+b2x1bW4gaWRlbnRpZmllZCBieSA8c3BhbiBjbGFzcz1HcmFtRT50aGUgPHNwYW4NCmNsYXNzPVNw
+ZWxsRT48aT5pPC9pPjwvc3Bhbj48L3NwYW4+PHNwYW4gY2xhc3M9U3BlbGxFPi10aDwvc3Bhbj4g
+Jmx0O2NvbHVtbg0KbmFtZSZndDsgaW4gdGhlICZsdDtpbnNlcnQgY29sdW1uIGxpc3QmZ3Q7IGFu
+ZCBsZXQgPHNwYW4gY2xhc3M9U3BlbGxFPjxpPlNWPC9pPjxpPjxzcGFuDQpzdHlsZT0nZm9udC1z
+aXplOjkuMHB0Jz5pPC9zcGFuPjwvaT48L3NwYW4+PC9zcGFuPjxpPjxzcGFuIHN0eWxlPSdmb250
+LXNpemU6DQo5LjBwdDtjb2xvcjpibGFjayc+IDwvc3Bhbj48L2k+PHNwYW4gc3R5bGU9J2ZvbnQt
+c2l6ZToxMS4wcHQ7Y29sb3I6YmxhY2snPmJlDQp0aGUgPHNwYW4gY2xhc3M9U3BlbGxFPjxpPmk8
+L2k+LXRoPC9zcGFuPiB2YWx1ZSBvZiA8aT5SPC9pPi48bzpwPjwvbzpwPjwvc3Bhbj48L3A+DQoN
+CjxwIGNsYXNzPU1zb05vcm1hbCBzdHlsZT0nbXNvLWxheW91dC1ncmlkLWFsaWduOm5vbmU7dGV4
+dC1hdXRvc3BhY2U6bm9uZSc+PHNwYW4NCnN0eWxlPSdmb250LXNpemU6MTEuMHB0O2NvbG9yOmJs
+YWNrJz40KSBGb3IgZXZlcnkgPHNwYW4gY2xhc3M9U3BlbGxFPjxpPkM8L2k+PGk+PHNwYW4NCnN0
+eWxlPSdmb250LXNpemU6OS4wcHQnPmk8L3NwYW4+PC9pPjwvc3Bhbj48L3NwYW4+PGk+PHNwYW4g
+c3R5bGU9J2ZvbnQtc2l6ZToNCjkuMHB0O2NvbG9yOmJsYWNrJz4gPC9zcGFuPjwvaT48c3BhbiBz
+dHlsZT0nZm9udC1zaXplOjExLjBwdDtjb2xvcjpibGFjayc+Zm9yDQp3aGljaCBvbmUgb2YgdGhl
+IGZvbGxvd2luZyBjb25kaXRpb25zIGlzIHRydWU6PG86cD48L286cD48L3NwYW4+PC9wPg0KDQo8
+cCBjbGFzcz1Nc29Ob3JtYWwgc3R5bGU9J21zby1sYXlvdXQtZ3JpZC1hbGlnbjpub25lO3RleHQt
+YXV0b3NwYWNlOm5vbmUnPjxzcGFuDQpzdHlsZT0nZm9udC1zaXplOjExLjBwdDtjb2xvcjpibGFj
+ayc+QSkgPHNwYW4gY2xhc3M9U3BlbGxFPjxpPkM8L2k+PGk+PHNwYW4NCnN0eWxlPSdmb250LXNp
+emU6OS4wcHQnPmk8L3NwYW4+PC9pPjwvc3Bhbj48L3NwYW4+PGk+PHNwYW4gc3R5bGU9J2ZvbnQt
+c2l6ZToNCjkuMHB0O2NvbG9yOmJsYWNrJz4gPC9zcGFuPjwvaT48c3BhbiBzdHlsZT0nZm9udC1z
+aXplOjExLjBwdDtjb2xvcjpibGFjayc+aXMNCm5vdCBtYXJrZWQgYXMgdW5hc3NpZ25lZCBhbmQg
+bm8gdW5kZXJseWluZyBjb2x1bW4gb2YgPHNwYW4gY2xhc3M9U3BlbGxFPjxpPkM8L2k+PGk+PHNw
+YW4NCnN0eWxlPSdmb250LXNpemU6OS4wcHQnPmk8L3NwYW4+PC9pPjwvc3Bhbj48L3NwYW4+PGk+
+PHNwYW4gc3R5bGU9J2ZvbnQtc2l6ZToNCjkuMHB0O2NvbG9yOmJsYWNrJz4gPC9zcGFuPjwvaT48
+c3BhbiBzdHlsZT0nZm9udC1zaXplOjExLjBwdDtjb2xvcjpibGFjayc+aXMgYQ0Kc2VsZi1yZWZl
+cmVuY2luZyBjb2x1bW4uPG86cD48L286cD48L3NwYW4+PC9wPg0KDQo8cCBjbGFzcz1Nc29Ob3Jt
+YWwgc3R5bGU9J21zby1sYXlvdXQtZ3JpZC1hbGlnbjpub25lO3RleHQtYXV0b3NwYWNlOm5vbmUn
+PjxzcGFuDQpzdHlsZT0nZm9udC1zaXplOjExLjBwdDtjb2xvcjpibGFjayc+QikgU29tZSB1bmRl
+cmx5aW5nIGNvbHVtbiBvZiA8c3Bhbg0KY2xhc3M9U3BlbGxFPjxpPkM8L2k+PGk+PHNwYW4gc3R5
+bGU9J2ZvbnQtc2l6ZTo5LjBwdCc+aTwvc3Bhbj48L2k+PC9zcGFuPjwvc3Bhbj48aT48c3Bhbg0K
+c3R5bGU9J2ZvbnQtc2l6ZTo5LjBwdDtjb2xvcjpibGFjayc+IDwvc3Bhbj48L2k+PHNwYW4gc3R5
+bGU9J2ZvbnQtc2l6ZToxMS4wcHQ7DQpjb2xvcjpibGFjayc+aXMgYSB1c2VyLWdlbmVyYXRlZCBz
+ZWxmLXJlZmVyZW5jaW5nIGNvbHVtbi48bzpwPjwvbzpwPjwvc3Bhbj48L3A+DQoNCjxwIGNsYXNz
+PU1zb05vcm1hbCBzdHlsZT0nbXNvLWxheW91dC1ncmlkLWFsaWduOm5vbmU7dGV4dC1hdXRvc3Bh
+Y2U6bm9uZSc+PHNwYW4NCnN0eWxlPSdmb250LXNpemU6MTEuMHB0O2NvbG9yOmJsYWNrJz5DKSBT
+b21lIHVuZGVybHlpbmcgY29sdW1uIG9mIDxzcGFuDQpjbGFzcz1TcGVsbEU+PGk+QzwvaT48aT48
+c3BhbiBzdHlsZT0nZm9udC1zaXplOjkuMHB0Jz5pPC9zcGFuPjwvaT48L3NwYW4+PC9zcGFuPjxp
+PjxzcGFuDQpzdHlsZT0nZm9udC1zaXplOjkuMHB0O2NvbG9yOmJsYWNrJz4gPC9zcGFuPjwvaT48
+c3BhbiBzdHlsZT0nZm9udC1zaXplOjExLjBwdDsNCmNvbG9yOmJsYWNrJz5pcyBhIHNlbGYtcmVm
+ZXJlbmNpbmcgY29sdW1uIGFuZCBPVkVSUklESU5HIFNZU1RFTSBWQUxVRSBpcw0Kc3BlY2lmaWVk
+LjxvOnA+PC9vOnA+PC9zcGFuPjwvcD4NCg0KPHAgY2xhc3M9TXNvTm9ybWFsIHN0eWxlPSdtc28t
+bGF5b3V0LWdyaWQtYWxpZ246bm9uZTt0ZXh0LWF1dG9zcGFjZTpub25lJz48c3Bhbg0Kc3R5bGU9
+J2ZvbnQtc2l6ZToxMS4wcHQ7Y29sb3I6YmxhY2snPkQpIFNvbWUgdW5kZXJseWluZyBjb2x1bW4g
+b2YgPHNwYW4NCmNsYXNzPVNwZWxsRT48aT5DPC9pPjxpPjxzcGFuIHN0eWxlPSdmb250LXNpemU6
+OS4wcHQnPmk8L3NwYW4+PC9pPjwvc3Bhbj48L3NwYW4+PGk+PHNwYW4NCnN0eWxlPSdmb250LXNp
+emU6OS4wcHQ7Y29sb3I6YmxhY2snPiA8L3NwYW4+PC9pPjxzcGFuIHN0eWxlPSdmb250LXNpemU6
+MTEuMHB0Ow0KY29sb3I6YmxhY2snPmlzIGFuIGlkZW50aXR5IGNvbHVtbiBhbmQgT1ZFUlJJRElO
+RyBTWVNURU0gVkFMVUUgaXMgc3BlY2lmaWVkLjxvOnA+PC9vOnA+PC9zcGFuPjwvcD4NCg0KPHAg
+Y2xhc3M9TXNvTm9ybWFsIHN0eWxlPSdtc28tbGF5b3V0LWdyaWQtYWxpZ246bm9uZTt0ZXh0LWF1
+dG9zcGFjZTpub25lJz48c3Bhbg0KY2xhc3M9R3JhbUU+PHNwYW4gc3R5bGU9J2ZvbnQtc2l6ZTox
+MS4wcHQ7Y29sb3I6YmxhY2snPnRoZTwvc3Bhbj48L3NwYW4+PHNwYW4NCnN0eWxlPSdmb250LXNp
+emU6MTEuMHB0O2NvbG9yOmJsYWNrJz4gR2VuZXJhbCBSdWxlcyBvZiA8L3NwYW4+PHNwYW4NCmNs
+YXNzPVNwZWxsRT48c3BhbiBzdHlsZT0nZm9udC1zaXplOjExLjBwdDtjb2xvcjojMDAwMDcwJz5T
+dWJjbGF1c2U8L3NwYW4+PC9zcGFuPjxzcGFuDQpzdHlsZT0nZm9udC1zaXplOjExLjBwdDtjb2xv
+cjojMDAwMDcwJz4gOS4yLCCTU3RvcmUgYXNzaWdubWVudJQ8L3NwYW4+PHNwYW4NCnN0eWxlPSdm
+b250LXNpemU6MTEuMHB0O2NvbG9yOmJsYWNrJz4sIGFyZSBhcHBsaWVkIHRvIDxzcGFuIGNsYXNz
+PVNwZWxsRT48aT5DPC9pPjxpPjxzcGFuDQpzdHlsZT0nZm9udC1zaXplOjkuMHB0Jz5pPC9zcGFu
+PjwvaT48L3NwYW4+PC9zcGFuPjxpPjxzcGFuIHN0eWxlPSdmb250LXNpemU6DQo5LjBwdDtjb2xv
+cjpibGFjayc+IDwvc3Bhbj48L2k+PHNwYW4gc3R5bGU9J2ZvbnQtc2l6ZToxMS4wcHQ7Y29sb3I6
+YmxhY2snPmFuZCA8c3Bhbg0KY2xhc3M9U3BlbGxFPjxpPlNWPC9pPjxpPjxzcGFuIHN0eWxlPSdm
+b250LXNpemU6OS4wcHQnPmk8L3NwYW4+PC9pPjwvc3Bhbj48L3NwYW4+PGk+PHNwYW4NCnN0eWxl
+PSdmb250LXNpemU6OS4wcHQ7Y29sb3I6YmxhY2snPiA8L3NwYW4+PC9pPjxzcGFuIHN0eWxlPSdm
+b250LXNpemU6MTEuMHB0Ow0KY29sb3I6YmxhY2snPmFzIDxpPlRBUkdFVCA8L2k+YW5kIDxpPlNP
+VVJDRTwvaT4sIHJlc3BlY3RpdmVseS48bzpwPjwvbzpwPjwvc3Bhbj48L3A+DQoNCjxwIGNsYXNz
+PU1zb05vcm1hbCBzdHlsZT0nbXNvLWxheW91dC1ncmlkLWFsaWduOm5vbmU7dGV4dC1hdXRvc3Bh
+Y2U6bm9uZSc+PHNwYW4NCnN0eWxlPSdmb250LXNpemU6OS4wcHQ7Y29sb3I6YmxhY2snPk5PVEUg
+Mzg0IJcgPHNwYW4gY2xhc3M9R3JhbUU+VGhlPC9zcGFuPg0KZGF0YSB2YWx1ZXMgYWxsb3dhYmxl
+IGluIHRoZSBjYW5kaWRhdGUgcm93IG1heSBiZSBjb25zdHJhaW5lZCBieSBhIFdJVEggQ0hFQ0sN
+Ck9QVElPTiBjb25zdHJhaW50LiBUaGUgZWZmZWN0IG9mIGEgV0lUSCBDSEVDSyBPUFRJT04gY29u
+c3RyYWludCBpcyBkZWZpbmVkIGluDQp0aGUgR2VuZXJhbCBSdWxlcyBvZiA8L3NwYW4+PHNwYW4g
+Y2xhc3M9U3BlbGxFPjxzcGFuIHN0eWxlPSdmb250LXNpemU6OS4wcHQ7DQpjb2xvcjojMDAwMDcw
+Jz5TdWJjbGF1c2U8L3NwYW4+PC9zcGFuPjxzcGFuIHN0eWxlPSdmb250LXNpemU6OS4wcHQ7Y29s
+b3I6IzAwMDA3MCc+DQoxNC4yMSwgk0VmZmVjdCBvZiBpbnNlcnRpbmcgYSB0YWJsZSBpbnRvIGEg
+dmlld2VkIHRhYmxllDwvc3Bhbj48c3Bhbg0Kc3R5bGU9J2ZvbnQtc2l6ZTo5LjBwdDtjb2xvcjpi
+bGFjayc+LjxvOnA+PC9vOnA+PC9zcGFuPjwvcD4NCg0KPHAgY2xhc3M9TXNvTm9ybWFsIHN0eWxl
+PSdtc28tbGF5b3V0LWdyaWQtYWxpZ246bm9uZTt0ZXh0LWF1dG9zcGFjZTpub25lJz48c3Bhbg0K
+c3R5bGU9J2ZvbnQtc2l6ZToxMS4wcHQ7Y29sb3I6YmxhY2snPnZpaSkgTGV0IDxpPlMgPC9pPmJl
+IHRoZSB0YWJsZSBjb25zaXN0aW5nDQpvZiB0aGUgY2FuZGlkYXRlIHJvd3MuPG86cD48L286cD48
+L3NwYW4+PC9wPg0KDQo8cCBjbGFzcz1Nc29Ob3JtYWwgc3R5bGU9J21zby1sYXlvdXQtZ3JpZC1h
+bGlnbjpub25lO3RleHQtYXV0b3NwYWNlOm5vbmUnPjxzcGFuDQpzdHlsZT0nZm9udC1zaXplOjEx
+LjBwdDtjb2xvcjpibGFjayc+Q2FzZTo8bzpwPjwvbzpwPjwvc3Bhbj48L3A+DQoNCjxwIGNsYXNz
+PU1zb05vcm1hbCBzdHlsZT0nbXNvLWxheW91dC1ncmlkLWFsaWduOm5vbmU7dGV4dC1hdXRvc3Bh
+Y2U6bm9uZSc+PHNwYW4NCnN0eWxlPSdmb250LXNpemU6MTEuMHB0O2NvbG9yOmJsYWNrJz4xKSBJ
+ZiA8aT5UIDwvaT5pcyBhIGJhc2UgdGFibGUsIHRoZW46PG86cD48L286cD48L3NwYW4+PC9wPg0K
+DQo8cCBjbGFzcz1Nc29Ob3JtYWwgc3R5bGU9J21zby1sYXlvdXQtZ3JpZC1hbGlnbjpub25lO3Rl
+eHQtYXV0b3NwYWNlOm5vbmUnPjxzcGFuDQpzdHlsZT0nZm9udC1zaXplOjExLjBwdDtjb2xvcjpi
+bGFjayc+QSkgPGk+VCA8L2k+aXMgPGk+aWRlbnRpZmllZCBmb3IgaW5zZXJ0aW9uDQpvZiBzb3Vy
+Y2UgdGFibGUgUzwvaT4uPG86cD48L286cD48L3NwYW4+PC9wPg0KDQo8cCBjbGFzcz1Nc29Ob3Jt
+YWwgc3R5bGU9J21zby1sYXlvdXQtZ3JpZC1hbGlnbjpub25lO3RleHQtYXV0b3NwYWNlOm5vbmUn
+PjxzcGFuDQpzdHlsZT0nZm9udC1zaXplOjkuMHB0O2NvbG9yOmJsYWNrJz5OT1RFIDM4NSCXIDxz
+cGFuIGNsYXNzPUdyYW1FPklkZW50aWZ5aW5nPC9zcGFuPg0KYSBiYXNlIHRhYmxlIGZvciBpbnNl
+cnRpb24gb2YgYSBzb3VyY2UgdGFibGUgaXMgYW4gaW1wbGVtZW50YXRpb24tZGVwZW5kZW50IG9w
+ZXJhdGlvbi48bzpwPjwvbzpwPjwvc3Bhbj48L3A+DQoNCjxwIGNsYXNzPU1zb05vcm1hbCBzdHls
+ZT0nbXNvLWxheW91dC1ncmlkLWFsaWduOm5vbmU7dGV4dC1hdXRvc3BhY2U6bm9uZSc+PHNwYW4N
+CnN0eWxlPSdmb250LXNpemU6MTEuMHB0O2NvbG9yOmJsYWNrJz5CKSBUaGUgR2VuZXJhbCBSdWxl
+cyBvZiA8L3NwYW4+PHNwYW4NCmNsYXNzPVNwZWxsRT48c3BhbiBzdHlsZT0nZm9udC1zaXplOjEx
+LjBwdDtjb2xvcjojMDAwMDcwJz5TdWJjbGF1c2U8L3NwYW4+PC9zcGFuPjxzcGFuDQpzdHlsZT0n
+Zm9udC1zaXplOjExLjBwdDtjb2xvcjojMDAwMDcwJz4gMTQuMTksIJNFZmZlY3Qgb2YgaW5zZXJ0
+aW5nIHRhYmxlcyBpbnRvDQpiYXNlIHRhYmxlc5Q8L3NwYW4+PHNwYW4gc3R5bGU9J2ZvbnQtc2l6
+ZToxMS4wcHQ7Y29sb3I6YmxhY2snPiwgYXJlIGFwcGxpZWQuPG86cD48L286cD48L3NwYW4+PC9w
+Pg0KDQo8cCBjbGFzcz1Nc29Ob3JtYWwgc3R5bGU9J21zby1sYXlvdXQtZ3JpZC1hbGlnbjpub25l
+O3RleHQtYXV0b3NwYWNlOm5vbmUnPjxzcGFuDQpzdHlsZT0nZm9udC1zaXplOjExLjBwdDtjb2xv
+cjpibGFjayc+MikgSWYgPGk+VCA8L2k+aXMgYSB2aWV3ZWQgdGFibGUsIHRoZW4gdGhlDQpHZW5l
+cmFsIFJ1bGVzIG9mIDwvc3Bhbj48c3BhbiBjbGFzcz1TcGVsbEU+PHNwYW4gc3R5bGU9J2ZvbnQt
+c2l6ZToxMS4wcHQ7DQpjb2xvcjojMDAwMDcwJz5TdWJjbGF1c2U8L3NwYW4+PC9zcGFuPjxzcGFu
+IHN0eWxlPSdmb250LXNpemU6MTEuMHB0O2NvbG9yOiMwMDAwNzAnPg0KMTQuMjEsIJNFZmZlY3Qg
+b2YgaW5zZXJ0aW5nIGEgdGFibGUgaW50byBhIHZpZXdlZCB0YWJsZZQ8L3NwYW4+PHNwYW4NCnN0
+eWxlPSdmb250LXNpemU6MTEuMHB0O2NvbG9yOmJsYWNrJz4sIGFyZSBhcHBsaWVkIHdpdGggPGk+
+UyA8L2k+YXMgPGk+U09VUkNFIDwvaT5hbmQNCjxpPlQgPC9pPmFzIDxpPlRBUkdFVDwvaT4uPG86
+cD48L286cD48L3NwYW4+PC9wPg0KDQo8cCBjbGFzcz1Nc29Ob3JtYWwgc3R5bGU9J21zby1sYXlv
+dXQtZ3JpZC1hbGlnbjpub25lO3RleHQtYXV0b3NwYWNlOm5vbmUnPjxzcGFuDQpzdHlsZT0nZm9u
+dC1zaXplOjExLjBwdDtjb2xvcjpibGFjayc+NykgSWYgPGk+USA8L2k+aXMgZW1wdHksIHRoZW4g
+YSBjb21wbGV0aW9uDQpjb25kaXRpb24gaXMgcmFpc2VkOiA8aT5ubyBkYXRhPC9pPi48bzpwPjwv
+bzpwPjwvc3Bhbj48L3A+DQoNCjxwIGNsYXNzPU1zb05vcm1hbCBzdHlsZT0nbXNvLWxheW91dC1n
+cmlkLWFsaWduOm5vbmU7dGV4dC1hdXRvc3BhY2U6bm9uZSc+PGI+PHNwYW4NCnN0eWxlPSdmb250
+LXNpemU6MTQuMHB0O2NvbG9yOmJsYWNrJz5Db25mb3JtYW5jZSBSdWxlczxvOnA+PC9vOnA+PC9z
+cGFuPjwvYj48L3A+DQoNCjxwIGNsYXNzPU1zb05vcm1hbCBzdHlsZT0nbXNvLWxheW91dC1ncmlk
+LWFsaWduOm5vbmU7dGV4dC1hdXRvc3BhY2U6bm9uZSc+PHNwYW4NCnN0eWxlPSdmb250LXNpemU6
+MTEuMHB0O2NvbG9yOmJsYWNrJz4xKSBXaXRob3V0IEZlYXR1cmUgRjc4MSwgk1NlbGYtcmVmZXJl
+bmNpbmcNCm9wZXJhdGlvbnOULCBjb25mb3JtaW5nIFNRTCBsYW5ndWFnZSBzaGFsbCBub3QgY29u
+dGFpbiBhICZsdDttZXJnZSBzdGF0ZW1lbnQmZ3Q7DQppbiB3aGljaCBhIGxlYWYgZ2VuZXJhbGx5
+IHVuZGVybHlpbmcgdGFibGUgb2YgPGk+VCA8L2k+aXMgZ2VuZXJhbGx5IGNvbnRhaW5lZA0KaW4g
+YSAmbHQ7cXVlcnkgZXhwcmVzc2lvbiZndDsgaW1tZWRpYXRlbHkgY29udGFpbmVkIGluIHRoZSAm
+bHQ7dGFibGUgcmVmZXJlbmNlJmd0Ow0KZXhjZXB0IGFzIHRoZSAmbHQ7dGFibGUgb3IgcXVlcnkg
+bmFtZSZndDsgb3IgJmx0O2NvcnJlbGF0aW9uIG5hbWUmZ3Q7IG9mIGENCmNvbHVtbiByZWZlcmVu
+Y2UuPG86cD48L286cD48L3NwYW4+PC9wPg0KDQo8cCBjbGFzcz1Nc29Ob3JtYWwgc3R5bGU9J21z
+by1sYXlvdXQtZ3JpZC1hbGlnbjpub25lO3RleHQtYXV0b3NwYWNlOm5vbmUnPjxzcGFuDQpzdHls
+ZT0nZm9udC1zaXplOjExLjBwdDtjb2xvcjpibGFjayc+MikgV2l0aG91dCBGZWF0dXJlIEY3ODEs
+IJNTZWxmLXJlZmVyZW5jaW5nDQpvcGVyYXRpb25zlCwgY29uZm9ybWluZyBTUUwgbGFuZ3VhZ2Ug
+c2hhbGwgbm90IGNvbnRhaW4gYSAmbHQ7bWVyZ2Ugc3RhdGVtZW50Jmd0Ow0KaW4gd2hpY2ggYSBs
+ZWFmIGdlbmVyYWxseSB1bmRlcmx5aW5nIHRhYmxlIG9mIDxpPlQgPC9pPmlzIGFuIHVuZGVybHlp
+bmcgdGFibGUNCm9mIGFueSAmbHQ7cXVlcnkgZXhwcmVzc2lvbiZndDsgZ2VuZXJhbGx5IGNvbnRh
+aW5lZCBpbiB0aGUgJmx0O3NlYXJjaA0KY29uZGl0aW9uJmd0Oy48bzpwPjwvbzpwPjwvc3Bhbj48
+L3A+DQoNCjxwIGNsYXNzPU1zb05vcm1hbCBzdHlsZT0nbXNvLWxheW91dC1ncmlkLWFsaWduOm5v
+bmU7dGV4dC1hdXRvc3BhY2U6bm9uZSc+PHNwYW4NCnN0eWxlPSdmb250LXNpemU6MTEuMHB0O2Nv
+bG9yOmJsYWNrJz4zKSBXaXRob3V0IEZlYXR1cmUgUzAyNCwgk0VuaGFuY2VkDQpzdHJ1Y3R1cmVk
+IHR5cGVzlCwgY29uZm9ybWluZyBTUUwgbGFuZ3VhZ2Ugc2hhbGwgbm90IGNvbnRhaW4gYSAmbHQ7
+bWVyZ2Ugc3RhdGVtZW50Jmd0Ow0KdGhhdCBkb2VzIG5vdCBzYXRpc2Z5IHRoZSBjb25kaXRpb246
+IGZvciBlYWNoIGNvbHVtbiA8aT5DIDwvaT5pZGVudGlmaWVkIGluIHRoZQ0KZXhwbGljaXQgb3Ig
+aW1wbGljaXQgJmx0O2luc2VydCBjb2x1bW4gbGlzdCZndDssIGlmIHRoZSBkZWNsYXJlZCB0eXBl
+IG9mIDxpPkMgPC9pPmlzDQphIHN0cnVjdHVyZWQgdHlwZSA8aT5UWTwvaT4sIHRoZW4gdGhlIGRl
+Y2xhcmVkIHR5cGUgb2YgdGhlIGNvcnJlc3BvbmRpbmcgY29sdW1uDQpvZiB0aGUgJmx0O3F1ZXJ5
+IGV4cHJlc3Npb24mZ3Q7IG9yICZsdDtjb250ZXh0dWFsbHkgdHlwZWQgdGFibGUgdmFsdWUNCmNv
+bnN0cnVjdG9yJmd0OyBpcyA8aT5UWTwvaT4uPG86cD48L286cD48L3NwYW4+PC9wPg0KDQo8cCBj
+bGFzcz1Nc29Ob3JtYWwgc3R5bGU9J21zby1sYXlvdXQtZ3JpZC1hbGlnbjpub25lO3RleHQtYXV0
+b3NwYWNlOm5vbmUnPjxzcGFuDQpzdHlsZT0nZm9udC1zaXplOjExLjBwdDtjb2xvcjpibGFjayc+
+NCkgV2l0aG91dCBGZWF0dXJlIEYzMTIsIJNNRVJHRSBzdGF0ZW1lbnSULA0KY29uZm9ybWluZyBT
+UUwgbGFuZ3VhZ2Ugc2hhbGwgbm90IGNvbnRhaW4gYSAmbHQ7bWVyZ2Ugc3RhdGVtZW50Jmd0Oy48
+bzpwPjwvbzpwPjwvc3Bhbj48L3A+DQoNCjxwIGNsYXNzPU1zb05vcm1hbCBzdHlsZT0nbXNvLWxh
+eW91dC1ncmlkLWFsaWduOm5vbmU7dGV4dC1hdXRvc3BhY2U6bm9uZSc+PHNwYW4NCnN0eWxlPSdm
+b250LXNpemU6MTEuMHB0O2NvbG9yOmJsYWNrJz41KSBXaXRob3V0IEZlYXR1cmUgVDExMSwgk1Vw
+ZGF0YWJsZSBqb2lucywNCnVuaW9ucywgYW5kIGNvbHVtbnOULCBjb25mb3JtaW5nIFNRTCBsYW5n
+dWFnZSBzaGFsbCBub3QgY29udGFpbiBhICZsdDttZXJnZQ0Kc3RhdGVtZW50Jmd0OyB0aGF0IGNv
+bnRhaW5zIGFuICZsdDt0YXJnZXQgdGFibGUmZ3Q7IHRoYXQgaWRlbnRpZmllcyBhIHRhYmxlDQp0
+aGF0IGlzIG5vdCBzaW1wbHkgdXBkYXRhYmxlLjxvOnA+PC9vOnA+PC9zcGFuPjwvcD4NCg0KPC9k
+aXY+DQoNCjwvYm9keT4NCg0KPC9odG1sPg0K
+
+------_=_NextPart_001_01C5EBF2.45ACB7DC--
+
+From pgsql-hackers-owner+M76240@postgresql.org Fri Nov 18 00:37:18 2005
+Return-path: <pgsql-hackers-owner+M76240@postgresql.org>
+Received: from ams.hub.org (ams.hub.org [200.46.204.13])
+       by candle.pha.pa.us (8.11.6/8.11.6) with ESMTP id jAI5bHO24992
+       for <pgman@candle.pha.pa.us>; Fri, 18 Nov 2005 00:37:17 -0500 (EST)
+Received: from postgresql.org (svr1.postgresql.org [200.46.204.71])
+       by ams.hub.org (Postfix) with ESMTP id 568F2C4BB5D;
+       Fri, 18 Nov 2005 05:37:13 +0000 (GMT)
+X-Original-To: pgsql-hackers-postgresql.org@localhost.postgresql.org
+Received: from localhost (av.hub.org [200.46.204.144])
+       by svr1.postgresql.org (Postfix) with ESMTP id B2ABDDB7D0
+       for <pgsql-hackers-postgresql.org@localhost.postgresql.org>; Fri, 18 Nov 2005 00:57:11 -0400 (AST)
+Received: from svr1.postgresql.org ([200.46.204.71])
+       by localhost (av.hub.org [200.46.204.144]) (amavisd-new, port 10024)
+       with ESMTP id 41664-06
+       for <pgsql-hackers-postgresql.org@localhost.postgresql.org>;
+       Fri, 18 Nov 2005 04:57:10 +0000 (GMT)
+X-Greylist: from auto-whitelisted by SQLgrey-
+Received: from zigo.dhs.org (ua-83-227-204-174.cust.bredbandsbolaget.se [83.227.204.174])
+       by svr1.postgresql.org (Postfix) with ESMTP id E7930DB745
+       for <pgsql-hackers@postgresql.org>; Fri, 18 Nov 2005 00:57:08 -0400 (AST)
+Received: from zigo.zigo.dhs.org (zigo.zigo.dhs.org [192.168.0.1])
+       by zigo.dhs.org (Postfix) with ESMTP
+       id EC5488467; Fri, 18 Nov 2005 05:57:05 +0100 (CET)
+Date: Fri, 18 Nov 2005 05:57:05 +0100 (CET)
+From: Dennis Bjorklund <db@zigo.dhs.org>
+To: Bruce Momjian <pgman@candle.pha.pa.us>
+cc: Zeugswetter Andreas DCP SD <ZeugswetterA@spardat.at>,
+   Csaba Nagy <nagy@ecircle-ag.com>,
+   Martijn van Oosterhout <kleptog@svana.org>, Dann Corbit <DCorbit@connx.com>,
+   Simon Riggs <simon@2ndquadrant.com>,
+   Rick Gigger <rick@alpinenetworking.com>, Tom Lane <tgl@sss.pgh.pa.us>,
+   Christopher Kings-Lynne <chriskl@familyhealth.com.au>,
+   "Jim C. Nasby" <jnasby@pervasive.com>, <josh@agliodbs.com>,
+   <pgsql-hackers@postgresql.org>, Jaime Casanova <systemguards@gmail.com>,
+   Peter Eisentraut <peter_e@gmx.net>
+Subject: Re: [HACKERS] MERGE vs REPLACE
+In-Reply-To: <200511180218.jAI2IPF04976@candle.pha.pa.us>
+Message-ID: <Pine.LNX.4.44.0511180542100.17602-100000@zigo.dhs.org>
+MIME-Version: 1.0
+Content-Type: TEXT/PLAIN; charset=ISO-8859-1
+Content-Transfer-Encoding: 8BIT
+X-Virus-Scanned: by amavisd-new at hub.org
+X-Spam-Status: No, score=0.479 required=5 tests=[DNS_FROM_RFC_ABUSE=0.479]
+X-Spam-Score: 0.479
+X-Mailing-List: pgsql-hackers
+List-Archive: <http://archives.postgresql.org/pgsql-hackers>
+List-Help: <mailto:majordomo@postgresql.org?body=help>
+List-Id: <pgsql-hackers.postgresql.org>
+List-Owner: <mailto:pgsql-hackers-owner@postgresql.org>
+List-Post: <mailto:pgsql-hackers@postgresql.org>
+List-Subscribe: <mailto:majordomo@postgresql.org?body=sub%20pgsql-hackers>
+List-Unsubscribe: <mailto:majordomo@postgresql.org?body=unsub%20pgsql-hackers>
+Precedence: bulk
+Sender: pgsql-hackers-owner@postgresql.org
+Status: ORr
+
+On Thu, 17 Nov 2005, Bruce Momjian wrote:
+
+> Unless you have a table lock, INSERT has to be before UPDATE, think
+> UPDATE, UPDATE (both fail), INSERT, INSERT.
+
+No matter what operation you start with you need a loop that try 
+insert/update until one of them succeed like in this example:
+
+http://www.postgresql.org/docs/8.1/static/plpgsql-control-structures.html#PLPGSQL-UPSERT-EXAMPLE
+
+Without a loop you might not get to execute neither the insert nor the 
+update. Why? Think about this example:
+
+BEGIN
+
+INSERT      <- fail because there is a row already
+
+            <- before we manage to do the update someone
+               delete the row (which we can see in the
+               default transaction isolation level)
+
+UPDATE      <- fail because there is no row so we will loop
+               and try the insert again
+
+            <- before we manage to do the insert someone else does
+               an insert
+
+INSERT      <- fail because there is a row already
+
+            <- before we manage to do the update someone
+               delete the row 
+....
+
+
+You might need to loop any number of times before you manage to perform
+one of the two operations. Which operation you should start with depends
+on which of the two cases is the common one.
+
+-- 
+/Dennis Björklund
+
+
+---------------------------(end of broadcast)---------------------------
+TIP 4: Have you searched our list archives?
+
+               http://archives.postgresql.org
+
+From ZeugswetterA@spardat.at Fri Nov 18 05:32:16 2005
+Return-path: <ZeugswetterA@spardat.at>
+Received: from smxsat1.smxs.net (smxsat1.smxs.net [213.150.10.1])
+       by candle.pha.pa.us (8.11.6/8.11.6) with ESMTP id jAIAWFO17231
+       for <pgman@candle.pha.pa.us>; Fri, 18 Nov 2005 05:32:15 -0500 (EST)
+Received: from m01x1.s-mxs.net [10.3.55.201]
+       by smxsat1.smxs.net
+       over TLS secured channel
+       with XWall v3.35d. ;
+       Fri, 18 Nov 2005 11:32:04 +0100
+Received: from m0102.s-mxs.net [10.3.55.2]
+       by m01x1.s-mxs.net
+       with XWall v3.35d. ;
+       Fri, 18 Nov 2005 11:33:38 +0100
+Received: from m0143.s-mxs.net ([10.252.53.143]) by m0102.s-mxs.net with Microsoft SMTPSVC(6.0.3790.1830);
+  Fri, 18 Nov 2005 11:33:38 +0100
+X-MimeOLE: Produced By Microsoft Exchange V6.5.7226.0
+content-class: urn:content-classes:message
+Subject: RE: [HACKERS] MERGE vs REPLACE
+MIME-Version: 1.0
+Content-Type: text/plain;
+       charset="us-ascii"
+Date: Fri, 18 Nov 2005 11:32:01 +0100
+Message-ID: <E1539E0ED7043848906A8FF995BDA5799A53C4@m0143.s-mxs.net>
+Thread-Topic: [HACKERS] MERGE vs REPLACE
+Thread-Index: AcXr5pYcJO3ZR4d/RwebJDquaJx6SQARC+uA
+From: "Zeugswetter Andreas DCP SD" <ZeugswetterA@spardat.at>
+To: "Bruce Momjian" <pgman@candle.pha.pa.us>
+cc: "Csaba Nagy" <nagy@ecircle-ag.com>,
+   "Martijn van Oosterhout" <kleptog@svana.org>,
+   "Dann Corbit" <DCorbit@connx.com>, "Simon Riggs" <simon@2ndquadrant.com>,
+   "Rick Gigger" <rick@alpinenetworking.com>, "Tom Lane" <tgl@sss.pgh.pa.us>,
+   "Christopher Kings-Lynne" <chriskl@familyhealth.com.au>,
+   "Jim C. Nasby" <jnasby@pervasive.com>, <josh@agliodbs.com>,
+   <pgsql-hackers@postgresql.org>, "Jaime Casanova" <systemguards@gmail.com>,
+   "Peter Eisentraut" <peter_e@gmx.net>
+X-OriginalArrivalTime: 18 Nov 2005 10:33:38.0046 (UTC) FILETIME=[8941B1E0:01C5EC2B]
+Content-Transfer-Encoding: 8bit
+X-MIME-Autoconverted: from quoted-printable to 8bit by candle.pha.pa.us id jAIAWFO17231
+Status: OR
+
+
+> Unless you have a table lock, INSERT has to be before UPDATE, think
+UPDATE, UPDATE (both fail), INSERT, INSERT.
+
+> > update
+> > if no rows updated
+> >   insert
+> >   if duplicate key
+> >     update
+> >     if no rows updated goto insert
+
+That is why you have the loop. This is not a problem with above code,
+because only one insert succeeds
+while the others then do the update.
+
+Andreas
+
+From pgsql-hackers-owner+M76266@postgresql.org Fri Nov 18 13:23:17 2005
+Return-path: <pgsql-hackers-owner+M76266@postgresql.org>
+Received: from ams.hub.org (ams.hub.org [200.46.204.13])
+       by candle.pha.pa.us (8.11.6/8.11.6) with ESMTP id jAIINGO19600
+       for <pgman@candle.pha.pa.us>; Fri, 18 Nov 2005 13:23:17 -0500 (EST)
+Received: from postgresql.org (svr1.postgresql.org [200.46.204.71])
+       by ams.hub.org (Postfix) with ESMTP id 33CABC4BB56;
+       Fri, 18 Nov 2005 18:23:14 +0000 (GMT)
+X-Original-To: pgsql-hackers-postgresql.org@localhost.postgresql.org
+Received: from localhost (av.hub.org [200.46.204.144])
+       by svr1.postgresql.org (Postfix) with ESMTP id 54076DBA92
+       for <pgsql-hackers-postgresql.org@localhost.postgresql.org>; Fri, 18 Nov 2005 11:35:26 -0400 (AST)
+Received: from svr1.postgresql.org ([200.46.204.71])
+       by localhost (av.hub.org [200.46.204.144]) (amavisd-new, port 10024)
+       with ESMTP id 41216-03
+       for <pgsql-hackers-postgresql.org@localhost.postgresql.org>;
+       Fri, 18 Nov 2005 15:35:29 +0000 (GMT)
+X-Greylist: from auto-whitelisted by SQLgrey-
+Received: from sss.pgh.pa.us (sss.pgh.pa.us [66.207.139.130])
+       by svr1.postgresql.org (Postfix) with ESMTP id 84C42DBAAE
+       for <pgsql-hackers@postgresql.org>; Fri, 18 Nov 2005 11:35:23 -0400 (AST)
+Received: from sss2.sss.pgh.pa.us (tgl@localhost [127.0.0.1])
+       by sss.pgh.pa.us (8.13.1/8.13.1) with ESMTP id jAIFYZcu006411;
+       Fri, 18 Nov 2005 10:34:35 -0500 (EST)
+To: Bruce Momjian <pgman@candle.pha.pa.us>
+cc: Dennis Bjorklund <db@zigo.dhs.org>,
+   Zeugswetter Andreas DCP SD <ZeugswetterA@spardat.at>,
+   Csaba Nagy <nagy@ecircle-ag.com>,
+   Martijn van Oosterhout <kleptog@svana.org>, Dann Corbit <DCorbit@connx.com>,
+   Simon Riggs <simon@2ndquadrant.com>,
+   Rick Gigger <rick@alpinenetworking.com>,
+   Christopher Kings-Lynne <chriskl@familyhealth.com.au>,
+   "Jim C. Nasby" <jnasby@pervasive.com>, josh@agliodbs.com,
+   pgsql-hackers@postgresql.org, Jaime Casanova <systemguards@gmail.com>,
+   Peter Eisentraut <peter_e@gmx.net>
+Subject: Re: [HACKERS] MERGE vs REPLACE 
+In-Reply-To: <200511181520.jAIFKpW02114@candle.pha.pa.us> 
+References: <200511181520.jAIFKpW02114@candle.pha.pa.us>
+Comments: In-reply-to Bruce Momjian <pgman@candle.pha.pa.us>
+       message dated "Fri, 18 Nov 2005 10:20:51 -0500"
+Date: Fri, 18 Nov 2005 10:34:35 -0500
+Message-ID: <6410.1132328075@sss.pgh.pa.us>
+From: Tom Lane <tgl@sss.pgh.pa.us>
+X-Virus-Scanned: by amavisd-new at hub.org
+X-Spam-Status: No, score=0.005 required=5 tests=[AWL=0.005]
+X-Spam-Score: 0.005
+X-Mailing-List: pgsql-hackers
+List-Archive: <http://archives.postgresql.org/pgsql-hackers>
+List-Help: <mailto:majordomo@postgresql.org?body=help>
+List-Id: <pgsql-hackers.postgresql.org>
+List-Owner: <mailto:pgsql-hackers-owner@postgresql.org>
+List-Post: <mailto:pgsql-hackers@postgresql.org>
+List-Subscribe: <mailto:majordomo@postgresql.org?body=sub%20pgsql-hackers>
+List-Unsubscribe: <mailto:majordomo@postgresql.org?body=unsub%20pgsql-hackers>
+Precedence: bulk
+Sender: pgsql-hackers-owner@postgresql.org
+Status: ORr
+
+Bruce Momjian <pgman@candle.pha.pa.us> writes:
+> Oh, good point.  I was thinking just about concurrent MERGEs.  However,
+> it is more complicated than that.  By definitaion you can not see
+> changes from other transactions while your statement is being run (even
+> if you increment CommandCounter), so to be atomic, you would still see
+> the row even though some other transaction had deleted it.
+
+We would have to use the same semantics we use now for read-committed
+UPDATE, that is look at the latest version of the row even though this
+would not normally be visible to the transaction's snapshot.
+
+In the case of a serializable transaction, no doubt we should fail if
+any concurrent change actually happens.
+
+                       regards, tom lane
+
+---------------------------(end of broadcast)---------------------------
+TIP 9: In versions below 8.0, the planner will ignore your desire to
+       choose an index scan if your joining column's datatypes do not
+       match
+
+From pgsql-hackers-owner+M76315@postgresql.org Sun Nov 20 12:35:46 2005
+Return-path: <pgsql-hackers-owner+M76315@postgresql.org>
+Received: from ams.hub.org (ams.hub.org [200.46.204.13])
+       by candle.pha.pa.us (8.11.6/8.11.6) with ESMTP id jAKHZjO09346
+       for <pgman@candle.pha.pa.us>; Sun, 20 Nov 2005 12:35:46 -0500 (EST)
+Received: from postgresql.org (svr1.postgresql.org [200.46.204.71])
+       by ams.hub.org (Postfix) with ESMTP id 463E1C4B337;
+       Sun, 20 Nov 2005 17:35:44 +0000 (GMT)
+X-Original-To: pgsql-hackers-postgresql.org@localhost.postgresql.org
+Received: from localhost (av.hub.org [200.46.204.144])
+       by svr1.postgresql.org (Postfix) with ESMTP id 63416D7E05
+       for <pgsql-hackers-postgresql.org@localhost.postgresql.org>; Sun, 20 Nov 2005 13:27:09 -0400 (AST)
+Received: from svr1.postgresql.org ([200.46.204.71])
+       by localhost (av.hub.org [200.46.204.144]) (amavisd-new, port 10024)
+       with ESMTP id 12345-02
+       for <pgsql-hackers-postgresql.org@localhost.postgresql.org>;
+       Sun, 20 Nov 2005 17:27:07 +0000 (GMT)
+X-Greylist: from auto-whitelisted by SQLgrey-
+Received: from candle.pha.pa.us (candle.pha.pa.us [64.139.89.126])
+       by svr1.postgresql.org (Postfix) with ESMTP id 264B4D7E3B
+       for <pgsql-hackers@postgresql.org>; Sun, 20 Nov 2005 13:27:05 -0400 (AST)
+Received: (from pgman@localhost)
+       by candle.pha.pa.us (8.11.6/8.11.6) id jAKHQI007897;
+       Sun, 20 Nov 2005 12:26:18 -0500 (EST)
+From: Bruce Momjian <pgman@candle.pha.pa.us>
+Message-ID: <200511201726.jAKHQI007897@candle.pha.pa.us>
+Subject: Re: [HACKERS] MERGE vs REPLACE
+In-Reply-To: <6410.1132328075@sss.pgh.pa.us>
+To: Tom Lane <tgl@sss.pgh.pa.us>
+Date: Sun, 20 Nov 2005 12:26:18 -0500 (EST)
+cc: Dennis Bjorklund <db@zigo.dhs.org>,
+   Zeugswetter Andreas DCP SD <ZeugswetterA@spardat.at>,
+   Csaba Nagy <nagy@ecircle-ag.com>,
+   Martijn van Oosterhout <kleptog@svana.org>, Dann Corbit <DCorbit@connx.com>,
+   Simon Riggs <simon@2ndquadrant.com>,
+   Rick Gigger <rick@alpinenetworking.com>,
+   Christopher Kings-Lynne <chriskl@familyhealth.com.au>,
+   "Jim C. Nasby" <jnasby@pervasive.com>, josh@agliodbs.com,
+   pgsql-hackers@postgresql.org, Jaime Casanova <systemguards@gmail.com>,
+   Peter Eisentraut <peter_e@gmx.net>
+X-Mailer: ELM [version 2.4ME+ PL121 (25)]
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Content-Type: text/plain; charset=US-ASCII
+X-Virus-Scanned: by amavisd-new at hub.org
+X-Spam-Status: No, score=0.034 required=5 tests=[AWL=0.034]
+X-Spam-Score: 0.034
+X-Mailing-List: pgsql-hackers
+List-Archive: <http://archives.postgresql.org/pgsql-hackers>
+List-Help: <mailto:majordomo@postgresql.org?body=help>
+List-Id: <pgsql-hackers.postgresql.org>
+List-Owner: <mailto:pgsql-hackers-owner@postgresql.org>
+List-Post: <mailto:pgsql-hackers@postgresql.org>
+List-Subscribe: <mailto:majordomo@postgresql.org?body=sub%20pgsql-hackers>
+List-Unsubscribe: <mailto:majordomo@postgresql.org?body=unsub%20pgsql-hackers>
+Precedence: bulk
+Sender: pgsql-hackers-owner@postgresql.org
+Status: OR
+
+Tom Lane wrote:
+> Bruce Momjian <pgman@candle.pha.pa.us> writes:
+> > Oh, good point.  I was thinking just about concurrent MERGEs.  However,
+> > it is more complicated than that.  By definitaion you can not see
+> > changes from other transactions while your statement is being run (even
+> > if you increment CommandCounter), so to be atomic, you would still see
+> > the row even though some other transaction had deleted it.
+> 
+> We would have to use the same semantics we use now for read-committed
+> UPDATE, that is look at the latest version of the row even though this
+> would not normally be visible to the transaction's snapshot.
+> 
+> In the case of a serializable transaction, no doubt we should fail if
+> any concurrent change actually happens.
+
+I have some psaudocode to explain what we want for this feature,
+whatever syntax we choose:
+
+       Start
+       Check unique index
+       Found
+               lock row for update
+               if zero rows, return to start
+               if more than one row, fail
+               update row
+       Notfound
+               create savepoint
+               insert row into heap
+               lock index page
+               if conflicting index entry, abort savepoint, return to start
+               add index entry
+               unlock index page
+
+While the "notfound" case might look strange, we actually use this exact
+method for inserts now, see ExecInsert() and _bt_doinsert(). 
+Particularly see this comment in the second function:
+
+    /*
+     * If we're not allowing duplicates, make sure the key isn't already in
+     * the index.
+     *
+     * NOTE: obviously,_bt_check_unique can only detect keys that are already in
+     * the index; so it cannot defend against concurrent insertions of the
+     * same key.  We protect against that by means of holding a write lock on
+     * the target page.  Any other would-be inserter of the same key must
+     * acquire a write lock on the same target page, so only one would-be
+     * inserter can be making the check at one time.  Furthermore, once we are
+     * past the check we hold write locks continuously until we have performed
+     * our insertion, so no later inserter can fail to see our insertion.
+     * (This requires some care in _bt_insertonpg.)
+     *
+     * If we must wait for another xact, we release the lock while waiting, and
+     * then must start over completely.
+     */
+
+Here is the unique check error from _bt_check_unique():
+
+                    ereport(ERROR,
+                            (errcode(ERRCODE_UNIQUE_VIOLATION),
+                    errmsg("duplicate key violates unique constraint \"%s\"",
+                           RelationGetRelationName(rel))));
+
+I think the problem here is that it is going to longjump() back to
+postgres.c (and out of your code loop).  While we have savepoints, I
+think they only work coming from client applications, rather than inside
+our code.  Ideally you would like to be able to say:
+
+       savepoint();
+       func();
+       rollback_to_savepoint();
+
+but you can't, so I think you are going to have to factor out that
+unique error callback and return a failure code to the caller.  I
+suppose some boolean flag need to be added to _bt_doinsert(), but that
+is called via a function pointer for the index type, so you are going to
+have to update the insert function signatures for all access methods. 
+The good news is that only btree supports unique indexes, according to
+the documentation ("Only B-tree currently supports unique indexes") so
+for the other access methods the extra parameter is just ignored.
+
+Another issue is multiple unique indexes.  What if the first unique
+index matches one row, but a different row matches the second unique
+indexed column?  Fail because unique checks do not identify exactly one
+row?
+
+Or the _new_ value for the second indexed column conflicts with the
+second unique index. The MERGE/REPLACE should fail.  The UPDATE block
+will handle this on its own, but the INSERT block will need to check for
+that an really error out, rather than return to the caller, so the loop
+in ExecInsertIndexTuples() has to restart on unique failure _only_ on
+the first index check, not the subsequent ones.
+
+One simplification would be to allow MERGE/REPLACE only on a table that
+has a single unique index.
+
+-- 
+  Bruce Momjian                        |  http://candle.pha.pa.us
+  pgman@candle.pha.pa.us               |  (610) 359-1001
+  +  If your life is a hard drive,     |  13 Roberts Road
+  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073
+
+---------------------------(end of broadcast)---------------------------
+TIP 9: In versions below 8.0, the planner will ignore your desire to
+       choose an index scan if your joining column's datatypes do not
+       match
+
+From pgsql-hackers-owner+M76369@postgresql.org Mon Nov 21 16:49:26 2005
+Return-path: <pgsql-hackers-owner+M76369@postgresql.org>
+Received: from ams.hub.org (ams.hub.org [200.46.204.13])
+       by candle.pha.pa.us (8.11.6/8.11.6) with ESMTP id jALLnPO11702
+       for <pgman@candle.pha.pa.us>; Mon, 21 Nov 2005 16:49:25 -0500 (EST)
+Received: from postgresql.org (svr1.postgresql.org [200.46.204.71])
+       by ams.hub.org (Postfix) with ESMTP id E0EF1C4BBF9;
+       Mon, 21 Nov 2005 21:49:23 +0000 (GMT)
+X-Original-To: pgsql-hackers-postgresql.org@localhost.postgresql.org
+Received: from localhost (av.hub.org [200.46.204.144])
+       by svr1.postgresql.org (Postfix) with ESMTP id 788FADA584
+       for <pgsql-hackers-postgresql.org@localhost.postgresql.org>; Mon, 21 Nov 2005 17:44:39 -0400 (AST)
+Received: from svr1.postgresql.org ([200.46.204.71])
+       by localhost (av.hub.org [200.46.204.144]) (amavisd-new, port 10024)
+       with ESMTP id 70913-06
+       for <pgsql-hackers-postgresql.org@localhost.postgresql.org>;
+       Mon, 21 Nov 2005 21:44:40 +0000 (GMT)
+X-Greylist: from auto-whitelisted by SQLgrey-
+Received: from flake.decibel.org (flake.decibel.org [67.100.216.10])
+       by svr1.postgresql.org (Postfix) with ESMTP id 128D5DA48D
+       for <pgsql-hackers@postgresql.org>; Mon, 21 Nov 2005 17:44:35 -0400 (AST)
+Received: by flake.decibel.org (Postfix, from userid 1001)
+       id AD10B1525F; Mon, 21 Nov 2005 15:44:36 -0600 (CST)
+Date: Mon, 21 Nov 2005 15:44:36 -0600
+From: "Jim C. Nasby" <jnasby@pervasive.com>
+To: Bruce Momjian <pgman@candle.pha.pa.us>
+cc: mark@mark.mielke.cc, Tom Lane <tgl@sss.pgh.pa.us>,
+   Csaba Nagy <nagy@ecircle-ag.com>,
+   Martijn van Oosterhout <kleptog@svana.org>,
+   Zeugswetter Andreas DCP SD <ZeugswetterA@spardat.at>,
+   Dann Corbit <DCorbit@connx.com>, Simon Riggs <simon@2ndquadrant.com>,
+   Rick Gigger <rick@alpinenetworking.com>,
+   Christopher Kings-Lynne <chriskl@familyhealth.com.au>, josh@agliodbs.com,
+   pgsql-hackers@postgresql.org, Jaime Casanova <systemguards@gmail.com>,
+   Peter Eisentraut <peter_e@gmx.net>
+Subject: Re: [HACKERS] MERGE vs REPLACE
+Message-ID: <20051121214436.GL19279@pervasive.com>
+References: <20051117173117.GA27563@mark.mielke.cc> <200511180230.jAI2Uh406548@candle.pha.pa.us>
+MIME-Version: 1.0
+Content-Type: text/plain; charset=us-ascii
+Content-Disposition: inline
+In-Reply-To: <200511180230.jAI2Uh406548@candle.pha.pa.us>
+X-Operating-System: FreeBSD 4.11-RELEASE-p10 i386
+X-Distributed: Join the Effort!  http://www.distributed.net
+User-Agent: Mutt/1.5.9i
+X-Virus-Scanned: by amavisd-new at hub.org
+X-Spam-Status: No, score=0.019 required=5 tests=[AWL=0.019]
+X-Spam-Score: 0.019
+X-Mailing-List: pgsql-hackers
+List-Archive: <http://archives.postgresql.org/pgsql-hackers>
+List-Help: <mailto:majordomo@postgresql.org?body=help>
+List-Id: <pgsql-hackers.postgresql.org>
+List-Owner: <mailto:pgsql-hackers-owner@postgresql.org>
+List-Post: <mailto:pgsql-hackers@postgresql.org>
+List-Subscribe: <mailto:majordomo@postgresql.org?body=sub%20pgsql-hackers>
+List-Unsubscribe: <mailto:majordomo@postgresql.org?body=unsub%20pgsql-hackers>
+Precedence: bulk
+Sender: pgsql-hackers-owner@postgresql.org
+Status: OR
+
+On Thu, Nov 17, 2005 at 09:30:43PM -0500, Bruce Momjian wrote:
+> > Is the requirement for predicate locking, over and above a unique
+> > constraint on an index that involves the record key, to deal with
+> > the scenario of two inserts executing at the same time, both before
+> > commit?
+> 
+> No.  If you have a primary key you can easily prevent duplicates.  You
+> need a table lock or predicate locking to prevent duplicates if you do
+> not have a primary key.
+
+AFAIK you can also accomplish this without a table lock as long as you
+have a unique index on the right set of fields and those fields are also
+NOT NULL. ISTM it would be good to support that case as well, since you
+might want to MERGE based on something other than the PK.
+-- 
+Jim C. Nasby, Sr. Engineering Consultant      jnasby@pervasive.com
+Pervasive Software      http://pervasive.com    work: 512-231-6117
+vcard: http://jim.nasby.net/pervasive.vcf       cell: 512-569-9461
+
+---------------------------(end of broadcast)---------------------------
+TIP 5: don't forget to increase your free space map settings
+
+From decibel@decibel.org Mon Nov 21 16:46:33 2005
+Return-path: <decibel@decibel.org>
+Received: from flake.decibel.org (flake.decibel.org [67.100.216.10])
+       by candle.pha.pa.us (8.11.6/8.11.6) with ESMTP id jALLkWO11195
+       for <pgman@candle.pha.pa.us>; Mon, 21 Nov 2005 16:46:32 -0500 (EST)
+Received: by flake.decibel.org (Postfix, from userid 1001)
+       id 78F981525F; Mon, 21 Nov 2005 15:46:30 -0600 (CST)
+Date: Mon, 21 Nov 2005 15:46:30 -0600
+From: "Jim C. Nasby" <jnasby@pervasive.com>
+To: Tom Lane <tgl@sss.pgh.pa.us>, Csaba Nagy <nagy@ecircle-ag.com>,
+   Martijn van Oosterhout <kleptog@svana.org>,
+   Zeugswetter Andreas DCP SD <ZeugswetterA@spardat.at>,
+   Dann Corbit <DCorbit@connx.com>, Simon Riggs <simon@2ndquadrant.com>,
+   Bruce Momjian <pgman@candle.pha.pa.us>,
+   Rick Gigger <rick@alpinenetworking.com>,
+   Christopher Kings-Lynne <chriskl@familyhealth.com.au>, josh@agliodbs.com,
+   pgsql-hackers@postgresql.org, Jaime Casanova <systemguards@gmail.com>,
+   Peter Eisentraut <peter_e@gmx.net>
+Subject: Re: [HACKERS] MERGE vs REPLACE
+Message-ID: <20051121214630.GM19279@pervasive.com>
+References: <E1539E0ED7043848906A8FF995BDA5799A524D@m0143.s-mxs.net> <1132228373.10890.313.camel@coppola.muc.ecircle.de> <20051117123250.GC22933@svana.org> <1132231474.10890.317.camel@coppola.muc.ecircle.de> <25849.1132238470@sss.pgh.pa.us> <20051117151530.GU6026@ns.snowman.net>
+MIME-Version: 1.0
+Content-Type: text/plain; charset=us-ascii
+Content-Disposition: inline
+In-Reply-To: <20051117151530.GU6026@ns.snowman.net>
+X-Operating-System: FreeBSD 4.11-RELEASE-p10 i386
+X-Distributed: Join the Effort!  http://www.distributed.net
+User-Agent: Mutt/1.5.9i
+Status: OR
+
+On Thu, Nov 17, 2005 at 10:15:30AM -0500, Stephen Frost wrote:
+> I don't think MERGE can really be made to be both though, in which case
+> it should really be the SQL2003 MERGE and we can make REPLACE/INSERT ON
+> DUPLICATE UPDATE something else.  Perhaps a special form of MERGE where
+> you know it's going to be doing that locking.  I really don't like the
+> idea of making the SQL2003 version of MERGE be the MERGE special case
+> (by requiring someone to take a table lock ahead of time or do something
+> else odd).
+
+Anyone know off-hand what the big 3 do? If the industry consensus is
+that merge should actually be REPLACE/INSERT ON DUPLICATE UPDATE then
+it's probably better to follow that lead.
+-- 
+Jim C. Nasby, Sr. Engineering Consultant      jnasby@pervasive.com
+Pervasive Software      http://pervasive.com    work: 512-231-6117
+vcard: http://jim.nasby.net/pervasive.vcf       cell: 512-569-9461
+
+From pgsql-hackers-owner+M76416@postgresql.org Mon Nov 21 22:20:45 2005
+Return-path: <pgsql-hackers-owner+M76416@postgresql.org>
+Received: from ams.hub.org (ams.hub.org [200.46.204.13])
+       by candle.pha.pa.us (8.11.6/8.11.6) with ESMTP id jAM3KiO01066
+       for <pgman@candle.pha.pa.us>; Mon, 21 Nov 2005 22:20:45 -0500 (EST)
+Received: from postgresql.org (svr1.postgresql.org [200.46.204.71])
+       by ams.hub.org (Postfix) with ESMTP id 16D40C4BC0E;
+       Tue, 22 Nov 2005 03:20:42 +0000 (GMT)
+X-Original-To: pgsql-hackers-postgresql.org@localhost.postgresql.org
+Received: from localhost (av.hub.org [200.46.204.144])
+       by svr1.postgresql.org (Postfix) with ESMTP id 19544D6E94
+       for <pgsql-hackers-postgresql.org@localhost.postgresql.org>; Mon, 21 Nov 2005 23:20:13 -0400 (AST)
+Received: from svr1.postgresql.org ([200.46.204.71])
+       by localhost (av.hub.org [200.46.204.144]) (amavisd-new, port 10024)
+       with ESMTP id 65279-06
+       for <pgsql-hackers-postgresql.org@localhost.postgresql.org>;
+       Tue, 22 Nov 2005 03:20:16 +0000 (GMT)
+X-Greylist: from auto-whitelisted by SQLgrey-
+Received: from gatekeeper.pjmodos.bounceme.net (5.176.broadband4.iol.cz [85.71.176.5])
+       by svr1.postgresql.org (Postfix) with ESMTP id 63160DA4D8
+       for <pgsql-hackers@postgresql.org>; Mon, 21 Nov 2005 23:20:10 -0400 (AST)
+Received: from modos ([10.12.0.96] ident=PJMODOS)
+       by gatekeeper.pjmodos.bounceme.net\r with esmtp (Exim 4.50)
+       id 1EeOhc-0004vs-1V; Tue, 22 Nov 2005 04:20:16 +0100
+Message-ID: <43828E6C.60406@seznam.cz>
+Date: Tue, 22 Nov 2005 04:20:12 +0100
+From: Petr Jelinek <pjmodos@seznam.cz>
+User-Agent: Mozilla Thunderbird 1.0 (Windows/20041206)
+X-Accept-Language: cs, en, en-us
+MIME-Version: 1.0
+To: "Jim C. Nasby" <jnasby@pervasive.com>
+cc: PostgreSQL-development <pgsql-hackers@postgresql.org>
+Subject: Re: [HACKERS] MERGE vs REPLACE
+References: <E1539E0ED7043848906A8FF995BDA5799A524D@m0143.s-mxs.net> <1132228373.10890.313.camel@coppola.muc.ecircle.de> <20051117123250.GC22933@svana.org> <1132231474.10890.317.camel@coppola.muc.ecircle.de> <25849.1132238470@sss.pgh.pa.us> <20051117151530.GU6026@ns.snowman.net> <20051121214630.GM19279@pervasive.com>
+In-Reply-To: <20051121214630.GM19279@pervasive.com>
+Content-Type: text/plain; charset=ISO-8859-1; format=flowed
+Content-Transfer-Encoding: 7bit
+X-Virus-Scanned: by amavisd-new at hub.org
+X-Amavis-Alert: BAD HEADER Improper use of control character (char 0D hex) in message header 'Received': Received: ...keeper.pjmodos.bounceme.net\r with esmtp (Ex...
+X-Spam-Status: No, score=1.44 required=5 tests=[DNS_FROM_RFC_POST=1.44]
+X-Spam-Score: 1.44
+X-Spam-Level: *
+X-Mailing-List: pgsql-hackers
+List-Archive: <http://archives.postgresql.org/pgsql-hackers>
+List-Help: <mailto:majordomo@postgresql.org?body=help>
+List-Id: <pgsql-hackers.postgresql.org>
+List-Owner: <mailto:pgsql-hackers-owner@postgresql.org>
+List-Post: <mailto:pgsql-hackers@postgresql.org>
+List-Subscribe: <mailto:majordomo@postgresql.org?body=sub%20pgsql-hackers>
+List-Unsubscribe: <mailto:majordomo@postgresql.org?body=unsub%20pgsql-hackers>
+Precedence: bulk
+Sender: pgsql-hackers-owner@postgresql.org
+Status: OR
+
+Jim C. Nasby wrote:
+> On Thu, Nov 17, 2005 at 10:15:30AM -0500, Stephen Frost wrote:
+> 
+>>I don't think MERGE can really be made to be both though, in which case
+>>it should really be the SQL2003 MERGE and we can make REPLACE/INSERT ON
+>>DUPLICATE UPDATE something else.  Perhaps a special form of MERGE where
+>>you know it's going to be doing that locking.  I really don't like the
+>>idea of making the SQL2003 version of MERGE be the MERGE special case
+>>(by requiring someone to take a table lock ahead of time or do something
+>>else odd).
+> 
+> 
+> Anyone know off-hand what the big 3 do? If the industry consensus is
+> that merge should actually be REPLACE/INSERT ON DUPLICATE UPDATE then
+> it's probably better to follow that lead.
+
+It was already said here that oracle and db2 both use MERGE, dunno about 
+mssql.
+
+And yes merge CAN be used to do REPLACE (oracle uses their dummy table 
+for this, we can use the fact that FROM clause isn't required in postgres).
+
+-- 
+Regards
+Petr Jelinek (PJMODOS)
+
+---------------------------(end of broadcast)---------------------------
+TIP 5: don't forget to increase your free space map settings
+
+From pgsql-hackers-owner+M76436@postgresql.org Tue Nov 22 05:58:26 2005
+Return-path: <pgsql-hackers-owner+M76436@postgresql.org>
+Received: from ams.hub.org (ams.hub.org [200.46.204.13])
+       by candle.pha.pa.us (8.11.6/8.11.6) with ESMTP id jAMAwPO08019
+       for <pgman@candle.pha.pa.us>; Tue, 22 Nov 2005 05:58:25 -0500 (EST)
+Received: from postgresql.org (svr1.postgresql.org [200.46.204.71])
+       by ams.hub.org (Postfix) with ESMTP id 73C27C4A48E;
+       Tue, 22 Nov 2005 10:58:21 +0000 (GMT)
+X-Original-To: pgsql-hackers-postgresql.org@localhost.postgresql.org
+Received: from localhost (av.hub.org [200.46.204.144])
+       by svr1.postgresql.org (Postfix) with ESMTP id 0E86EDAFA6
+       for <pgsql-hackers-postgresql.org@localhost.postgresql.org>; Tue, 22 Nov 2005 06:57:56 -0400 (AST)
+Received: from svr1.postgresql.org ([200.46.204.71])
+       by localhost (av.hub.org [200.46.204.144]) (amavisd-new, port 10024)
+       with ESMTP id 82600-10
+       for <pgsql-hackers-postgresql.org@localhost.postgresql.org>;
+       Tue, 22 Nov 2005 10:57:57 +0000 (GMT)
+X-Greylist: from auto-whitelisted by SQLgrey-
+Received: from svana.org (svana.org [203.20.62.76])
+       by svr1.postgresql.org (Postfix) with ESMTP id EE3F8DAFA1
+       for <pgsql-hackers@postgresql.org>; Tue, 22 Nov 2005 06:57:51 -0400 (AST)
+Received: from kleptog by svana.org with local (Exim 3.35 #1 (Debian))
+       id 1EeVqO-0003kj-00; Tue, 22 Nov 2005 21:57:48 +1100
+Date: Tue, 22 Nov 2005 11:57:48 +0100
+From: Martijn van Oosterhout <kleptog@svana.org>
+To: Petr Jelinek <pjmodos@seznam.cz>
+cc: "Jim C. Nasby" <jnasby@pervasive.com>,
+   PostgreSQL-development <pgsql-hackers@postgresql.org>
+Subject: Re: [HACKERS] MERGE vs REPLACE
+Message-ID: <20051122105747.GC12548@svana.org>
+Reply-To: Martijn van Oosterhout <kleptog@svana.org>
+References: <E1539E0ED7043848906A8FF995BDA5799A524D@m0143.s-mxs.net> <1132228373.10890.313.camel@coppola.muc.ecircle.de> <20051117123250.GC22933@svana.org> <1132231474.10890.317.camel@coppola.muc.ecircle.de> <25849.1132238470@sss.pgh.pa.us> <20051117151530.GU6026@ns.snowman.net> <20051121214630.GM19279@pervasive.com> <43828E6C.60406@seznam.cz>
+MIME-Version: 1.0
+Content-Type: multipart/signed; micalg=pgp-sha1;
+       protocol="application/pgp-signature"; boundary="aT9PWwzfKXlsBJM1"
+Content-Disposition: inline
+In-Reply-To: <43828E6C.60406@seznam.cz>
+User-Agent: Mutt/1.3.28i
+X-PGP-Key-ID: Length=1024; ID=0x0DC67BE6
+X-PGP-Key-Fingerprint: 295F A899 A81A 156D B522  48A7 6394 F08A 0DC6 7BE6
+X-PGP-Key-URL: <http://svana.org/kleptog/0DC67BE6.pgp.asc>
+X-Virus-Scanned: by amavisd-new at hub.org
+X-Spam-Status: No, score=0 required=5 tests=[AWL=0.000]
+X-Spam-Score: 0
+X-Mailing-List: pgsql-hackers
+List-Archive: <http://archives.postgresql.org/pgsql-hackers>
+List-Help: <mailto:majordomo@postgresql.org?body=help>
+List-Id: <pgsql-hackers.postgresql.org>
+List-Owner: <mailto:pgsql-hackers-owner@postgresql.org>
+List-Post: <mailto:pgsql-hackers@postgresql.org>
+List-Subscribe: <mailto:majordomo@postgresql.org?body=sub%20pgsql-hackers>
+List-Unsubscribe: <mailto:majordomo@postgresql.org?body=unsub%20pgsql-hackers>
+Precedence: bulk
+Sender: pgsql-hackers-owner@postgresql.org
+Status: OR
+
+
+--aT9PWwzfKXlsBJM1
+Content-Type: text/plain; charset=us-ascii
+Content-Disposition: inline
+Content-Transfer-Encoding: quoted-printable
+
+On Tue, Nov 22, 2005 at 04:20:12AM +0100, Petr Jelinek wrote:
+> It was already said here that oracle and db2 both use MERGE, dunno about=
+=20
+> mssql.
+>=20
+> And yes merge CAN be used to do REPLACE (oracle uses their dummy table=20
+> for this, we can use the fact that FROM clause isn't required in postgres=
+).
+
+Statements about MERGE on the web:
+
+http://www.dba-oracle.com/oracle_tips_rittman_merge.htm
+http://databasejournal.com/features/db2/article.php/3322041
+http://certcities.com/editorial/columns/story.asp?EditorialsID=3D51
+http://publib.boulder.ibm.com/infocenter/ids9help/index.jsp?topic=3D/com.ib=
+m.sqls.doc/sqls578.htm
+http://www.jdixon.dotnetdevelopersjournal.com/i_want_my_sql_2005_merge_stat=
+ement.htm
+http://publib.boulder.ibm.com/infocenter/db2help/topic/com.ibm.db2.udb.doc/=
+admin/r0010873.htm
+http://expertanswercenter.techtarget.com/eac/knowledgebaseAnswer/0,295199,s=
+id63_gci978700,00.html
+
+Not one (*not one!*) of these mentions any special handling of
+duplicate keys. They even go to pains to say that any errors cause
+everything to rollback. The last one is especially interesting:
+
+: Is there any way to capture errors from a MERGE statement? Also, is
+: there any way to know how many records were inserted or updated for the
+: MERGE statement like SQL%ROWCOUNT? Any assistance greatly appreciated.=20
+:
+: You capture errors the same way you would if you were doing regular
+: INSERT and UPDATE statements....with exception handlers. Just include a
+: WHEN OTHERS exception handler in the block where your MERGE statement
+: is and have to display SQLCODE and SQLERRM if an error occurs. Then you
+: can figure out which specific errors are occurring and create
+: individual exception handlers for those.=20
+
+There are even places that tell you how to decompose your MERGE into an
+INSERT plus UPDATE statement. The real advantage of MERGE is that the
+semantics prevent your updating a row you just inserted, which is
+harder in the general case but easy if the executor is handling the
+rows one at a time.
+
+Rather than trying to make MERGE do something it wasn't designed for,
+we should probably be spending our efforts on triggers for error
+conditions. Maybe something like:
+
+CREATE TRIGGER foo AFTER ERROR ON bar EXECUTE baz();
+
+Where baz would be passed NEW and OLD just like a normal trigger and if
+the trigger return NULL, the update is ignored. In the meantime the
+function can divert the insert to another table if it likes. This seems
+like a much more workable and useful addition.
+
+Have a nice day,
+--=20
+Martijn van Oosterhout   <kleptog@svana.org>   http://svana.org/kleptog/
+> Patent. n. Genius is 5% inspiration and 95% perspiration. A patent is a
+> tool for doing 5% of the work and then sitting around waiting for someone
+> else to do the other 95% so you can sue them.
+
+--aT9PWwzfKXlsBJM1
+Content-Type: application/pgp-signature
+Content-Disposition: inline
+
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v1.0.6 (GNU/Linux)
+Comment: For info see http://www.gnupg.org
+
+iD8DBQFDgvmqIB7bNG8LQkwRAr0eAKCBybl6qs2NN6kXG15tiGg+nObK0QCeP+2S
++S9F/7PZ70V8CQmZqqMn6sE=
+=QsDZ
+-----END PGP SIGNATURE-----
+
+--aT9PWwzfKXlsBJM1--
+
+From pgsql-hackers-owner+M76466@postgresql.org Tue Nov 22 15:31:18 2005
+Return-path: <pgsql-hackers-owner+M76466@postgresql.org>
+Received: from ams.hub.org (ams.hub.org [200.46.204.13])
+       by candle.pha.pa.us (8.11.6/8.11.6) with ESMTP id jAMKVHO11734
+       for <pgman@candle.pha.pa.us>; Tue, 22 Nov 2005 15:31:17 -0500 (EST)
+Received: from postgresql.org (svr1.postgresql.org [200.46.204.71])
+       by ams.hub.org (Postfix) with ESMTP id A1AC1C4BC25;
+       Tue, 22 Nov 2005 20:31:15 +0000 (GMT)
+X-Original-To: pgsql-hackers-postgresql.org@localhost.postgresql.org
+Received: from localhost (av.hub.org [200.46.204.144])
+       by svr1.postgresql.org (Postfix) with ESMTP id 354D0DB257
+       for <pgsql-hackers-postgresql.org@localhost.postgresql.org>; Tue, 22 Nov 2005 16:30:47 -0400 (AST)
+Received: from svr1.postgresql.org ([200.46.204.71])
+       by localhost (av.hub.org [200.46.204.144]) (amavisd-new, port 10024)
+       with ESMTP id 15163-07-3
+       for <pgsql-hackers-postgresql.org@localhost.postgresql.org>;
+       Tue, 22 Nov 2005 20:30:47 +0000 (GMT)
+X-Greylist: from auto-whitelisted by SQLgrey-
+Received: from flake.decibel.org (flake.decibel.org [67.100.216.10])
+       by svr1.postgresql.org (Postfix) with ESMTP id 3E9B9DBA86
+       for <pgsql-hackers@postgresql.org>; Tue, 22 Nov 2005 16:30:43 -0400 (AST)
+Received: by flake.decibel.org (Postfix, from userid 1001)
+       id 781A61525F; Tue, 22 Nov 2005 14:30:45 -0600 (CST)
+Date: Tue, 22 Nov 2005 14:30:45 -0600
+From: "Jim C. Nasby" <jnasby@pervasive.com>
+To: Martijn van Oosterhout <kleptog@svana.org>
+cc: Petr Jelinek <pjmodos@seznam.cz>,
+   PostgreSQL-development <pgsql-hackers@postgresql.org>
+Subject: Re: [HACKERS] MERGE vs REPLACE
+Message-ID: <20051122203045.GC99429@pervasive.com>
+References: <E1539E0ED7043848906A8FF995BDA5799A524D@m0143.s-mxs.net> <1132228373.10890.313.camel@coppola.muc.ecircle.de> <20051117123250.GC22933@svana.org> <1132231474.10890.317.camel@coppola.muc.ecircle.de> <25849.1132238470@sss.pgh.pa.us> <20051117151530.GU6026@ns.snowman.net> <20051121214630.GM19279@pervasive.com> <43828E6C.60406@seznam.cz> <20051122105747.GC12548@svana.org>
+MIME-Version: 1.0
+Content-Type: text/plain; charset=us-ascii
+Content-Disposition: inline
+In-Reply-To: <20051122105747.GC12548@svana.org>
+X-Operating-System: FreeBSD 4.11-RELEASE-p10 i386
+X-Distributed: Join the Effort!  http://www.distributed.net
+User-Agent: Mutt/1.5.9i
+X-Virus-Scanned: by amavisd-new at hub.org
+X-Spam-Status: No, score=0.012 required=5 tests=[AWL=0.012]
+X-Spam-Score: 0.012
+X-Mailing-List: pgsql-hackers
+List-Archive: <http://archives.postgresql.org/pgsql-hackers>
+List-Help: <mailto:majordomo@postgresql.org?body=help>
+List-Id: <pgsql-hackers.postgresql.org>
+List-Owner: <mailto:pgsql-hackers-owner@postgresql.org>
+List-Post: <mailto:pgsql-hackers@postgresql.org>
+List-Subscribe: <mailto:majordomo@postgresql.org?body=sub%20pgsql-hackers>
+List-Unsubscribe: <mailto:majordomo@postgresql.org?body=unsub%20pgsql-hackers>
+Precedence: bulk
+Sender: pgsql-hackers-owner@postgresql.org
+Status: OR
+
+On Tue, Nov 22, 2005 at 11:57:48AM +0100, Martijn van Oosterhout wrote:
+<excellent research snipped>
+
+> Rather than trying to make MERGE do something it wasn't designed for,
+> we should probably be spending our efforts on triggers for error
+> conditions. Maybe something like:
+> 
+> CREATE TRIGGER foo AFTER ERROR ON bar EXECUTE baz();
+> 
+> Where baz would be passed NEW and OLD just like a normal trigger and if
+> the trigger return NULL, the update is ignored. In the meantime the
+> function can divert the insert to another table if it likes. This seems
+> like a much more workable and useful addition.
+
+I agree that we shouldn't try and distort MERGE into something fancy.
+The AFTER ERROR trigger is a very interesting idea, since it could
+handle many different cases. But I'm worried that people might not want
+that behavior on by default for everything done against some table. I
+think it'd be better to have some way to specify in a command that
+you want to use some kind of error-handling trigger. Though presumably
+the underlying framework would be same, so it shouldn't be hard to
+support both.
+-- 
+Jim C. Nasby, Sr. Engineering Consultant      jnasby@pervasive.com
+Pervasive Software      http://pervasive.com    work: 512-231-6117
+vcard: http://jim.nasby.net/pervasive.vcf       cell: 512-569-9461
+
+---------------------------(end of broadcast)---------------------------
+TIP 4: Have you searched our list archives?
+
+               http://archives.postgresql.org
+
+From pgsql-hackers-owner+M76499@postgresql.org Wed Nov 23 04:10:09 2005
+Return-path: <pgsql-hackers-owner+M76499@postgresql.org>
+Received: from ams.hub.org (ams.hub.org [200.46.204.13])
+       by candle.pha.pa.us (8.11.6/8.11.6) with ESMTP id jAN9A8O01978
+       for <pgman@candle.pha.pa.us>; Wed, 23 Nov 2005 04:10:09 -0500 (EST)
+Received: from postgresql.org (svr1.postgresql.org [200.46.204.71])
+       by ams.hub.org (Postfix) with ESMTP id 8270EC4BC25;
+       Wed, 23 Nov 2005 09:10:04 +0000 (GMT)
+X-Original-To: pgsql-hackers-postgresql.org@localhost.postgresql.org
+Received: from localhost (av.hub.org [200.46.204.144])
+       by svr1.postgresql.org (Postfix) with ESMTP id 39862DB27A
+       for <pgsql-hackers-postgresql.org@localhost.postgresql.org>; Wed, 23 Nov 2005 05:09:40 -0400 (AST)
+Received: from svr1.postgresql.org ([200.46.204.71])
+       by localhost (av.hub.org [200.46.204.144]) (amavisd-new, port 10024)
+       with ESMTP id 89452-02
+       for <pgsql-hackers-postgresql.org@localhost.postgresql.org>;
+       Wed, 23 Nov 2005 09:09:40 +0000 (GMT)
+X-Greylist: from auto-whitelisted by SQLgrey-
+Received: from svana.org (svana.org [203.20.62.76])
+       by svr1.postgresql.org (Postfix) with ESMTP id C6404DB088
+       for <pgsql-hackers@postgresql.org>; Wed, 23 Nov 2005 05:09:36 -0400 (AST)
+Received: from kleptog by svana.org with local (Exim 3.35 #1 (Debian))
+       id 1Eeqd7-0002FD-00; Wed, 23 Nov 2005 20:09:29 +1100
+Date: Wed, 23 Nov 2005 10:09:29 +0100
+From: Martijn van Oosterhout <kleptog@svana.org>
+To: Petr Jelinek <pjmodos@seznam.cz>
+cc: Jaime Casanova <systemguards@gmail.com>,
+   PostgreSQL-development <pgsql-hackers@postgresql.org>,
+   "Jim C. Nasby" <jnasby@pervasive.com>
+Subject: Re: [HACKERS] MERGE vs REPLACE
+Message-ID: <20051123090926.GA8374@svana.org>
+Reply-To: Martijn van Oosterhout <kleptog@svana.org>
+References: <E1539E0ED7043848906A8FF995BDA5799A524D@m0143.s-mxs.net> <1132228373.10890.313.camel@coppola.muc.ecircle.de> <20051117123250.GC22933@svana.org> <1132231474.10890.317.camel@coppola.muc.ecircle.de> <25849.1132238470@sss.pgh.pa.us> <20051117151530.GU6026@ns.snowman.net> <20051121214630.GM19279@pervasive.com> <43828E6C.60406@seznam.cz> <c2d9e70e0511212307p2cd340fer113de21002be1e94@mail.gmail.com> <4383A8A8.30805@seznam.cz>
+MIME-Version: 1.0
+Content-Type: multipart/signed; micalg=pgp-sha1;
+       protocol="application/pgp-signature"; boundary="fdj2RfSjLxBAspz7"
+Content-Disposition: inline
+In-Reply-To: <4383A8A8.30805@seznam.cz>
+User-Agent: Mutt/1.3.28i
+X-PGP-Key-ID: Length=1024; ID=0x0DC67BE6
+X-PGP-Key-Fingerprint: 295F A899 A81A 156D B522  48A7 6394 F08A 0DC6 7BE6
+X-PGP-Key-URL: <http://svana.org/kleptog/0DC67BE6.pgp.asc>
+X-Virus-Scanned: by amavisd-new at hub.org
+X-Spam-Status: No, score=0 required=5 tests=[AWL=0.000]
+X-Spam-Score: 0
+X-Mailing-List: pgsql-hackers
+List-Archive: <http://archives.postgresql.org/pgsql-hackers>
+List-Help: <mailto:majordomo@postgresql.org?body=help>
+List-Id: <pgsql-hackers.postgresql.org>
+List-Owner: <mailto:pgsql-hackers-owner@postgresql.org>
+List-Post: <mailto:pgsql-hackers@postgresql.org>
+List-Subscribe: <mailto:majordomo@postgresql.org?body=sub%20pgsql-hackers>
+List-Unsubscribe: <mailto:majordomo@postgresql.org?body=unsub%20pgsql-hackers>
+Precedence: bulk
+Sender: pgsql-hackers-owner@postgresql.org
+Status: OR
+
+
+--fdj2RfSjLxBAspz7
+Content-Type: text/plain; charset=us-ascii
+Content-Disposition: inline
+Content-Transfer-Encoding: quoted-printable
+
+On Wed, Nov 23, 2005 at 12:24:24AM +0100, Petr Jelinek wrote:
+> Btw about that keys, oracle gives error on many-to-one or many-to-many=20
+> relationship between the source and target tables.
+
+The standard has something called a "cardinality violation" if the
+to-be-merged table doesn't match 1-1 with the rest of the statement. If
+I had access to an Oracle I'd run two tests on MERGE:
+
+1. Does the joining column have to have an index? For example, make a
+column that's full of unique values but no unique index. According to
+my reading of the the standard, this should still work (just slower).
+
+2. Additionally, only the rows involved in the MERGE need to be
+uniquely referenced, so if you add duplicate values but add a WHERE
+clause to exclude those, it should also work.
+
+My feeling is that requiring an index will limit it's usefulness as a
+general tool.
+
+Have a nice day,
+--=20
+Martijn van Oosterhout   <kleptog@svana.org>   http://svana.org/kleptog/
+> Patent. n. Genius is 5% inspiration and 95% perspiration. A patent is a
+> tool for doing 5% of the work and then sitting around waiting for someone
+> else to do the other 95% so you can sue them.
+
+--fdj2RfSjLxBAspz7
+Content-Type: application/pgp-signature
+Content-Disposition: inline
+
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v1.0.6 (GNU/Linux)
+Comment: For info see http://www.gnupg.org
+
+iD8DBQFDhDHFIB7bNG8LQkwRAq+3AJ4kprR3WbWOegJGf9JTVsNLa11/jQCfTmH8
+6o2CsvPgg1g8uOnjbHoGMHo=
+=D4Cr
+-----END PGP SIGNATURE-----
+
+--fdj2RfSjLxBAspz7--
+
+From pgsql-hackers-owner+M76510@postgresql.org Wed Nov 23 14:25:05 2005
+Return-path: <pgsql-hackers-owner+M76510@postgresql.org>
+Received: from ams.hub.org (ams.hub.org [200.46.204.13])
+       by candle.pha.pa.us (8.11.6/8.11.6) with ESMTP id jANJP4O22462
+       for <pgman@candle.pha.pa.us>; Wed, 23 Nov 2005 14:25:04 -0500 (EST)
+Received: from postgresql.org (svr1.postgresql.org [200.46.204.71])
+       by ams.hub.org (Postfix) with ESMTP id 3EF3EC4BBCD;
+       Wed, 23 Nov 2005 19:25:02 +0000 (GMT)
+X-Original-To: pgsql-hackers-postgresql.org@localhost.postgresql.org
+Received: from localhost (av.hub.org [200.46.204.144])
+       by svr1.postgresql.org (Postfix) with ESMTP id 94C5FDB839
+       for <pgsql-hackers-postgresql.org@localhost.postgresql.org>; Wed, 23 Nov 2005 15:24:39 -0400 (AST)
+Received: from svr1.postgresql.org ([200.46.204.71])
+       by localhost (av.hub.org [200.46.204.144]) (amavisd-new, port 10024)
+       with ESMTP id 81352-06
+       for <pgsql-hackers-postgresql.org@localhost.postgresql.org>;
+       Wed, 23 Nov 2005 19:24:39 +0000 (GMT)
+X-Greylist: delayed 00:31:59.455806 by SQLgrey-
+Received: from mecho.sysmaster.com (unknown [65.119.37.45])
+       by svr1.postgresql.org (Postfix) with ESMTP id 5078FDA7A5
+       for <pgsql-hackers@postgresql.org>; Wed, 23 Nov 2005 15:24:36 -0400 (AST)
+Received: from [127.0.0.1] (office.sysmaster.com [65.113.143.60])
+       by mecho.sysmaster.com (8.11.6/8.11.6) with ESMTP id jANIqMB22433;
+       Wed, 23 Nov 2005 10:52:22 -0800
+Message-ID: <4384BA5F.4080402@sysmaster.com>
+Date: Wed, 23 Nov 2005 10:52:15 -0800
+From: Lyubomir Petrov <lpetrov@sysmaster.com>
+User-Agent: Thunderbird 1.5 (Windows/20051025)
+MIME-Version: 1.0
+To: Martijn van Oosterhout <kleptog@svana.org>
+cc: PostgreSQL-development <pgsql-hackers@postgresql.org>
+Subject: Re: [HACKERS] MERGE vs REPLACE
+References: <E1539E0ED7043848906A8FF995BDA5799A524D@m0143.s-mxs.net> <1132228373.10890.313.camel@coppola.muc.ecircle.de> <20051117123250.GC22933@svana.org> <1132231474.10890.317.camel@coppola.muc.ecircle.de> <25849.1132238470@sss.pgh.pa.us> <20051117151530.GU6026@ns.snowman.net> <20051121214630.GM19279@pervasive.com> <43828E6C.60406@seznam.cz> <c2d9e70e0511212307p2cd340fer113de21002be1e94@mail.gmail.com> <4383A8A8.30805@seznam.cz> <20051123090926.GA8374@svana.org>
+In-Reply-To: <20051123090926.GA8374@svana.org>
+Content-Type: text/plain; charset=ISO-8859-1; format=flowed
+Content-Transfer-Encoding: 7bit
+X-Virus-Scanned: by amavisd-new at hub.org
+X-Spam-Status: No, score=0 required=5 tests=[none]
+X-Spam-Score: 0
+X-Mailing-List: pgsql-hackers
+List-Archive: <http://archives.postgresql.org/pgsql-hackers>
+List-Help: <mailto:majordomo@postgresql.org?body=help>
+List-Id: <pgsql-hackers.postgresql.org>
+List-Owner: <mailto:pgsql-hackers-owner@postgresql.org>
+List-Post: <mailto:pgsql-hackers@postgresql.org>
+List-Subscribe: <mailto:majordomo@postgresql.org?body=sub%20pgsql-hackers>
+List-Unsubscribe: <mailto:majordomo@postgresql.org?body=unsub%20pgsql-hackers>
+Precedence: bulk
+Sender: pgsql-hackers-owner@postgresql.org
+Status: OR
+
+Martijn,
+
+Here is a quick test (Oracle 10.1.0.3/Linux):
+
+
+SQL> select banner from v$version;
+BANNER
+----------------------------------------------------------------
+Oracle Database 10g Enterprise Edition Release 10.1.0.3.0 - Prod
+PL/SQL Release 10.1.0.3.0 - Production
+CORE    10.1.0.3.0      Production
+TNS for Linux: Version 10.1.0.3.0 - Production
+NLSRTL Version 10.1.0.3.0 - Production
+
+SQL> select * from merge_test_1;
+        ID NAME
+---------- --------------------
+         1 aaa
+         2 bbb
+         3 ccc
+         4 ddd
+         5 eee
+         1 xxx
+6 rows selected.
+
+SQL> select * from merge_test_2;
+        ID NAME
+---------- --------------------
+         1 AAA
+         2 BBB
+         6 FFF
+
+SQL> select index_name from user_indexes where table_name like 
+'merge_test%';
+no rows selected
+
+SQL> merge into merge_test_1 a1
+  2  using merge_test_2 a2
+  3      on (a1.id = a2.id)
+  4  when matched then
+  5      update set a1.name = a2.name
+  6  when not matched then
+  7      insert (id, name) values (a2.id, a2.name);
+4 rows merged.
+
+SQL> select * from merge_test_1;
+        ID NAME
+---------- --------------------
+         1 AAA
+         2 BBB
+         3 ccc
+         4 ddd
+         5 eee
+         1 AAA
+         6 FFF
+7 rows selected.
+
+
+
+Regards,
+Lubomir Petrov
+
+
+
+Martijn van Oosterhout wrote:
+> On Wed, Nov 23, 2005 at 12:24:24AM +0100, Petr Jelinek wrote:
+>   
+>> Btw about that keys, oracle gives error on many-to-one or many-to-many 
+>> relationship between the source and target tables.
+>>     
+>
+> The standard has something called a "cardinality violation" if the
+> to-be-merged table doesn't match 1-1 with the rest of the statement. If
+> I had access to an Oracle I'd run two tests on MERGE:
+>
+> 1. Does the joining column have to have an index? For example, make a
+> column that's full of unique values but no unique index. According to
+> my reading of the the standard, this should still work (just slower).
+>
+> 2. Additionally, only the rows involved in the MERGE need to be
+> uniquely referenced, so if you add duplicate values but add a WHERE
+> clause to exclude those, it should also work.
+>
+> My feeling is that requiring an index will limit it's usefulness as a
+> general tool.
+>
+> Have a nice day,
+>   
+
+
+---------------------------(end of broadcast)---------------------------
+TIP 3: Have you checked our extensive FAQ?
+
+               http://www.postgresql.org/docs/faq
+
+From pgsql-hackers-owner+M76513@postgresql.org Wed Nov 23 17:23:34 2005
+Return-path: <pgsql-hackers-owner+M76513@postgresql.org>
+Received: from ams.hub.org (ams.hub.org [200.46.204.13])
+       by candle.pha.pa.us (8.11.6/8.11.6) with ESMTP id jANMNXO20323
+       for <pgman@candle.pha.pa.us>; Wed, 23 Nov 2005 17:23:33 -0500 (EST)
+Received: from postgresql.org (svr1.postgresql.org [200.46.204.71])
+       by ams.hub.org (Postfix) with ESMTP id C020EC4A48E;
+       Wed, 23 Nov 2005 22:23:30 +0000 (GMT)
+X-Original-To: pgsql-hackers-postgresql.org@localhost.postgresql.org
+Received: from localhost (av.hub.org [200.46.204.144])
+       by svr1.postgresql.org (Postfix) with ESMTP id 03F71DBAA3
+       for <pgsql-hackers-postgresql.org@localhost.postgresql.org>; Wed, 23 Nov 2005 18:23:06 -0400 (AST)
+Received: from svr1.postgresql.org ([200.46.204.71])
+       by localhost (av.hub.org [200.46.204.144]) (amavisd-new, port 10024)
+       with ESMTP id 92598-01
+       for <pgsql-hackers-postgresql.org@localhost.postgresql.org>;
+       Wed, 23 Nov 2005 22:23:06 +0000 (GMT)
+X-Greylist: from auto-whitelisted by SQLgrey-
+Received: from smtp018.mail.yahoo.com (smtp018.mail.yahoo.com [216.136.174.115])
+       by svr1.postgresql.org (Postfix) with SMTP id 121D3DBA93
+       for <pgsql-hackers@postgresql.org>; Wed, 23 Nov 2005 18:23:01 -0400 (AST)
+Received: (qmail 47652 invoked from network); 23 Nov 2005 22:22:56 -0000
+DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws;
+  s=s1024; d=Yahoo.com;
+  h=Received:Message-ID:Date:From:User-Agent:X-Accept-Language:MIME-Version:To:CC:Subject:References:In-Reply-To:Content-Type:Content-Transfer-Encoding;
+  b=ikj/Ob+3p22lsO9ikWyS1RkIbs6fq47zO2HF4jU7ZStjg5F/smOj0F+YkTeoepYDBoiKtd5pr0vxODe6iSXdUmQgXKe4BvzaypEm8KFqgR2kKtlpW/QAy1arUUnD1DoFpx/SJgPFt1V4S//lgGTpWw5v99EeoYfapzNmNV0hgQI=  ;
+Received: from unknown (HELO jupiter.black-lion.info) (janwieck@68.80.245.191 with login)
+  by smtp018.mail.yahoo.com with SMTP; 23 Nov 2005 22:22:55 -0000
+Received: from [172.21.8.23] (mars.black-lion.info [192.168.192.101])
+       (authenticated bits=0)
+       by jupiter.black-lion.info (8.12.10/8.12.9) with ESMTP id jANLtT1o054955;
+       Wed, 23 Nov 2005 16:55:29 -0500 (EST)
+       (envelope-from JanWieck@Yahoo.com)
+Message-ID: <4384E54D.8000500@Yahoo.com>
+Date: Wed, 23 Nov 2005 16:55:25 -0500
+From: Jan Wieck <JanWieck@Yahoo.com>
+User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.1) Gecko/20040707
+X-Accept-Language: en-us, en
+MIME-Version: 1.0
+To: Tom Lane <tgl@sss.pgh.pa.us>
+cc: Peter Eisentraut <peter_e@gmx.net>, pgsql-hackers@postgresql.org,
+   Josh Berkus <josh@agliodbs.com>, Jaime Casanova <systemguards@gmail.com>
+Subject: Re: [HACKERS] someone working to add merge?
+References: <c2d9e70e0511110603q1799d811u6e4564be516b10ce@mail.gmail.com> <200511111924.41532.peter_e@gmx.net> <20561.1131734697@sss.pgh.pa.us> <200511112004.35876.peter_e@gmx.net> <20899.1131736841@sss.pgh.pa.us>
+In-Reply-To: <20899.1131736841@sss.pgh.pa.us>
+Content-Type: text/plain; charset=us-ascii; format=flowed
+Content-Transfer-Encoding: 7bit
+X-Virus-Scanned: by amavisd-new at hub.org
+X-Spam-Status: No, score=0.359 required=5 tests=[AWL=-0.120,
+       DNS_FROM_RFC_ABUSE=0.479]
+X-Spam-Score: 0.359
+X-Mailing-List: pgsql-hackers
+List-Archive: <http://archives.postgresql.org/pgsql-hackers>
+List-Help: <mailto:majordomo@postgresql.org?body=help>
+List-Id: <pgsql-hackers.postgresql.org>
+List-Owner: <mailto:pgsql-hackers-owner@postgresql.org>
+List-Post: <mailto:pgsql-hackers@postgresql.org>
+List-Subscribe: <mailto:majordomo@postgresql.org?body=sub%20pgsql-hackers>
+List-Unsubscribe: <mailto:majordomo@postgresql.org?body=unsub%20pgsql-hackers>
+Precedence: bulk
+Sender: pgsql-hackers-owner@postgresql.org
+Status: OR
+
+On 11/11/2005 2:20 PM, Tom Lane wrote:
+
+> Peter Eisentraut <peter_e@gmx.net> writes:
+>> Tom Lane wrote:
+>>> Surely they require a unique constraint --- else the behavior isn't
+>>> even well defined, is it?
+> 
+>> They require that the merge condition does not match for more than one 
+>> row, but since the merge condition can do just about anything, there is 
+>> no guarantee that a unique constraint encompasses it.
+> 
+> ISTM to be a reasonable implementation restriction that there be a
+> constraint by which the system can prove that there is at most one
+> matching row.  Per other comments in this thread, we'd not be the only
+> implementation making such a restriction.
+> 
+> (Certainly, if I were a DBA and were told that the performance of MERGE
+> would go to hell in a handbasket if I had no such constraint, I'd make
+> sure there was one.  I don't think there is very much of a use-case for
+> the general scenario.)
+
+Such restriction does look reasonable. Especially because ...
+
+The largest problem I see with MERGE is the question of BEFORE triggers. 
+Consider a BEFORE INSERT trigger that modifies a third table, after 
+which the constraint or whatever post-heap_insert-attempt we might use 
+detects a conflict. How do we undo the actions of the BEFORE trigger? 
+The only way to do that is to plan the query as a nestloop, with the 
+USING part as the outer loop. If the (updating) scan of the INTO 
+relation did not hit any tuple, then do the INSERT. We can only undo the 
+side effects of any BEFORE trigger by wrapping each and evey nested INTO 
+relation insert attempt into its own subtransaction.
+
+Sure, we "could" of course do the insert and then rescan the whole thing 
+with read-committed to see if our row is now the only one ... needless 
+to say that in the case of a sequential scan inside the loop, that 
+nestloop will suck big times even without that second scan. But ... hmmm 
+... we could get away with that and if we don't find a constraint that 
+will ensure uniqueness, then we do a rescan to check for it. But I would 
+vote for a "please_no_notice_about_stupid_usage_of_merge" runtime option 
+that suppresses the corresponding NOTICE.
+
+
+Jan
+
+-- 
+#======================================================================#
+# It's easier to get forgiveness for being wrong than for being right. #
+# Let's break this rule - forgive me.                                  #
+#================================================== JanWieck@Yahoo.com #
+
+---------------------------(end of broadcast)---------------------------
+TIP 4: Have you searched our list archives?
+
+               http://archives.postgresql.org
+
+From pgsql-hackers-owner+M76524@postgresql.org Thu Nov 24 01:31:30 2005
+Return-path: <pgsql-hackers-owner+M76524@postgresql.org>
+Received: from ams.hub.org (ams.hub.org [200.46.204.13])
+       by candle.pha.pa.us (8.11.6/8.11.6) with ESMTP id jAO6VTO16396
+       for <pgman@candle.pha.pa.us>; Thu, 24 Nov 2005 01:31:30 -0500 (EST)
+Received: from postgresql.org (svr1.postgresql.org [200.46.204.71])
+       by ams.hub.org (Postfix) with ESMTP id D9160C4A48E;
+       Thu, 24 Nov 2005 06:31:25 +0000 (GMT)
+X-Original-To: pgsql-hackers-postgresql.org@localhost.postgresql.org
+Received: from localhost (av.hub.org [200.46.204.144])
+       by svr1.postgresql.org (Postfix) with ESMTP id 42FE3DBC43
+       for <pgsql-hackers-postgresql.org@localhost.postgresql.org>; Thu, 24 Nov 2005 02:31:01 -0400 (AST)
+Received: from svr1.postgresql.org ([200.46.204.71])
+       by localhost (av.hub.org [200.46.204.144]) (amavisd-new, port 10024)
+       with ESMTP id 56362-10
+       for <pgsql-hackers-postgresql.org@localhost.postgresql.org>;
+       Thu, 24 Nov 2005 06:31:00 +0000 (GMT)
+X-Greylist: from auto-whitelisted by SQLgrey-
+Received: from svana.org (svana.org [203.20.62.76])
+       by svr1.postgresql.org (Postfix) with ESMTP id A1169DBC30
+       for <pgsql-hackers@postgresql.org>; Thu, 24 Nov 2005 02:30:58 -0400 (AST)
+Received: from kleptog by svana.org with local (Exim 3.35 #1 (Debian))
+       id 1EfAcw-0004xu-00; Thu, 24 Nov 2005 17:30:38 +1100
+Date: Thu, 24 Nov 2005 07:30:37 +0100
+From: Martijn van Oosterhout <kleptog@svana.org>
+To: Jan Wieck <JanWieck@Yahoo.com>
+cc: Tom Lane <tgl@sss.pgh.pa.us>, Peter Eisentraut <peter_e@gmx.net>,
+   pgsql-hackers@postgresql.org, Josh Berkus <josh@agliodbs.com>,
+   Jaime Casanova <systemguards@gmail.com>
+Subject: Re: [HACKERS] someone working to add merge?
+Message-ID: <20051124063034.GA18750@svana.org>
+Reply-To: Martijn van Oosterhout <kleptog@svana.org>
+References: <c2d9e70e0511110603q1799d811u6e4564be516b10ce@mail.gmail.com> <200511111924.41532.peter_e@gmx.net> <20561.1131734697@sss.pgh.pa.us> <200511112004.35876.peter_e@gmx.net> <20899.1131736841@sss.pgh.pa.us> <4384E54D.8000500@Yahoo.com>
+MIME-Version: 1.0
+Content-Type: multipart/signed; micalg=pgp-sha1;
+       protocol="application/pgp-signature"; boundary="45Z9DzgjV8m4Oswq"
+Content-Disposition: inline
+In-Reply-To: <4384E54D.8000500@Yahoo.com>
+User-Agent: Mutt/1.3.28i
+X-PGP-Key-ID: Length=1024; ID=0x0DC67BE6
+X-PGP-Key-Fingerprint: 295F A899 A81A 156D B522  48A7 6394 F08A 0DC6 7BE6
+X-PGP-Key-URL: <http://svana.org/kleptog/0DC67BE6.pgp.asc>
+X-Virus-Scanned: by amavisd-new at hub.org
+X-Spam-Status: No, score=0 required=5 tests=[AWL=0.000]
+X-Spam-Score: 0
+X-Mailing-List: pgsql-hackers
+List-Archive: <http://archives.postgresql.org/pgsql-hackers>
+List-Help: <mailto:majordomo@postgresql.org?body=help>
+List-Id: <pgsql-hackers.postgresql.org>
+List-Owner: <mailto:pgsql-hackers-owner@postgresql.org>
+List-Post: <mailto:pgsql-hackers@postgresql.org>
+List-Subscribe: <mailto:majordomo@postgresql.org?body=sub%20pgsql-hackers>
+List-Unsubscribe: <mailto:majordomo@postgresql.org?body=unsub%20pgsql-hackers>
+Precedence: bulk
+Sender: pgsql-hackers-owner@postgresql.org
+Status: OR
+
+
+--45Z9DzgjV8m4Oswq
+Content-Type: text/plain; charset=us-ascii
+Content-Disposition: inline
+Content-Transfer-Encoding: quoted-printable
+
+On Wed, Nov 23, 2005 at 04:55:25PM -0500, Jan Wieck wrote:
+> The largest problem I see with MERGE is the question of BEFORE triggers.=
+=20
+> Consider a BEFORE INSERT trigger that modifies a third table, after=20
+> which the constraint or whatever post-heap_insert-attempt we might use=20
+> detects a conflict. How do we undo the actions of the BEFORE trigger?=20
+> The only way to do that is to plan the query as a nestloop, with the=20
+> USING part as the outer loop. If the (updating) scan of the INTO=20
+> relation did not hit any tuple, then do the INSERT. We can only undo the=
+=20
+> side effects of any BEFORE trigger by wrapping each and evey nested INTO=
+=20
+> relation insert attempt into its own subtransaction.
+
+Umm, if there are any errors you abort the transaction, just like any
+other case. ACID requires that either the whole statement is done, or
+none. If a trigger causes the INSERT or UPDATE to fail you have no
+choice but to abort the transaction.
+
+Besides, someone posted an example on Oracle, they don't require an
+index so I don't think we realistically can say that people need one.
+If two concurrent MERGEs, which can't see eachothers output, both end
+up INSERTing, that not an error unless the user has a UNIQUE
+constraint, so the problem vanishes.
+
+Have a nice day,
+--=20
+Martijn van Oosterhout   <kleptog@svana.org>   http://svana.org/kleptog/
+> Patent. n. Genius is 5% inspiration and 95% perspiration. A patent is a
+> tool for doing 5% of the work and then sitting around waiting for someone
+> else to do the other 95% so you can sue them.
+
+--45Z9DzgjV8m4Oswq
+Content-Type: application/pgp-signature
+Content-Disposition: inline
+
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v1.0.6 (GNU/Linux)
+Comment: For info see http://www.gnupg.org
+
+iD8DBQFDhV4HIB7bNG8LQkwRAgXZAKCBD3QOdBVT3GmCqEQj9tfapJq38QCeOdvW
+VXixm+YDkCCWkSLEQcUtixM=
+=3H5a
+-----END PGP SIGNATURE-----
+
+--45Z9DzgjV8m4Oswq--
+
+From pgsql-hackers-owner+M76549@postgresql.org Thu Nov 24 11:12:14 2005
+Return-path: <pgsql-hackers-owner+M76549@postgresql.org>
+Received: from ams.hub.org (ams.hub.org [200.46.204.13])
+       by candle.pha.pa.us (8.11.6/8.11.6) with ESMTP id jAOGCDO07384
+       for <pgman@candle.pha.pa.us>; Thu, 24 Nov 2005 11:12:13 -0500 (EST)
+Received: from postgresql.org (svr1.postgresql.org [200.46.204.71])
+       by ams.hub.org (Postfix) with ESMTP id 305F4C4A48E;
+       Thu, 24 Nov 2005 16:12:12 +0000 (GMT)
+X-Original-To: pgsql-hackers-postgresql.org@localhost.postgresql.org
+Received: from localhost (av.hub.org [200.46.204.144])
+       by svr1.postgresql.org (Postfix) with ESMTP id 6A539DBC1D
+       for <pgsql-hackers-postgresql.org@localhost.postgresql.org>; Thu, 24 Nov 2005 12:11:46 -0400 (AST)
+Received: from svr1.postgresql.org ([200.46.204.71])
+       by localhost (av.hub.org [200.46.204.144]) (amavisd-new, port 10024)
+       with ESMTP id 60324-06-2
+       for <pgsql-hackers-postgresql.org@localhost.postgresql.org>;
+       Thu, 24 Nov 2005 16:11:44 +0000 (GMT)
+X-Greylist: from auto-whitelisted by SQLgrey-
+Received: from smtp011.mail.yahoo.com (smtp011.mail.yahoo.com [216.136.173.31])
+       by svr1.postgresql.org (Postfix) with SMTP id 11B74DBBF3
+       for <pgsql-hackers@postgresql.org>; Thu, 24 Nov 2005 12:11:42 -0400 (AST)
+Received: (qmail 72237 invoked from network); 24 Nov 2005 16:11:41 -0000
+DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws;
+  s=s1024; d=Yahoo.com;
+  h=Received:Message-ID:Date:From:User-Agent:X-Accept-Language:MIME-Version:To:CC:Subject:References:In-Reply-To:Content-Type:Content-Transfer-Encoding;
+  b=dgj7516dhcBQJ4gSnC2f7PmbQi7TxXH8v8ahOhOPDm/53Yj9wVKNG2jTbp+j2crVe+Tw7VA5EEhS2YqaHTmD8Fs3np6yVP4J1VN/SF7+aywZkiiRJUSEAe3qYpGIGRFxtnKr3K3M6TufdeJZuEKu4O3YCW+IZi8SCulBwKV5jfM=  ;
+Received: from unknown (HELO jupiter.black-lion.info) (janwieck@68.80.245.191 with login)
+  by smtp011.mail.yahoo.com with SMTP; 24 Nov 2005 16:11:41 -0000
+Received: from [172.21.8.23] (mars.black-lion.info [192.168.192.101])
+       (authenticated bits=0)
+       by jupiter.black-lion.info (8.12.10/8.12.9) with ESMTP id jAOGBc1o058226;
+       Thu, 24 Nov 2005 11:11:38 -0500 (EST)
+       (envelope-from JanWieck@Yahoo.com)
+Message-ID: <4385E636.4070503@Yahoo.com>
+Date: Thu, 24 Nov 2005 11:11:34 -0500
+From: Jan Wieck <JanWieck@Yahoo.com>
+User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.1) Gecko/20040707
+X-Accept-Language: en-us, en
+MIME-Version: 1.0
+To: Martijn van Oosterhout <kleptog@svana.org>
+cc: Tom Lane <tgl@sss.pgh.pa.us>, Peter Eisentraut <peter_e@gmx.net>,
+   pgsql-hackers@postgresql.org, Josh Berkus <josh@agliodbs.com>,
+   Jaime Casanova <systemguards@gmail.com>
+Subject: Re: [HACKERS] someone working to add merge?
+References: <c2d9e70e0511110603q1799d811u6e4564be516b10ce@mail.gmail.com> <200511111924.41532.peter_e@gmx.net> <20561.1131734697@sss.pgh.pa.us> <200511112004.35876.peter_e@gmx.net> <20899.1131736841@sss.pgh.pa.us> <4384E54D.8000500@Yahoo.com> <20051124063034.GA18750@svana.org>
+In-Reply-To: <20051124063034.GA18750@svana.org>
+Content-Type: text/plain; charset=us-ascii; format=flowed
+Content-Transfer-Encoding: 7bit
+X-Virus-Scanned: by amavisd-new at hub.org
+X-Spam-Status: No, score=0.359 required=5 tests=[AWL=-0.120,
+       DNS_FROM_RFC_ABUSE=0.479]
+X-Spam-Score: 0.359
+X-Mailing-List: pgsql-hackers
+List-Archive: <http://archives.postgresql.org/pgsql-hackers>
+List-Help: <mailto:majordomo@postgresql.org?body=help>
+List-Id: <pgsql-hackers.postgresql.org>
+List-Owner: <mailto:pgsql-hackers-owner@postgresql.org>
+List-Post: <mailto:pgsql-hackers@postgresql.org>
+List-Subscribe: <mailto:majordomo@postgresql.org?body=sub%20pgsql-hackers>
+List-Unsubscribe: <mailto:majordomo@postgresql.org?body=unsub%20pgsql-hackers>
+Precedence: bulk
+Sender: pgsql-hackers-owner@postgresql.org
+Status: OR
+
+On 11/24/2005 1:30 AM, Martijn van Oosterhout wrote:
+
+> On Wed, Nov 23, 2005 at 04:55:25PM -0500, Jan Wieck wrote:
+>> The largest problem I see with MERGE is the question of BEFORE triggers. 
+>> Consider a BEFORE INSERT trigger that modifies a third table, after 
+>> which the constraint or whatever post-heap_insert-attempt we might use 
+>> detects a conflict. How do we undo the actions of the BEFORE trigger? 
+>> The only way to do that is to plan the query as a nestloop, with the 
+>> USING part as the outer loop. If the (updating) scan of the INTO 
+>> relation did not hit any tuple, then do the INSERT. We can only undo the 
+>> side effects of any BEFORE trigger by wrapping each and evey nested INTO 
+>> relation insert attempt into its own subtransaction.
+> 
+> Umm, if there are any errors you abort the transaction, just like any
+> other case. ACID requires that either the whole statement is done, or
+> none. If a trigger causes the INSERT or UPDATE to fail you have no
+> choice but to abort the transaction.
+
+I guess you misunderstood. What I am talking about is a problem in the 
+order of execution. since we don't have predicate locking, there is a 
+possibility that our implementation of MERGE decides to do an INSERT 
+while another transaction does the same. What has to happen is that the 
+BEFORE INSERT trigger is called, then the heap tuple inserted, then the 
+index tuples created. At this time, the duplicate key error occurs, 
+telling us that we had a conflict and that we have to try an UPDATE 
+instead. That means, in the end this particular row's INSERT has never 
+happened and we have to undo the BEFORE INSERT triggers actions too.
+
+> 
+> Besides, someone posted an example on Oracle, they don't require an
+> index so I don't think we realistically can say that people need one.
+> If two concurrent MERGEs, which can't see eachothers output, both end
+> up INSERTing, that not an error unless the user has a UNIQUE
+> constraint, so the problem vanishes.
+
+Not following the semantics is an error. MERGE is not supposed to do 
+multiple inserts for the same match, concurrency or not.
+
+
+Jan
+
+-- 
+#======================================================================#
+# It's easier to get forgiveness for being wrong than for being right. #
+# Let's break this rule - forgive me.                                  #
+#================================================== JanWieck@Yahoo.com #
+
+---------------------------(end of broadcast)---------------------------
+TIP 4: Have you searched our list archives?
+
+               http://archives.postgresql.org
+
+From pgsql-hackers-owner+M76581@postgresql.org Fri Nov 25 07:14:48 2005
+Return-path: <pgsql-hackers-owner+M76581@postgresql.org>
+Received: from ams.hub.org (ams.hub.org [200.46.204.13])
+       by candle.pha.pa.us (8.11.6/8.11.6) with ESMTP id jAPCElB26143
+       for <pgman@candle.pha.pa.us>; Fri, 25 Nov 2005 07:14:47 -0500 (EST)
+Received: from postgresql.org (svr1.postgresql.org [200.46.204.71])
+       by ams.hub.org (Postfix) with ESMTP id 46071C4BC79;
+       Fri, 25 Nov 2005 12:14:46 +0000 (GMT)
+X-Original-To: pgsql-hackers-postgresql.org@localhost.postgresql.org
+Received: from localhost (av.hub.org [200.46.204.144])
+       by svr1.postgresql.org (Postfix) with ESMTP id A32A1D72AA
+       for <pgsql-hackers-postgresql.org@localhost.postgresql.org>; Fri, 25 Nov 2005 08:14:18 -0400 (AST)
+Received: from svr1.postgresql.org ([200.46.204.71])
+       by localhost (av.hub.org [200.46.204.144]) (amavisd-new, port 10024)
+       with ESMTP id 86344-02
+       for <pgsql-hackers-postgresql.org@localhost.postgresql.org>;
+       Fri, 25 Nov 2005 12:14:19 +0000 (GMT)
+X-Greylist: from auto-whitelisted by SQLgrey-
+Received: from svana.org (svana.org [203.20.62.76])
+       by svr1.postgresql.org (Postfix) with ESMTP id 14D00D6FFA
+       for <pgsql-hackers@postgresql.org>; Fri, 25 Nov 2005 08:14:14 -0400 (AST)
+Received: from kleptog by svana.org with local (Exim 3.35 #1 (Debian))
+       id 1EfcSp-00058u-00; Fri, 25 Nov 2005 23:14:03 +1100
+Date: Fri, 25 Nov 2005 13:14:03 +0100
+From: Martijn van Oosterhout <kleptog@svana.org>
+To: Jan Wieck <JanWieck@Yahoo.com>
+cc: Tom Lane <tgl@sss.pgh.pa.us>, Peter Eisentraut <peter_e@gmx.net>,
+   pgsql-hackers@postgresql.org, Josh Berkus <josh@agliodbs.com>,
+   Jaime Casanova <systemguards@gmail.com>
+Subject: Re: [HACKERS] someone working to add merge?
+Message-ID: <20051125121402.GB16970@svana.org>
+Reply-To: Martijn van Oosterhout <kleptog@svana.org>
+References: <c2d9e70e0511110603q1799d811u6e4564be516b10ce@mail.gmail.com> <200511111924.41532.peter_e@gmx.net> <20561.1131734697@sss.pgh.pa.us> <200511112004.35876.peter_e@gmx.net> <20899.1131736841@sss.pgh.pa.us> <4384E54D.8000500@Yahoo.com> <20051124063034.GA18750@svana.org> <4385E636.4070503@Yahoo.com>
+MIME-Version: 1.0
+Content-Type: multipart/signed; micalg=pgp-sha1;
+       protocol="application/pgp-signature"; boundary="2B/JsCI69OhZNC5r"
+Content-Disposition: inline
+In-Reply-To: <4385E636.4070503@Yahoo.com>
+User-Agent: Mutt/1.3.28i
+X-PGP-Key-ID: Length=1024; ID=0x0DC67BE6
+X-PGP-Key-Fingerprint: 295F A899 A81A 156D B522  48A7 6394 F08A 0DC6 7BE6
+X-PGP-Key-URL: <http://svana.org/kleptog/0DC67BE6.pgp.asc>
+X-Virus-Scanned: by amavisd-new at hub.org
+X-Spam-Status: No, score=0 required=5 tests=[AWL=0.000]
+X-Spam-Score: 0
+X-Mailing-List: pgsql-hackers
+List-Archive: <http://archives.postgresql.org/pgsql-hackers>
+List-Help: <mailto:majordomo@postgresql.org?body=help>
+List-Id: <pgsql-hackers.postgresql.org>
+List-Owner: <mailto:pgsql-hackers-owner@postgresql.org>
+List-Post: <mailto:pgsql-hackers@postgresql.org>
+List-Subscribe: <mailto:majordomo@postgresql.org?body=sub%20pgsql-hackers>
+List-Unsubscribe: <mailto:majordomo@postgresql.org?body=unsub%20pgsql-hackers>
+Precedence: bulk
+Sender: pgsql-hackers-owner@postgresql.org
+Status: OR
+
+
+--2B/JsCI69OhZNC5r
+Content-Type: text/plain; charset=us-ascii
+Content-Disposition: inline
+Content-Transfer-Encoding: quoted-printable
+
+On Thu, Nov 24, 2005 at 11:11:34AM -0500, Jan Wieck wrote:
+> On 11/24/2005 1:30 AM, Martijn van Oosterhout wrote:
+> >Umm, if there are any errors you abort the transaction, just like any
+> >other case. ACID requires that either the whole statement is done, or
+> >none. If a trigger causes the INSERT or UPDATE to fail you have no
+> >choice but to abort the transaction.
+>=20
+> I guess you misunderstood. What I am talking about is a problem in the=20
+> order of execution. since we don't have predicate locking, there is a=20
+> possibility that our implementation of MERGE decides to do an INSERT=20
+> while another transaction does the same. What has to happen is that the=
+=20
+> BEFORE INSERT trigger is called, then the heap tuple inserted, then the=
+=20
+> index tuples created. At this time, the duplicate key error occurs,=20
+> telling us that we had a conflict and that we have to try an UPDATE=20
+> instead. That means, in the end this particular row's INSERT has never=20
+> happened and we have to undo the BEFORE INSERT triggers actions too.
+
+But I'm not sure we're supposed to handle that case anyway. Oracle at
+least doesn't require an index on the table being merged. And if I look
+at it from a visibility view point, if someone else does an INSERT in
+another transaction, then MERGE cannot see it and thus it will INSERT
+too. This isn't an error.
+
+Consider the case of a deferred unique constraint (Postgres doesn't
+support these yet but bear with me). Say in one session you start a
+transaction, do a MERGE and then a few other statements. In the
+meantime in another session someone inserts a row on the table you
+merged. Are you asserting that the first session should undo
+everything, do an UPDATE instead of an INSERT and redo all your queries
+since? Obviously not.
+
+Though the above relies on something Postgres doesn't support, but you
+would be able to emulate the some without a unique key. For example:
+
+Session 1:
+CREATE TEMP TABLE foo (id integer, val integer);
+
+BEGIN;
+SELECT * FROM foo;
+
+Session 2:
+BEGIN;
+
+INSERT INTO foo (1,3);
+
+Session 1:
+MERGE INTO foo
+  USING (SELECT 1)
+  ON (foo.id =3D 1)
+  WHEN MATCHED THEN UPDATE SET val =3D 1
+  WHEN NOT MATCHED THEN INSERT (id,val) VALUES (1,2);
+
+Session 2:
+COMMIT;
+
+Session 1:
+COMMIT;
+
+Now, (IMO) in serializable mode, the MERGE should block on reading the
+row inserted by the second session and when that commits do the UPDATE,
+thus leaving you with a table with one row (1.1).
+
+In read committed mode, the MERGE shouldn't block and you should end up
+with a table with two rows (1,3) and (1,2).
+
+If you switch the order of the insert and merge you should get the same
+results in both cases, (1,2) and (1,3).
+
+I think you are arguing that the result should be (1,1) in all cases. I
+honestly don't see how that is feasible and certainly not supported by
+my reading of the standard. I would be interested to know how other
+databases handle the above case.
+
+> Not following the semantics is an error. MERGE is not supposed to do=20
+> multiple inserts for the same match, concurrency or not.
+
+Yes, any single MERGE cannot insert twice. However, two MERGEs running
+concurrently, or a MERGE with an INSERT/UPDATE/DELETE in another
+session could very well end up with multiple rows on the same key. I
+maintain that MERGE has no special rules w.r.t. visibility or locking
+and we should not be acting as if it does. If at the end of the
+transaction there a duplicate key we should throw the error and let the
+client deal with it.
+
+Have a nice day,
+--=20
+Martijn van Oosterhout   <kleptog@svana.org>   http://svana.org/kleptog/
+> Patent. n. Genius is 5% inspiration and 95% perspiration. A patent is a
+> tool for doing 5% of the work and then sitting around waiting for someone
+> else to do the other 95% so you can sue them.
+
+--2B/JsCI69OhZNC5r
+Content-Type: application/pgp-signature
+Content-Disposition: inline
+
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v1.0.6 (GNU/Linux)
+Comment: For info see http://www.gnupg.org
+
+iD8DBQFDhwAKIB7bNG8LQkwRAvpQAJsHNO/wnfcH0QwNQ7AKXkV5CzCz9wCfVJBH
+/iCYKxdxjTOkw6+M2PgPAjY=
+=ERXt
+-----END PGP SIGNATURE-----
+
+--2B/JsCI69OhZNC5r--
+
+From pgsql-hackers-owner+M76584@postgresql.org Fri Nov 25 09:15:33 2005
+Return-path: <pgsql-hackers-owner+M76584@postgresql.org>
+Received: from ams.hub.org (ams.hub.org [200.46.204.13])
+       by candle.pha.pa.us (8.11.6/8.11.6) with ESMTP id jAPEFWB13482
+       for <pgman@candle.pha.pa.us>; Fri, 25 Nov 2005 09:15:32 -0500 (EST)
+Received: from postgresql.org (svr1.postgresql.org [200.46.204.71])
+       by ams.hub.org (Postfix) with ESMTP id AFCB6C4BC79;
+       Fri, 25 Nov 2005 14:15:30 +0000 (GMT)
+X-Original-To: pgsql-hackers-postgresql.org@localhost.postgresql.org
+Received: from localhost (av.hub.org [200.46.204.144])
+       by svr1.postgresql.org (Postfix) with ESMTP id 039CCD774A
+       for <pgsql-hackers-postgresql.org@localhost.postgresql.org>; Fri, 25 Nov 2005 10:14:59 -0400 (AST)
+Received: from svr1.postgresql.org ([200.46.204.71])
+       by localhost (av.hub.org [200.46.204.144]) (amavisd-new, port 10024)
+       with ESMTP id 13125-10
+       for <pgsql-hackers-postgresql.org@localhost.postgresql.org>;
+       Fri, 25 Nov 2005 14:15:01 +0000 (GMT)
+X-Greylist: from auto-whitelisted by SQLgrey-
+Received: from smtp015.mail.yahoo.com (smtp015.mail.yahoo.com [216.136.173.59])
+       by svr1.postgresql.org (Postfix) with SMTP id 55EA1D6822
+       for <pgsql-hackers@postgresql.org>; Fri, 25 Nov 2005 10:14:55 -0400 (AST)
+Received: (qmail 6658 invoked from network); 25 Nov 2005 14:14:55 -0000
+DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws;
+  s=s1024; d=Yahoo.com;
+  h=Received:Message-ID:Date:From:User-Agent:X-Accept-Language:MIME-Version:To:CC:Subject:References:In-Reply-To:Content-Type:Content-Transfer-Encoding;
+  b=3IYwOeJgAhkmP/C6LDpv1wsSJCeqr4E0XFCc+cW2u3ZWf6NbmJ19+1NqiyPs/4RVzSH0M8FIPcRZDB1e3bkKQHt3wxdGJrfdxMi5d7DjlC59xirRpZGzUAD3yusU8lg3uE2G/TraLtC6VVpbJo8+rYerPOg+daspmuRqhlcXUjg=  ;
+Received: from unknown (HELO jupiter.black-lion.info) (janwieck@68.80.245.191 with login)
+  by smtp015.mail.yahoo.com with SMTP; 25 Nov 2005 14:14:55 -0000
+Received: from [172.21.8.23] (mars.black-lion.info [192.168.192.101])
+       (authenticated bits=0)
+       by jupiter.black-lion.info (8.12.10/8.12.9) with ESMTP id jAPEEq1o062023;
+       Fri, 25 Nov 2005 09:14:52 -0500 (EST)
+       (envelope-from JanWieck@Yahoo.com)
+Message-ID: <43871C57.6060000@Yahoo.com>
+Date: Fri, 25 Nov 2005 09:14:47 -0500
+From: Jan Wieck <JanWieck@Yahoo.com>
+User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.1) Gecko/20040707
+X-Accept-Language: en-us, en
+MIME-Version: 1.0
+To: Martijn van Oosterhout <kleptog@svana.org>
+cc: Tom Lane <tgl@sss.pgh.pa.us>, Peter Eisentraut <peter_e@gmx.net>,
+   pgsql-hackers@postgresql.org, Josh Berkus <josh@agliodbs.com>,
+   Jaime Casanova <systemguards@gmail.com>
+Subject: Re: [HACKERS] someone working to add merge?
+References: <c2d9e70e0511110603q1799d811u6e4564be516b10ce@mail.gmail.com> <200511111924.41532.peter_e@gmx.net> <20561.1131734697@sss.pgh.pa.us> <200511112004.35876.peter_e@gmx.net> <20899.1131736841@sss.pgh.pa.us> <4384E54D.8000500@Yahoo.com> <20051124063034.GA18750@svana.org> <4385E636.4070503@Yahoo.com> <20051125121402.GB16970@svana.org>
+In-Reply-To: <20051125121402.GB16970@svana.org>
+Content-Type: text/plain; charset=us-ascii; format=flowed
+Content-Transfer-Encoding: 7bit
+X-Virus-Scanned: by amavisd-new at hub.org
+X-Spam-Status: No, score=0.359 required=5 tests=[AWL=-0.120,
+       DNS_FROM_RFC_ABUSE=0.479]
+X-Spam-Score: 0.359
+X-Mailing-List: pgsql-hackers
+List-Archive: <http://archives.postgresql.org/pgsql-hackers>
+List-Help: <mailto:majordomo@postgresql.org?body=help>
+List-Id: <pgsql-hackers.postgresql.org>
+List-Owner: <mailto:pgsql-hackers-owner@postgresql.org>
+List-Post: <mailto:pgsql-hackers@postgresql.org>
+List-Subscribe: <mailto:majordomo@postgresql.org?body=sub%20pgsql-hackers>
+List-Unsubscribe: <mailto:majordomo@postgresql.org?body=unsub%20pgsql-hackers>
+Precedence: bulk
+Sender: pgsql-hackers-owner@postgresql.org
+Status: OR
+
+On 11/25/2005 7:14 AM, Martijn van Oosterhout wrote:
+> On Thu, Nov 24, 2005 at 11:11:34AM -0500, Jan Wieck wrote:
+>> I guess you misunderstood. [...]
+> 
+> But I'm not sure we're supposed to handle that case anyway. Oracle at
+> least doesn't require an index on the table being merged. And if I look
+> at it from a visibility view point, if someone else does an INSERT in
+> another transaction, then MERGE cannot see it and thus it will INSERT
+> too. This isn't an error.
+
+Hmmm ... so you maintain that MERGE without an explicit LOCK TABLE, done 
+by the user before performing the MERGE, can create duplicate rows (WRT 
+the merge condition) and consequently raise a duplicate key error if 
+there is a UNIQUE constraint.
+
+If that is what the standard describes, then it can be implemented 
+without any sort of index or constraint requirement. The query tree for 
+MERGE will have the INTO relation as a left outer join. In the case of a 
+match of this outer join, one set of targetlist expressions is used to 
+form the result tuple containing the INTO-relations ctid. That result 
+tuple us useable for heap_update() or heap_delete(). In the case of 
+no-match another set of target list expressions is used, suitable for 
+heap_insert(). This way, MERGE will work with one single sequential scan 
+of the INTO relation in case there is no suitable index.
+
+
+Jan
+
+-- 
+#======================================================================#
+# It's easier to get forgiveness for being wrong than for being right. #
+# Let's break this rule - forgive me.                                  #
+#================================================== JanWieck@Yahoo.com #
+
+---------------------------(end of broadcast)---------------------------
+TIP 9: In versions below 8.0, the planner will ignore your desire to
+       choose an index scan if your joining column's datatypes do not
+       match
+
+From pgsql-hackers-owner+M76588@postgresql.org Fri Nov 25 09:55:41 2005
+Return-path: <pgsql-hackers-owner+M76588@postgresql.org>
+Received: from ams.hub.org (ams.hub.org [200.46.204.13])
+       by candle.pha.pa.us (8.11.6/8.11.6) with ESMTP id jAPEtfB01898
+       for <pgman@candle.pha.pa.us>; Fri, 25 Nov 2005 09:55:41 -0500 (EST)
+Received: from postgresql.org (svr1.postgresql.org [200.46.204.71])
+       by ams.hub.org (Postfix) with ESMTP id D0574C4BCA2;
+       Fri, 25 Nov 2005 14:55:39 +0000 (GMT)
+X-Original-To: pgsql-hackers-postgresql.org@localhost.postgresql.org
+Received: from localhost (av.hub.org [200.46.204.144])
+       by svr1.postgresql.org (Postfix) with ESMTP id 9BABBD7693
+       for <pgsql-hackers-postgresql.org@localhost.postgresql.org>; Fri, 25 Nov 2005 10:55:13 -0400 (AST)
+Received: from svr1.postgresql.org ([200.46.204.71])
+       by localhost (av.hub.org [200.46.204.144]) (amavisd-new, port 10024)
+       with ESMTP id 21958-02
+       for <pgsql-hackers-postgresql.org@localhost.postgresql.org>;
+       Fri, 25 Nov 2005 14:55:16 +0000 (GMT)
+X-Greylist: from auto-whitelisted by SQLgrey-
+Received: from svana.org (svana.org [203.20.62.76])
+       by svr1.postgresql.org (Postfix) with ESMTP id C3689D7121
+       for <pgsql-hackers@postgresql.org>; Fri, 25 Nov 2005 10:55:08 -0400 (AST)
+Received: from kleptog by svana.org with local (Exim 3.35 #1 (Debian))
+       id 1Efeyd-0005xQ-00; Sat, 26 Nov 2005 01:55:03 +1100
+Date: Fri, 25 Nov 2005 15:55:03 +0100
+From: Martijn van Oosterhout <kleptog@svana.org>
+To: Jan Wieck <JanWieck@Yahoo.com>
+cc: Tom Lane <tgl@sss.pgh.pa.us>, Peter Eisentraut <peter_e@gmx.net>,
+   pgsql-hackers@postgresql.org, Josh Berkus <josh@agliodbs.com>,
+   Jaime Casanova <systemguards@gmail.com>
+Subject: Re: [HACKERS] someone working to add merge?
+Message-ID: <20051125145501.GD16970@svana.org>
+Reply-To: Martijn van Oosterhout <kleptog@svana.org>
+References: <c2d9e70e0511110603q1799d811u6e4564be516b10ce@mail.gmail.com> <200511111924.41532.peter_e@gmx.net> <20561.1131734697@sss.pgh.pa.us> <200511112004.35876.peter_e@gmx.net> <20899.1131736841@sss.pgh.pa.us> <4384E54D.8000500@Yahoo.com> <20051124063034.GA18750@svana.org> <4385E636.4070503@Yahoo.com> <20051125121402.GB16970@svana.org> <43871C57.6060000@Yahoo.com>
+MIME-Version: 1.0
+Content-Type: multipart/signed; micalg=pgp-sha1;
+       protocol="application/pgp-signature"; boundary="NklN7DEeGtkPCoo3"
+Content-Disposition: inline
+In-Reply-To: <43871C57.6060000@Yahoo.com>
+User-Agent: Mutt/1.3.28i
+X-PGP-Key-ID: Length=1024; ID=0x0DC67BE6
+X-PGP-Key-Fingerprint: 295F A899 A81A 156D B522  48A7 6394 F08A 0DC6 7BE6
+X-PGP-Key-URL: <http://svana.org/kleptog/0DC67BE6.pgp.asc>
+X-Virus-Scanned: by amavisd-new at hub.org
+X-Spam-Status: No, score=0 required=5 tests=[AWL=0.000]
+X-Spam-Score: 0
+X-Mailing-List: pgsql-hackers
+List-Archive: <http://archives.postgresql.org/pgsql-hackers>
+List-Help: <mailto:majordomo@postgresql.org?body=help>
+List-Id: <pgsql-hackers.postgresql.org>
+List-Owner: <mailto:pgsql-hackers-owner@postgresql.org>
+List-Post: <mailto:pgsql-hackers@postgresql.org>
+List-Subscribe: <mailto:majordomo@postgresql.org?body=sub%20pgsql-hackers>
+List-Unsubscribe: <mailto:majordomo@postgresql.org?body=unsub%20pgsql-hackers>
+Precedence: bulk
+Sender: pgsql-hackers-owner@postgresql.org
+Status: OR
+
+
+--NklN7DEeGtkPCoo3
+Content-Type: text/plain; charset=us-ascii
+Content-Disposition: inline
+Content-Transfer-Encoding: quoted-printable
+
+On Fri, Nov 25, 2005 at 09:14:47AM -0500, Jan Wieck wrote:
+> Hmmm ... so you maintain that MERGE without an explicit LOCK TABLE, done=
+=20
+> by the user before performing the MERGE, can create duplicate rows (WRT=
+=20
+> the merge condition) and consequently raise a duplicate key error if=20
+> there is a UNIQUE constraint.
+>=20
+> If that is what the standard describes, then it can be implemented=20
+> without any sort of index or constraint requirement. The query tree for=
+=20
+> MERGE will have the INTO relation as a left outer join. In the case of a=
+=20
+> match of this outer join, one set of targetlist expressions is used to=20
+> form the result tuple containing the INTO-relations ctid. That result=20
+> tuple us useable for heap_update() or heap_delete(). In the case of=20
+> no-match another set of target list expressions is used, suitable for=20
+> heap_insert(). This way, MERGE will work with one single sequential scan=
+=20
+> of the INTO relation in case there is no suitable index.
+
+Yes, that's the way I read the standard and how I was thinking it could
+be implemented. It does simplify the case suggested by people that want
+atomic REPLACE, because you only have one statement to repeat until you
+get success.
+
+do
+   MERGE ...;
+while( not error and modified_rows <> 1 )
+
+I was thinking that we could make a seperate REPLACE command which can
+only insert or update one row, but can do it atomically. Basically a
+loop like above with builtin savepoints.
+
+Alternativly, we could special case the MERGE-without-USING case, in
+the cases where the plan simply devolves into an Index Scan, but I
+don't like special casing. If we're going to have special semantics we
+should have a seperate statement so it's clear that it's special.
+
+Have a nice day,
+--=20
+Martijn van Oosterhout   <kleptog@svana.org>   http://svana.org/kleptog/
+> Patent. n. Genius is 5% inspiration and 95% perspiration. A patent is a
+> tool for doing 5% of the work and then sitting around waiting for someone
+> else to do the other 95% so you can sue them.
+
+--NklN7DEeGtkPCoo3
+Content-Type: application/pgp-signature
+Content-Disposition: inline
+
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v1.0.6 (GNU/Linux)
+Comment: For info see http://www.gnupg.org
+
+iD8DBQFDhyXEIB7bNG8LQkwRAlxiAJ4tVMSPKRELg0H7na778cppeU1opACgkawW
+xsYY7O6aMVjdXT4ye3fS6KI=
+=XS8K
+-----END PGP SIGNATURE-----
+
+--NklN7DEeGtkPCoo3--
+