Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1p3ZVF-0001bM-9k for pgsql-hackers@arkaria.postgresql.org; Fri, 09 Dec 2022 09:17:09 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1p3ZVD-0006wU-SD for pgsql-hackers@arkaria.postgresql.org; Fri, 09 Dec 2022 09:17:07 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1p3ZVD-0006t8-C1 for pgsql-hackers@lists.postgresql.org; Fri, 09 Dec 2022 09:17:07 +0000 Received: from mail-pj1-x1032.google.com ([2607:f8b0:4864:20::1032]) by makus.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.92) (envelope-from ) id 1p3ZV6-0008MX-2i for pgsql-hackers@postgresql.org; Fri, 09 Dec 2022 09:17:05 +0000 Received: by mail-pj1-x1032.google.com with SMTP id js9so3232340pjb.2 for ; Fri, 09 Dec 2022 01:16:59 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=to:subject:message-id:date:from:mime-version:from:to:cc:subject :date:message-id:reply-to; bh=x1P8/A/j4ApDddronDsRco8JYgRrq0aXrPC/9TCA24Q=; b=g7Io2YPKU+/b9cgND1c45HeWwzZOmhPavbXmhqgSEjq/oCCkbREaF5f4hfCLZBdo+u UhlpzWBQjRpr/yqB6zpKRhJ399ptd3vHO0nypT+/sa7WH/gyD9f3z9SRs/ZSE9dsLzql 2cabRteZYMxvWPb8it7Jsf5EcH4G3v00e17MmT/2S66sYZF7RIh4fWXdkqWtu41s0T3b 6V5bgK25oBSpmevH3oSQhmvgA8HFwesWN41fm6dHR8Zrm/AG5FBWfgBbzZx6qbahTudZ 8YJAm3tXZ2va03lIHvJtZExMt4OInSbc/+mebeO04dzqUDRqJh+iEIqKGiEBFW7bS/2R b2SQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=to:subject:message-id:date:from:mime-version:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=x1P8/A/j4ApDddronDsRco8JYgRrq0aXrPC/9TCA24Q=; b=ieaMumRSHUgOZAFOPYJnW/8PD+xdURf/R/iKdGKZSaj7EqJgVacteD9DYSNVhmMwKr qH4bOMLBXzQCkbCCt2ZvF8ldNFvipRYH7H5RNj3aumfC1NcWH5rXbz8JAiNbiSkDdzo8 RNtx5ssYZk+oiw5qq/9Al7Vj5z6COk3OGMGoB4CH6B2B34vkli13dAJeIEeZawVQP84K YyjLR+la+fBOEvYS/aDdUobppNHFhPxvv2Lj4RqbpDGGpx22gcJA2/8d2TwJK92vAw6Z ruKlpmr+HDyLuYl12+AL4ysPE9tssEk1bs5d+YPYDlMZg6FjFtBn0yDHa4vfcpxVazeH T/AQ== X-Gm-Message-State: ANoB5pmySIg7LLURlIDE/be8ze17jlBj7gPBFnIrNmXKbzdakWfHi9Ma nUZUaeZkKecM7fPpPmvwyj9EbStMqeyDa8edwlwH70oWkbA= X-Google-Smtp-Source: AA0mqf6soHFwSCSL4WbiccI6MW4azxMh4xZcsUa/NGkwhp1eQc+f+xcPiJi83q1R4LzsB3AFy3P+cq8hMFG5i/HX+I0= X-Received: by 2002:a17:902:d0d4:b0:189:9b43:a085 with SMTP id n20-20020a170902d0d400b001899b43a085mr45602779pln.169.1670577418228; Fri, 09 Dec 2022 01:16:58 -0800 (PST) MIME-Version: 1.0 From: Richard Guo Date: Fri, 9 Dec 2022 17:16:47 +0800 Message-ID: Subject: Check lateral references within PHVs for memoize cache keys To: PostgreSQL-development Content-Type: multipart/mixed; boundary="00000000000095ed7105ef619d8f" List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --00000000000095ed7105ef619d8f Content-Type: multipart/alternative; boundary="00000000000095ed6f05ef619d8d" --00000000000095ed6f05ef619d8d Content-Type: text/plain; charset="UTF-8" If we intend to generate a memoize node atop a path, we need some kind of cache key. Currently we search the path's parameterized clauses and its parent's lateral_vars for that. ISTM this is not sufficient because their might be lateral references derived from PlaceHolderVars, which can also act as cache key but we neglect to take into consideration. As an example, consider create table t(a int); insert into t values (1), (1), (1), (1); analyze t; explain (costs off) select * from t t1 left join lateral (select t1.a as t1a, t2.a as t2a from t t2) s on true where s.t1a = s.t2a; QUERY PLAN ---------------------------- Nested Loop -> Seq Scan on t t1 -> Seq Scan on t t2 Filter: (t1.a = a) (4 rows) We cannot find available cache keys for memoize node because the inner side has neither parameterized path clauses nor lateral_vars. However if we are able to look in the PHV for lateral references, we will find the cache key 't1.a'. Actually we do have checked PHVs for lateral references, earlier in create_lateral_join_info. But that time we only marked lateral_relids and direct_lateral_relids, without remembering the lateral expressions. So I'm wondering whether we can fix that by fetching Vars (or PHVs) of lateral references within PlaceHolderVars and remembering them in the baserel's lateral_vars. Attach a draft patch to show my thoughts. Thanks Richard --00000000000095ed6f05ef619d8d Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
If we intend to generate a memoize node atop a path, we ne= ed some kind
of cache key.=C2=A0 Currently we search the path's para= meterized clauses and
its parent's lateral_vars for that.=C2=A0 ISTM= this is not sufficient because
their might be lateral references derive= d from PlaceHolderVars, which
can also act as cache key but we neglect t= o take into consideration.=C2=A0 As
an example, consider

create t= able t(a int);
insert into t values (1), (1), (1), (1);
analyze t;
explain (costs off) select * from t t1 left join lateral (select t1.a = as t1a, t2.a as t2a from t t2) s on true where s.t1a =3D s.t2a;
=C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0QUERY PLAN
----------------------------
= =C2=A0Nested Loop
=C2=A0 =C2=A0-> =C2=A0Seq Scan on t t1
=C2=A0 = =C2=A0-> =C2=A0Seq Scan on t t2
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Fil= ter: (t1.a =3D a)
(4 rows)

We cannot find available cache keys fo= r memoize node because the inner
side has neither parameterized path cla= uses nor lateral_vars.=C2=A0 However
if we are able to look in the PHV f= or lateral references, we will find
the cache key 't1.a'.
Actually we do have checked PHVs for lateral references, earlier in
cre= ate_lateral_join_info.=C2=A0 But that time we only marked lateral_relidsand direct_lateral_relids, without remembering the lateral expressions.So I'm wondering whether we can fix that by fetching Vars (or PHVs) of=
lateral references within PlaceHolderVars and remembering them in thebaserel's lateral_vars.

Attach a draft patch to show my though= ts.

Thanks
Richard
--00000000000095ed6f05ef619d8d-- --00000000000095ed7105ef619d8f Content-Type: application/octet-stream; name="v1-0001-Check-lateral-references-within-PHVs-for-memoize-.patch" Content-Disposition: attachment; filename="v1-0001-Check-lateral-references-within-PHVs-for-memoize-.patch" Content-Transfer-Encoding: base64 Content-ID: X-Attachment-Id: f_lbgam4wp0 RnJvbSA4NDI2NjA5YjcxNmNmYzdjZDg4NDJmOGQyMmFmNGU0ZjVlMjkzNWIyIE1vbiBTZXAgMTcg MDA6MDA6MDAgMjAwMQpGcm9tOiBSaWNoYXJkIEd1byA8Z3VvZmVuZ2xpbnV4QGdtYWlsLmNvbT4K RGF0ZTogRnJpLCA5IERlYyAyMDIyIDEyOjA3OjE1ICswODAwClN1YmplY3Q6IFtQQVRDSCB2MV0g Q2hlY2sgbGF0ZXJhbCByZWZlcmVuY2VzIHdpdGhpbiBQSFZzIGZvciBtZW1vaXplIGNhY2hlCiBr ZXlzCgotLS0KIHNyYy9iYWNrZW5kL29wdGltaXplci9wbGFuL2luaXRzcGxhbi5jIHwgNTEgKysr KysrKysrKysrKysrKysrKysrKysrKysKIHNyYy90ZXN0L3JlZ3Jlc3MvZXhwZWN0ZWQvbWVtb2l6 ZS5vdXQgIHwgMzEgKysrKysrKysrKysrKysrKwogc3JjL3Rlc3QvcmVncmVzcy9zcWwvbWVtb2l6 ZS5zcWwgICAgICAgfCAxMSArKysrKysKIDMgZmlsZXMgY2hhbmdlZCwgOTMgaW5zZXJ0aW9ucygr KQoKZGlmZiAtLWdpdCBhL3NyYy9iYWNrZW5kL29wdGltaXplci9wbGFuL2luaXRzcGxhbi5jIGIv c3JjL2JhY2tlbmQvb3B0aW1pemVyL3BsYW4vaW5pdHNwbGFuLmMKaW5kZXggZmQ4Y2JiMWRjNy4u NjhmZjA5NzVkMSAxMDA2NDQKLS0tIGEvc3JjL2JhY2tlbmQvb3B0aW1pemVyL3BsYW4vaW5pdHNw bGFuLmMKKysrIGIvc3JjL2JhY2tlbmQvb3B0aW1pemVyL3BsYW4vaW5pdHNwbGFuLmMKQEAgLTUy MywxMiArNTIzLDQ5IEBAIGNyZWF0ZV9sYXRlcmFsX2pvaW5faW5mbyhQbGFubmVySW5mbyAqcm9v dCkKIAkJUGxhY2VIb2xkZXJJbmZvICpwaGluZm8gPSAoUGxhY2VIb2xkZXJJbmZvICopIGxmaXJz dChsYyk7CiAJCVJlbGlkcwkJZXZhbF9hdCA9IHBoaW5mby0+cGhfZXZhbF9hdDsKIAkJaW50CQkJ dmFybm87CisJCUxpc3QJICAgKnZhcnM7CisJCUxpc3QJICAgKnBoX2xhdGVyYWxfdmFyczsKKwkJ TGlzdENlbGwgICAqY2VsbDsKIAogCQlpZiAocGhpbmZvLT5waF9sYXRlcmFsID09IE5VTEwpCiAJ CQljb250aW51ZTsJCQkvKiBQSFYgaXMgdW5pbnRlcmVzdGluZyBpZiBubyBsYXRlcmFsIHJlZnMg Ki8KIAogCQlmb3VuZF9sYXRlcmFscyA9IHRydWU7CiAKKwkJLyogRmV0Y2ggVmFycyBhbmQgUEhW cyBvZiBsYXRlcmFsIHJlZmVyZW5jZXMgd2l0aGluIFBsYWNlSG9sZGVyVmFycyAqLworCQl2YXJz ID0gcHVsbF92YXJzX29mX2xldmVsKChOb2RlICopIHBoaW5mby0+cGhfdmFyLT5waGV4cHIsIDAp OworCisJCXBoX2xhdGVyYWxfdmFycyA9IE5JTDsKKwkJZm9yZWFjaChjZWxsLCB2YXJzKQorCQl7 CisJCQlOb2RlCSAgICpub2RlID0gKE5vZGUgKikgbGZpcnN0KGNlbGwpOworCisJCQlub2RlID0g Y29weU9iamVjdChub2RlKTsKKwkJCWlmIChJc0Eobm9kZSwgVmFyKSkKKwkJCXsKKwkJCQlWYXIJ CSAgICp2YXIgPSAoVmFyICopIG5vZGU7CisKKwkJCQlBc3NlcnQodmFyLT52YXJsZXZlbHN1cCA9 PSAwKTsKKworCQkJCWlmIChibXNfaXNfbWVtYmVyKHZhci0+dmFybm8sIHBoaW5mby0+cGhfbGF0 ZXJhbCkpCisJCQkJCXBoX2xhdGVyYWxfdmFycyA9IGxhcHBlbmQocGhfbGF0ZXJhbF92YXJzLCBu b2RlKTsKKwkJCX0KKwkJCWVsc2UgaWYgKElzQShub2RlLCBQbGFjZUhvbGRlclZhcikpCisJCQl7 CisJCQkJUGxhY2VIb2xkZXJWYXIgKnBodiA9IChQbGFjZUhvbGRlclZhciAqKSBub2RlOworCisJ CQkJQXNzZXJ0KHBodi0+cGhsZXZlbHN1cCA9PSAwKTsKKworCQkJCWlmIChibXNfaXNfc3Vic2V0 KGZpbmRfcGxhY2Vob2xkZXJfaW5mbyhyb290LCBwaHYpLT5waF9ldmFsX2F0LAorCQkJCQkJCQkg IHBoaW5mby0+cGhfbGF0ZXJhbCkpCisJCQkJCXBoX2xhdGVyYWxfdmFycyA9IGxhcHBlbmQocGhf bGF0ZXJhbF92YXJzLCBub2RlKTsKKwkJCX0KKwkJCWVsc2UKKwkJCQlBc3NlcnQoZmFsc2UpOwor CQl9CisKKwkJbGlzdF9mcmVlKHZhcnMpOworCiAJCWlmIChibXNfZ2V0X3NpbmdsZXRvbl9tZW1i ZXIoZXZhbF9hdCwgJnZhcm5vKSkKIAkJewogCQkJLyogRXZhbHVhdGlvbiBzaXRlIGlzIGEgYmFz ZXJlbCAqLwpAQCAtNTQwLDYgKzU3NywxMyBAQCBjcmVhdGVfbGF0ZXJhbF9qb2luX2luZm8oUGxh bm5lckluZm8gKnJvb3QpCiAJCQlicmVsLT5sYXRlcmFsX3JlbGlkcyA9CiAJCQkJYm1zX2FkZF9t ZW1iZXJzKGJyZWwtPmxhdGVyYWxfcmVsaWRzLAogCQkJCQkJCQlwaGluZm8tPnBoX2xhdGVyYWwp OworCisJCQkvKgorCQkJICogUmVtZW1iZXIgdGhlIGxhdGVyYWwgcmVmZXJlbmNlcy4gV2UgbmVl ZCB0aGlzIGluZm8gZm9yIHNlYXJjaGluZworCQkJICogbWVtb2l6ZSBjYWNoZSBrZXlzLgorCQkJ ICovCisJCQlicmVsLT5sYXRlcmFsX3ZhcnMgPQorCQkJCWxpc3RfY29uY2F0KGJyZWwtPmxhdGVy YWxfdmFycywgcGhfbGF0ZXJhbF92YXJzKTsKIAkJfQogCQllbHNlCiAJCXsKQEAgLTU1MSw2ICs1 OTUsMTMgQEAgY3JlYXRlX2xhdGVyYWxfam9pbl9pbmZvKFBsYW5uZXJJbmZvICpyb290KQogCiAJ CQkJYnJlbC0+bGF0ZXJhbF9yZWxpZHMgPSBibXNfYWRkX21lbWJlcnMoYnJlbC0+bGF0ZXJhbF9y ZWxpZHMsCiAJCQkJCQkJCQkJCQkJICAgcGhpbmZvLT5waF9sYXRlcmFsKTsKKworCQkJCS8qCisJ CQkJICogUmVtZW1iZXIgdGhlIGxhdGVyYWwgcmVmZXJlbmNlcy4gV2UgbmVlZCB0aGlzIGluZm8g Zm9yCisJCQkJICogc2VhcmNoaW5nIG1lbW9pemUgY2FjaGUga2V5cy4KKwkJCQkgKi8KKwkJCQli cmVsLT5sYXRlcmFsX3ZhcnMgPSBsaXN0X2NvbmNhdChicmVsLT5sYXRlcmFsX3ZhcnMsCisJCQkJ CQkJCQkJCQkgcGhfbGF0ZXJhbF92YXJzKTsKIAkJCX0KIAkJfQogCX0KZGlmZiAtLWdpdCBhL3Ny Yy90ZXN0L3JlZ3Jlc3MvZXhwZWN0ZWQvbWVtb2l6ZS5vdXQgYi9zcmMvdGVzdC9yZWdyZXNzL2V4 cGVjdGVkL21lbW9pemUub3V0CmluZGV4IGRlNDNhZmE3NmUuLmNmMjM4NjYxZDIgMTAwNjQ0Ci0t LSBhL3NyYy90ZXN0L3JlZ3Jlc3MvZXhwZWN0ZWQvbWVtb2l6ZS5vdXQKKysrIGIvc3JjL3Rlc3Qv cmVncmVzcy9leHBlY3RlZC9tZW1vaXplLm91dApAQCAtOTAsNiArOTAsMzcgQEAgV0hFUkUgdDEu dW5pcXVlMSA8IDEwMDA7CiAgIDEwMDAgfCA5LjUwMDAwMDAwMDAwMDAwMDAKICgxIHJvdykKIAor LS0gVHJ5IHdpdGggTEFURVJBTCByZWZlcmVuY2VzIHdpdGhpbiBQbGFjZUhvbGRlclZhcnMKK1NF TEVDVCBleHBsYWluX21lbW9pemUoJworU0VMRUNUIENPVU5UKCopLEFWRyh0MS50d2VudHkpIEZS T00gdGVuazEgdDEgTEVGVCBKT0lOCitMQVRFUkFMIChTRUxFQ1QgdDEudHdlbnR5IGFzIGMxLCB0 Mi51bmlxdWUxIGFzIGMyIEZST00gdGVuazEgdDIpIHMgb24gdHJ1ZQorV0hFUkUgcy5jMSA9IHMu YzIgYW5kIHQxLnVuaXF1ZTEgPCAxMDAwOycsIGZhbHNlKTsKKyAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgZXhwbGFpbl9tZW1vaXplICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAKKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KKyBBZ2dy ZWdhdGUgKGFjdHVhbCByb3dzPTEgbG9vcHM9TikKKyAgIC0+ICBOZXN0ZWQgTG9vcCAoYWN0dWFs IHJvd3M9MTAwMCBsb29wcz1OKQorICAgICAgICAgLT4gIFNlcSBTY2FuIG9uIHRlbmsxIHQxIChh Y3R1YWwgcm93cz0xMDAwIGxvb3BzPU4pCisgICAgICAgICAgICAgICBGaWx0ZXI6ICh1bmlxdWUx IDwgMTAwMCkKKyAgICAgICAgICAgICAgIFJvd3MgUmVtb3ZlZCBieSBGaWx0ZXI6IDkwMDAKKyAg ICAgICAgIC0+ICBNZW1vaXplIChhY3R1YWwgcm93cz0xIGxvb3BzPU4pCisgICAgICAgICAgICAg ICBDYWNoZSBLZXk6IHQxLnR3ZW50eQorICAgICAgICAgICAgICAgQ2FjaGUgTW9kZTogYmluYXJ5 CisgICAgICAgICAgICAgICBIaXRzOiA5ODAgIE1pc3NlczogMjAgIEV2aWN0aW9uczogWmVybyAg T3ZlcmZsb3dzOiAwICBNZW1vcnkgVXNhZ2U6IE5rQgorICAgICAgICAgICAgICAgLT4gIEluZGV4 IE9ubHkgU2NhbiB1c2luZyB0ZW5rMV91bmlxdWUxIG9uIHRlbmsxIHQyIChhY3R1YWwgcm93cz0x IGxvb3BzPU4pCisgICAgICAgICAgICAgICAgICAgICBGaWx0ZXI6ICh0MS50d2VudHkgPSB1bmlx dWUxKQorICAgICAgICAgICAgICAgICAgICAgUm93cyBSZW1vdmVkIGJ5IEZpbHRlcjogOTk5OQor ICAgICAgICAgICAgICAgICAgICAgSGVhcCBGZXRjaGVzOiBOCisoMTMgcm93cykKKworLS0gQW5k IGNoZWNrIHdlIGdldCB0aGUgZXhwZWN0ZWQgcmVzdWx0cy4KK1NFTEVDVCBDT1VOVCgqKSxBVkco dDEudHdlbnR5KSBGUk9NIHRlbmsxIHQxIExFRlQgSk9JTgorTEFURVJBTCAoU0VMRUNUIHQxLnR3 ZW50eSBhcyBjMSwgdDIudW5pcXVlMSBhcyBjMiBGUk9NIHRlbmsxIHQyKSBzIG9uIHRydWUKK1dI RVJFIHMuYzEgPSBzLmMyIGFuZCB0MS51bmlxdWUxIDwgMTAwMDsKKyBjb3VudCB8ICAgICAgICBh dmcgICAgICAgICAKKy0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0KKyAgMTAwMCB8IDkuNTAw MDAwMDAwMDAwMDAwMAorKDEgcm93KQorCiAtLSBSZWR1Y2Ugd29ya19tZW0gYW5kIGhhc2hfbWVt X211bHRpcGxpZXIgc28gdGhhdCB3ZSBzZWUgc29tZSBjYWNoZSBldmljdGlvbnMKIFNFVCB3b3Jr X21lbSBUTyAnNjRrQic7CiBTRVQgaGFzaF9tZW1fbXVsdGlwbGllciBUTyAxLjA7CmRpZmYgLS1n aXQgYS9zcmMvdGVzdC9yZWdyZXNzL3NxbC9tZW1vaXplLnNxbCBiL3NyYy90ZXN0L3JlZ3Jlc3Mv c3FsL21lbW9pemUuc3FsCmluZGV4IDE3YzViNGJmYWIuLjUxMmM2ZGZlYmEgMTAwNjQ0Ci0tLSBh L3NyYy90ZXN0L3JlZ3Jlc3Mvc3FsL21lbW9pemUuc3FsCisrKyBiL3NyYy90ZXN0L3JlZ3Jlc3Mv c3FsL21lbW9pemUuc3FsCkBAIC01NSw2ICs1NSwxNyBAQCBTRUxFQ1QgQ09VTlQoKiksQVZHKHQy LnVuaXF1ZTEpIEZST00gdGVuazEgdDEsCiBMQVRFUkFMIChTRUxFQ1QgdDIudW5pcXVlMSBGUk9N IHRlbmsxIHQyIFdIRVJFIHQxLnR3ZW50eSA9IHQyLnVuaXF1ZTEpIHQyCiBXSEVSRSB0MS51bmlx dWUxIDwgMTAwMDsKIAorLS0gVHJ5IHdpdGggTEFURVJBTCByZWZlcmVuY2VzIHdpdGhpbiBQbGFj ZUhvbGRlclZhcnMKK1NFTEVDVCBleHBsYWluX21lbW9pemUoJworU0VMRUNUIENPVU5UKCopLEFW Ryh0MS50d2VudHkpIEZST00gdGVuazEgdDEgTEVGVCBKT0lOCitMQVRFUkFMIChTRUxFQ1QgdDEu dHdlbnR5IGFzIGMxLCB0Mi51bmlxdWUxIGFzIGMyIEZST00gdGVuazEgdDIpIHMgb24gdHJ1ZQor V0hFUkUgcy5jMSA9IHMuYzIgYW5kIHQxLnVuaXF1ZTEgPCAxMDAwOycsIGZhbHNlKTsKKworLS0g QW5kIGNoZWNrIHdlIGdldCB0aGUgZXhwZWN0ZWQgcmVzdWx0cy4KK1NFTEVDVCBDT1VOVCgqKSxB VkcodDEudHdlbnR5KSBGUk9NIHRlbmsxIHQxIExFRlQgSk9JTgorTEFURVJBTCAoU0VMRUNUIHQx LnR3ZW50eSBhcyBjMSwgdDIudW5pcXVlMSBhcyBjMiBGUk9NIHRlbmsxIHQyKSBzIG9uIHRydWUK K1dIRVJFIHMuYzEgPSBzLmMyIGFuZCB0MS51bmlxdWUxIDwgMTAwMDsKKwogLS0gUmVkdWNlIHdv cmtfbWVtIGFuZCBoYXNoX21lbV9tdWx0aXBsaWVyIHNvIHRoYXQgd2Ugc2VlIHNvbWUgY2FjaGUg ZXZpY3Rpb25zCiBTRVQgd29ya19tZW0gVE8gJzY0a0InOwogU0VUIGhhc2hfbWVtX211bHRpcGxp ZXIgVE8gMS4wOwotLSAKMi4zMS4wCgo= --00000000000095ed7105ef619d8f--