From f28bdd95c1755027756914d7d46424287e192e9e Mon Sep 17 00:00:00 2001 From: Bruce Momjian Date: Thu, 1 Dec 2005 22:12:06 +0000 Subject: [PATCH] Add merge TODO.detail item. --- doc/TODO.detail/merge | 3390 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 3390 insertions(+) create mode 100644 doc/TODO.detail/merge diff --git a/doc/TODO.detail/merge b/doc/TODO.detail/merge new file mode 100644 index 0000000000..276e2528a3 --- /dev/null +++ b/doc/TODO.detail/merge @@ -0,0 +1,3390 @@ +From kleptog@svana.org Thu Nov 17 07:33:25 2005 +Return-path: +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 ; 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 +To: Csaba Nagy +cc: Zeugswetter Andreas DCP SD , + Dann Corbit , Simon Riggs , + Bruce Momjian , + Rick Gigger , Tom Lane , + Christopher Kings-Lynne , + "Jim C. Nasby" , josh@agliodbs.com, + pgsql-hackers@postgresql.org, Jaime Casanova , + Peter Eisentraut +Subject: Re: [HACKERS] MERGE vs REPLACE +Message-ID: <20051117123250.GC22933@svana.org> +Reply-To: Martijn van Oosterhout +References: <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: +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 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: +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 ; 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 ; 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 ; + 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 ; 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 +cc: Martijn van Oosterhout , + Zeugswetter Andreas DCP SD , + Dann Corbit , Simon Riggs , + Bruce Momjian , + 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 +In-Reply-To: <1132231474.10890.317.camel@coppola.muc.ecircle.de> +References: <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 + 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 +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: +List-Help: +List-Id: +List-Owner: +List-Post: +List-Subscribe: +List-Unsubscribe: +Precedence: bulk +Sender: pgsql-hackers-owner@postgresql.org +Status: ORr + +Csaba Nagy 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: +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 ; 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 ; 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 ; + 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 ; 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 ; 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 +To: Tom Lane +cc: Csaba Nagy , + Martijn van Oosterhout , + Zeugswetter Andreas DCP SD , + Dann Corbit , Simon Riggs , + Bruce Momjian , + 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 +Message-ID: <20051117151530.GU6026@ns.snowman.net> +Mail-Followup-To: Tom Lane , + Csaba Nagy , + Martijn van Oosterhout , + Zeugswetter Andreas DCP SD , + Dann Corbit , Simon Riggs , + Bruce Momjian , + Rick Gigger , + Christopher Kings-Lynne , + "Jim C. Nasby" , josh@agliodbs.com, + pgsql-hackers@postgresql.org, + Jaime Casanova , + Peter Eisentraut +References: <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: +List-Help: +List-Id: +List-Owner: +List-Post: +List-Subscribe: +List-Unsubscribe: +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: +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 ; 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 +To: Tom Lane +cc: Csaba Nagy , + Martijn van Oosterhout , + Zeugswetter Andreas DCP SD , + Dann Corbit , Simon Riggs , + Bruce Momjian , + 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 +Message-ID: <20051117151530.GU6026@ns.snowman.net> +Mail-Followup-To: Tom Lane , + Csaba Nagy , + Martijn van Oosterhout , + Zeugswetter Andreas DCP SD , + Dann Corbit , + Simon Riggs , + Bruce Momjian , + Rick Gigger , + Christopher Kings-Lynne , + "Jim C. Nasby" , josh@agliodbs.com, + pgsql-hackers@postgresql.org, + Jaime Casanova , + Peter Eisentraut +References: <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: +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 ; 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 ; 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 ; + 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 ; 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 +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 +Date: Thu, 17 Nov 2005 22:11:33 -0500 (EST) +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 +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: +List-Help: +List-Id: +List-Owner: +List-Post: +List-Subscribe: +List-Unsubscribe: +Precedence: bulk +Sender: pgsql-hackers-owner@postgresql.org +Status: OR + +Tom Lane wrote: +> Csaba Nagy 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: +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 ; 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: +Thread-Topic: [HACKERS] MERGE vs REPLACE +Thread-Index: AcXr7dUIILx3WyhrREu/dEAzLwToBgABFVZw +From: "Dann Corbit" +To: "Bruce Momjian" , "Tom Lane" +cc: "Csaba Nagy" , + "Martijn van Oosterhout" , + "Zeugswetter Andreas DCP SD" , + "Simon Riggs" , + "Rick Gigger" , + "Christopher Kings-Lynne" , + "Jim C. Nasby" , , + , "Jaime Casanova" , + "Peter Eisentraut" +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 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: +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 ; 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 ; 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 ; + 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 ; 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 +To: Bruce Momjian +cc: Zeugswetter Andreas DCP SD , + Csaba Nagy , + Martijn van Oosterhout , Dann Corbit , + Simon Riggs , + Rick Gigger , Tom Lane , + Christopher Kings-Lynne , + "Jim C. Nasby" , , + , Jaime Casanova , + Peter Eisentraut +Subject: Re: [HACKERS] MERGE vs REPLACE +In-Reply-To: <200511180218.jAI2IPF04976@candle.pha.pa.us> +Message-ID: +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: +List-Help: +List-Id: +List-Owner: +List-Post: +List-Subscribe: +List-Unsubscribe: +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: +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 ; 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: +Thread-Topic: [HACKERS] MERGE vs REPLACE +Thread-Index: AcXr5pYcJO3ZR4d/RwebJDquaJx6SQARC+uA +From: "Zeugswetter Andreas DCP SD" +To: "Bruce Momjian" +cc: "Csaba Nagy" , + "Martijn van Oosterhout" , + "Dann Corbit" , "Simon Riggs" , + "Rick Gigger" , "Tom Lane" , + "Christopher Kings-Lynne" , + "Jim C. Nasby" , , + , "Jaime Casanova" , + "Peter Eisentraut" +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: +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 ; 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 ; 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 ; + 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 ; 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 +cc: Dennis Bjorklund , + Zeugswetter Andreas DCP SD , + Csaba Nagy , + Martijn van Oosterhout , 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 +In-Reply-To: <200511181520.jAIFKpW02114@candle.pha.pa.us> +References: <200511181520.jAIFKpW02114@candle.pha.pa.us> +Comments: In-reply-to Bruce Momjian + 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 +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: +List-Help: +List-Id: +List-Owner: +List-Post: +List-Subscribe: +List-Unsubscribe: +Precedence: bulk +Sender: pgsql-hackers-owner@postgresql.org +Status: ORr + +Bruce Momjian 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: +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 ; 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 ; 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 ; + 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 ; 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 +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 +Date: Sun, 20 Nov 2005 12:26:18 -0500 (EST) +cc: Dennis Bjorklund , + Zeugswetter Andreas DCP SD , + Csaba Nagy , + Martijn van Oosterhout , Dann Corbit , + Simon Riggs , + Rick Gigger , + Christopher Kings-Lynne , + "Jim C. Nasby" , josh@agliodbs.com, + pgsql-hackers@postgresql.org, Jaime Casanova , + Peter Eisentraut +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: +List-Help: +List-Id: +List-Owner: +List-Post: +List-Subscribe: +List-Unsubscribe: +Precedence: bulk +Sender: pgsql-hackers-owner@postgresql.org +Status: OR + +Tom Lane wrote: +> Bruce Momjian 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: +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 ; 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 ; 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 ; + 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 ; 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" +To: Bruce Momjian +cc: mark@mark.mielke.cc, Tom Lane , + Csaba Nagy , + Martijn van Oosterhout , + Zeugswetter Andreas DCP SD , + Dann Corbit , Simon Riggs , + Rick Gigger , + Christopher Kings-Lynne , josh@agliodbs.com, + pgsql-hackers@postgresql.org, Jaime Casanova , + Peter Eisentraut +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: +List-Help: +List-Id: +List-Owner: +List-Post: +List-Subscribe: +List-Unsubscribe: +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: +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 ; 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" +To: Tom Lane , Csaba Nagy , + Martijn van Oosterhout , + Zeugswetter Andreas DCP SD , + Dann Corbit , Simon Riggs , + Bruce Momjian , + Rick Gigger , + Christopher Kings-Lynne , josh@agliodbs.com, + pgsql-hackers@postgresql.org, Jaime Casanova , + Peter Eisentraut +Subject: Re: [HACKERS] MERGE vs REPLACE +Message-ID: <20051121214630.GM19279@pervasive.com> +References: <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: +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 ; 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 ; 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 ; + 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 ; Mon, 21 Nov 2005 23:20:10 -0400 (AST) +Received: from modos ([10.12.0.96] ident=PJMODOS) + by gatekeeper.pjmodos.bounceme.net 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 +User-Agent: Mozilla Thunderbird 1.0 (Windows/20041206) +X-Accept-Language: cs, en, en-us +MIME-Version: 1.0 +To: "Jim C. Nasby" +cc: PostgreSQL-development +Subject: Re: [HACKERS] MERGE vs REPLACE +References: <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: +List-Help: +List-Id: +List-Owner: +List-Post: +List-Subscribe: +List-Unsubscribe: +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: +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 ; 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 ; 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 ; + 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 ; 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 +To: Petr Jelinek +cc: "Jim C. Nasby" , + PostgreSQL-development +Subject: Re: [HACKERS] MERGE vs REPLACE +Message-ID: <20051122105747.GC12548@svana.org> +Reply-To: Martijn van Oosterhout +References: <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: +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: +List-Help: +List-Id: +List-Owner: +List-Post: +List-Subscribe: +List-Unsubscribe: +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 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: +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 ; 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 ; 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 ; + 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 ; 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" +To: Martijn van Oosterhout +cc: Petr Jelinek , + PostgreSQL-development +Subject: Re: [HACKERS] MERGE vs REPLACE +Message-ID: <20051122203045.GC99429@pervasive.com> +References: <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: +List-Help: +List-Id: +List-Owner: +List-Post: +List-Subscribe: +List-Unsubscribe: +Precedence: bulk +Sender: pgsql-hackers-owner@postgresql.org +Status: OR + +On Tue, Nov 22, 2005 at 11:57:48AM +0100, Martijn van Oosterhout wrote: + + +> 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: +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 ; 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 ; 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 ; + 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 ; 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 +To: Petr Jelinek +cc: Jaime Casanova , + PostgreSQL-development , + "Jim C. Nasby" +Subject: Re: [HACKERS] MERGE vs REPLACE +Message-ID: <20051123090926.GA8374@svana.org> +Reply-To: Martijn van Oosterhout +References: <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> <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: +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: +List-Help: +List-Id: +List-Owner: +List-Post: +List-Subscribe: +List-Unsubscribe: +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 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: +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 ; 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 ; 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 ; + 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 ; 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 +User-Agent: Thunderbird 1.5 (Windows/20051025) +MIME-Version: 1.0 +To: Martijn van Oosterhout +cc: PostgreSQL-development +Subject: Re: [HACKERS] MERGE vs REPLACE +References: <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> <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: +List-Help: +List-Id: +List-Owner: +List-Post: +List-Subscribe: +List-Unsubscribe: +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: +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 ; 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 ; 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 ; + 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 ; 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 +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 +cc: Peter Eisentraut , pgsql-hackers@postgresql.org, + Josh Berkus , Jaime Casanova +Subject: Re: [HACKERS] someone working to add merge? +References: <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: +List-Help: +List-Id: +List-Owner: +List-Post: +List-Subscribe: +List-Unsubscribe: +Precedence: bulk +Sender: pgsql-hackers-owner@postgresql.org +Status: OR + +On 11/11/2005 2:20 PM, Tom Lane wrote: + +> Peter Eisentraut 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: +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 ; 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 ; 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 ; + 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 ; 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 +To: Jan Wieck +cc: Tom Lane , Peter Eisentraut , + pgsql-hackers@postgresql.org, Josh Berkus , + Jaime Casanova +Subject: Re: [HACKERS] someone working to add merge? +Message-ID: <20051124063034.GA18750@svana.org> +Reply-To: Martijn van Oosterhout +References: <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: +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: +List-Help: +List-Id: +List-Owner: +List-Post: +List-Subscribe: +List-Unsubscribe: +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 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: +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 ; 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 ; 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 ; + 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 ; 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 +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 +cc: Tom Lane , Peter Eisentraut , + pgsql-hackers@postgresql.org, Josh Berkus , + Jaime Casanova +Subject: Re: [HACKERS] someone working to add merge? +References: <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: +List-Help: +List-Id: +List-Owner: +List-Post: +List-Subscribe: +List-Unsubscribe: +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: +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 ; 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 ; 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 ; + 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 ; 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 +To: Jan Wieck +cc: Tom Lane , Peter Eisentraut , + pgsql-hackers@postgresql.org, Josh Berkus , + Jaime Casanova +Subject: Re: [HACKERS] someone working to add merge? +Message-ID: <20051125121402.GB16970@svana.org> +Reply-To: Martijn van Oosterhout +References: <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: +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: +List-Help: +List-Id: +List-Owner: +List-Post: +List-Subscribe: +List-Unsubscribe: +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 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: +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 ; 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 ; 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 ; + 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 ; 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 +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 +cc: Tom Lane , Peter Eisentraut , + pgsql-hackers@postgresql.org, Josh Berkus , + Jaime Casanova +Subject: Re: [HACKERS] someone working to add merge? +References: <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: +List-Help: +List-Id: +List-Owner: +List-Post: +List-Subscribe: +List-Unsubscribe: +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: +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 ; 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 ; 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 ; + 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 ; 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 +To: Jan Wieck +cc: Tom Lane , Peter Eisentraut , + pgsql-hackers@postgresql.org, Josh Berkus , + Jaime Casanova +Subject: Re: [HACKERS] someone working to add merge? +Message-ID: <20051125145501.GD16970@svana.org> +Reply-To: Martijn van Oosterhout +References: <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: +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: +List-Help: +List-Id: +List-Owner: +List-Post: +List-Subscribe: +List-Unsubscribe: +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 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-- + -- 2.40.0