Re: SDriverOracle OffesetStrategy
Franck Routier <[email protected]> Mon, 04 Feb 2013 19:01:44 +0100
| Newsgroups | gmane.comp.java.orm.simpleorm |
|---|---|
| Message-ID | <[email protected]> |
--------------ms090508090105040601040108 Content-Type: multipart/alternative; boundary="------------060607000709000307010200" --------------060607000709000307010200 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: quoted-printable Hi, this has been a long process... but I finally implemented a QUERY=20 OffsetStrategy for SDriverOracle that uses Oracle's native rownum idiom. I had to slightly modify the signature of the limitSQL() method, but=20 this was worth the effort: I have a real life example where I read 1 million rows with a 15000=20 limit size, do some deduplication, and insert into another table. Before this modification, it took 54 minutes on Postgresql (on a=20 slightly slower server), but 2 hours and 25 minutes on Oracle (and even=20 2h38 without batch updates)... Query time was getting longer and longer as the offset increased... After the modification, Oracle takes only 43 minutes ! Comments are welcome, Franck Le 03/10/2010 02:20, [email protected] a =E9crit : > > Hello Franck, > > It amazes me that Oracle does not support scrollable cursors in the=20 > database, but there you are. Could you please add a short comment to=20 > the change explaining why you did it. > > There never has been a standard way to do this in traditional SQL. The=20 > Oracle ROWNUM is actually more general than than Limit/Offset -- eg.=20 > you could retrieve every 10th row for sampling, or use it to detect=20 > duplicate rows, pick the "best" etc. If someone is interested it would=20 > not be that hard to wrap our queries with SELECT * FROM <original=20 > query> WHERE ROWNUM.... However, it would not be trivial. > > SQL 2003 implements a very magic CURRENT_ROW() function which is=20 > supported by Oracle and MSSQL, but not much else that I can tell. I=20 > would avoid it as it is complex and therefore more likely to have=20 > issues. (It is amazing that the incredibly complex SQL 92 & 99 did not=20 > address these very basic issues!) > > (Before MSSQL introduced CURRENT_ROW it was just about impossible to=20 > get at any row number, eg. to remove duplicate rows.) > > Thanks for the fix, > > Anthony > > At 02:21 AM 2/10/2010, Franck Routier wrote: > > > > > >I have set SDriverOracle offsetStrategy to SCAN, ie let Simpleorm drop > >records we want to skip. Anyway, this is already what Oracle driver is > >doing (but instead of dropping the records, it keeps them in a cache > >that eats all memory...). > > > >At least, this will always work. > > > >Franck > > > >Le vendredi 01 octobre 2010 =C3 15:42 +0200, Franck Routier a =C3=A9crit= : > >> > >> Yes, I also found this : > >> > >>=20 > <http://stackoverflow.com/questions/595123/is-there-an-ansi-sql-alternati= ve-to-the-mysql-limit-keyword>http://stackoverflow.com/questions/595123/is-= there-an-ansi-sql-alternative-to-the-mysql-limit-keyword > >> > >> Oracle seems to be one of the worse database regarding this issue. > >> But the rownum path is not easy in Simpleorm, as it won't fit in the > >> sql > >> structure that we rely on... > >> > >> Le vendredi 01 octobre 2010 =C3 15:01 +0200, Noel Grandin a =C3=A9crit= : > >> > > >> > these 2 links have some solutions: > >> > > >> >=20 > <http://www.club-oracle.com/forums/limit-clause-for-oracle-sql-t637/>http= ://www.club-oracle.com/forums/limit-clause-for-oracle-sql-t637/ > >> > http://www.delphifaq.com/faq/databases/oracle/f594.shtml > >> > > >> > the basic syntax looks like this: > >> > > >> > select * > >> > from ( > >> > select rownum rnum, a.* > >> > from (your_query) a > >> > where rownum <=3D :M ) > >> > where rnum >=3D :N; > >> > > >> > in order to get rows n through m from 'your query.' > >> > > >> > -- Noel. > >> > > >> > Franck Routier wrote: > >> > > > >> > > > >> > > Seems I spoke too quickly. Oracle does not seem to support the > >> ansi > >> > > (2008) "OFFSET x FETCH y ROWS" syntax, nor any proprietary syntax > >> to > >> > > do > >> > > that... > >> > > > >> > > Le vendredi 01 octobre 2010 =C3 13:55 +0200, Franck Routier a > >> =C3=A9crit : > >> > > > > >> > > > Hi, > >> > > > > >> > > > I am bitten by an oom exception using offset/limit with > >> > > SDriverOracle. > >> > > > The driver uses SDriver.OffsetStrategy.JDBC. The was done > >> assuming > >> > > > (from > >> > > > various reading but without any evidence) that the Oracle Driver > >> > > was > >> > > > smart enought to use a cursor on the server side to handle this. > >> > > > > >> > > > But I definitely get an oom caused by OracleResultCacheImpl > >> eating > >> > > all > >> > > > memory. > >> > > > > >> > > > So I searched again and found this, on > >> > > > > >> > > > >>=20 > <http://download.oracle.com/docs/cd/B28359_01/java.111/b31224/resltset.ht= m#CIHCHBJB>http://download.oracle.com/docs/cd/B28359_01/java.111/b31224/res= ltset.htm#CIHCHBJB > >> > > > > >> > > > "Oracle JDBC Implementation for Result Set Scrollability > >> > > > > >> > > > Because the underlying server does not support scrollable > >> cursors, > >> > > > (sic!) Oracle JDBC must implement scrollability in a separate > >> > > layer. > >> > > > > >> > > > It is important to be aware that this is accomplished by using a > >> > > > client-side memory cache to store rows of a scrollable result > >> set. > >> > > > > >> > > > Important: > >> > > > Because all rows of any scrollable result set are stored in the > >> > > > client-side cache, a situation where the result set contains > >> many > >> > > > rows, > >> > > > many columns, or very large columns might cause the client-side > >> > > Java > >> > > > Virtual Machine (JVM) to fail. Do not specify scrollability for > >> a > >> > > > large > >> > > > result set." > >> > > > > >> > > > So it seems that Oracle is not any smarter than Postgresql is, > >> and > >> > > > that > >> > > > resorting to a limit clause in the sql > >> > > (SDriver.OffsetStrategy.QUERY) > >> > > > would be a better solution for Oracle as well. > >> > > > > >> > > > So I propose to change the SDriverOracle to implement this > >> > > strategy. > >> > > > Does it sound ok ? > >> > > > > >> > > > Franck > >> > > > > >> > > > > >> > > > > >> > > > > >> > > > > >> > > > >> > > -- > >> > > Franck Routier > >> > > Logo Ax=C3=A8ge > >> > > Ax=C3=A8ge > >> > > 23,rue Saint-Simon > >> > > 63000 Clermont-Ferrand > >> > > T=C3=A9l: +33 (0)4 63 05 95 40 > >> > > Fax: +33 (0)4 73 70 65 29 > >> > > Email:=20 > <mailto:franck.routier%40axege.com>[email protected]=20 > <mailto:franck.routier%40axege.com> > >> > > > >> > > > >> > > > >> > > > >> > > >> > > >> > > >> > > >> > __________________________________________________________ > >> > Disclaimer:=20 > <http://www.peralex.com/disclaimer.html>http://www.peralex.com/disclaimer= .html > >> > > >> > > >> > > >> > > >> > > >> > >> -- > >> Franck Routier > >> Logo Ax=C3=A8ge > >> Ax=C3=A8ge > >> 23,rue Saint-Simon > >> 63000 Clermont-Ferrand > >> T=C3=A9l: +33 (0)4 63 05 95 40 > >> Fax: +33 (0)4 73 70 65 29 > >> Email: <mailto:franck.routier%40axege.com>[email protected]=20 > <mailto:franck.routier%40axege.com> > >> > >> > >> > >> > >> > > > >-- > >Franck Routier > >Logo Ax=C3=A8ge > >Ax=C3=A8ge > >23,rue Saint-Simon > >63000 Clermont-Ferrand > >T=C3=A9l: +33 (0)4 63 05 95 40 > >Fax: +33 (0)4 73 70 65 29 > >Email: <mailto:franck.routier%40axege.com>[email protected]=20 > <mailto:franck.routier%40axege.com> > > > > > > Spreadsheet Detective, > Southern Cross Software Queensland Pty Limited > 54 Gerler Street > Bardon, Queensland 4065, Australia. > > Email: [email protected]=20 > <mailto:berglas%40spreadsheetdetective.com> > www.SpreadsheetDetective.com > Ph: +61 427 830248 (Australian Eastern Standard Time) > > "If the model seems correct only because the numbers look right, > then why build the model in the first place?" > >=20 --------------060607000709000307010200 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable <html> <head> <meta content=3D"text/html; charset=3DISO-8859-1" http-equiv=3D"Content-Type"> </head> <body text=3D"#000000" bgcolor=3D"#FFFFFF"> <div class=3D"moz-cite-prefix">Hi,<br> <br> this has been a long process... but I finally implemented a QUERY OffsetStrategy for SDriverOracle that uses Oracle's native rownum idiom.<br> I had to slightly modify the signature of the limitSQL() method, but this was worth the effort:<br> I have a real life example where I read 1 million rows with a 15000 limit size, do some deduplication, and insert into another table.<br> Before this modification, it took 54 minutes on Postgresql (on a slightly slower server), but 2 hours and 25 minutes on Oracle (and even 2h38 without batch updates)...<br> Query time was getting longer and longer as the offset increased...<br> <br> After the modification, Oracle takes only 43 minutes !<br> <br> Comments are welcome,<br> <br> Franck<br> <br> <br> Le 03/10/2010 02:20, <a class=3D"moz-txt-link-abbreviated" href=3D"ma= ilto:[email protected]">[email protected]</a>= a écrit :<br> </div> <blockquote cite=3D"mid:[email protected]= m" type=3D"cite"> <span style=3D"display:none"> </span> =20=20=20=20=20=20 <div id=3D"ygrp-text"> <p>Hello Franck,<br> <br> It amazes me that Oracle does not support scrollable cursors in the database, but there you are. Could you please add a short comment to the change explaining why you did it.<br> <br> There never has been a standard way to do this in traditional SQL. The Oracle ROWNUM is actually more general than than Limit/Offset -- eg. you could retrieve every 10th row for sampling, or use it to detect duplicate rows, pick the "best" etc. If someone is interested it would not be that hard to wrap our queries with SELECT * FROM <original query> WHERE ROWNUM.... However, it would not be trivial.<br> <br> SQL 2003 implements a very magic CURRENT_ROW() function which is supported by Oracle and MSSQL, but not much else that I can tell. I would avoid it as it is complex and therefore more likely to have issues. (It is amazing that the incredibly complex SQL 92 & 99 did not address these very basic issues!)<br> <br> (Before MSSQL introduced CURRENT_ROW it was just about impossible to get at any row number, eg. to remove duplicate rows.)<br> <br> Thanks for the fix,<br> <br> Anthony<br> <br> At 02:21 AM 2/10/2010, Franck Routier wrote:<br> > <br> ><br> >I have set SDriverOracle offsetStrategy to SCAN, ie let Simpleorm drop<br> >records we want to skip. Anyway, this is already what Oracle driver is<br> >doing (but instead of dropping the records, it keeps them in a cache<br> >that eats all memory...).<br> ><br> >At least, this will always work.<br> ><br> >Franck<br> ><br> >Le vendredi 01 octobre 2010 à 15:42 +0200, Franck Routier a écrit :<br> >> <br> >> Yes, I also found this :<br> >> <br> >> <<a moz-do-not-send=3D"true" href=3D"http://stackoverflow.com/questions/595123/is-there-an-ansi-sql-alte= rnative-to-the-mysql-limit-keyword">http://stackoverflow.com/questions/5951= 23/is-there-an-ansi-sql-alternative-to-the-mysql-limit-keyword</a>><a moz-do-not-send=3D"true" href=3D"http://stackoverflow.com/questions/595123/is-there-an-ansi-sql-alte= rnative-to-the-mysql-limit-keyword">http://stackoverflow.com/questions/5951= 23/is-there-an-ansi-sql-alternative-to-the-mysql-limit-keyword</a><br> >> <br> >> Oracle seems to be one of the worse database regarding this issue.<br> >> But the rownum path is not easy in Simpleorm, as it won't fit in the<br> >> sql<br> >> structure that we rely on...<br> >> <br> >> Le vendredi 01 octobre 2010 à 15:01 +0200, No= el Grandin a écrit :<br> >> > <br> >> > these 2 links have some solutions:<br> >> > <br> >> > <<a moz-do-not-send=3D"true" href=3D"http://www.club-oracle.com/forums/limit-clause-for-oracle-sql-t637/= ">http://www.club-oracle.com/forums/limit-clause-for-oracle-sql-t637/</a>&g= t;<a moz-do-not-send=3D"true" href=3D"http://www.club-oracle.com/forums/limit-clause-for-oracle-sql-t637/= ">http://www.club-oracle.com/forums/limit-clause-for-oracle-sql-t637/</a><b= r> >> > <a moz-do-not-send=3D"true" href=3D"http://www.delphifaq.com/faq/databases/oracle/f594.= shtml">http://www.delphifaq.com/faq/databases/oracle/f594.shtml</a><br> >> > <br> >> > the basic syntax looks like this:<br> >> > <br> >> > select * <br> >> > from ( <br> >> > select rownum rnum, a.* <br> >> > from (your_query) a <br> >> > where rownum <=3D :M ) <br> >> > where rnum >=3D :N; <br> >> > <br> >> > in order to get rows n through m from 'your query.'<br> >> > <br> >> > -- Noel.<br> >> > <br> >> > Franck Routier wrote: <br> >> > > <br> >> > > <br> >> > > Seems I spoke too quickly. Oracle does not seem to support the<br> >> ansi<br> >> > > (2008) "OFFSET x FETCH y ROWS" syntax, nor any proprietary syntax<br> >> to<br> >> > > do<br> >> > > that...<br> >> > > <br> >> > > Le vendredi 01 octobre 2010 à 13:55 +0200, Franck Routier a<br> >> écrit :<br> >> > > > <br> >> > > > Hi,<br> >> > > > <br> >> > > > I am bitten by an oom exception using offset/limit with<br> >> > > SDriverOracle.<br> >> > > > The driver uses SDriver.OffsetStrategy.JDBC. The was done<br> >> assuming<br> >> > > > (from<br> >> > > > various reading but without any evidence) that the Oracle Driver<br> >> > > was<br> >> > > > smart enought to use a cursor on the server side to handle this.<br> >> > > > <br> >> > > > But I definitely get an oom caused by OracleResultCacheImpl<br> >> eating<br> >> > > all<br> >> > > > memory.<br> >> > > > <br> >> > > > So I searched again and found this, on<br> >> > > ><br> >> > ><br> >> <<a moz-do-not-send=3D"true" href=3D"http://download.oracle.com/docs/cd/B28359_01/java.111/b31224/reslts= et.htm#CIHCHBJB">http://download.oracle.com/docs/cd/B28359_01/java.111/b312= 24/resltset.htm#CIHCHBJB</a>><a moz-do-not-send=3D"true" href=3D"http://download.oracle.com/docs/cd/B28359_01/java.111/b31224/reslts= et.htm#CIHCHBJB">http://download.oracle.com/docs/cd/B28359_01/java.111/b312= 24/resltset.htm#CIHCHBJB</a><br> >> > > > <br> >> > > > "Oracle JDBC Implementation for Result Set Scrollability<br> >> > > > <br> >> > > > Because the underlying server does not support scrollable<br> >> cursors,<br> >> > > > (sic!) Oracle JDBC must implement scrollability in a separate<br> >> > > layer.<br> >> > > > <br> >> > > > It is important to be aware that this is accomplished by using a<br> >> > > > client-side memory cache to store rows of a scrollable result<br> >> set.<br> >> > > > <br> >> > > > Important:<br> >> > > > Because all rows of any scrollable result set are stored in the<br> >> > > > client-side cache, a situation where the result set contains<br> >> many<br> >> > > > rows,<br> >> > > > many columns, or very large columns might cause the client-side<br> >> > > Java<br> >> > > > Virtual Machine (JVM) to fail. Do not specify scrollability for<br> >> a<br> >> > > > large<br> >> > > > result set."<br> >> > > > <br> >> > > > So it seems that Oracle is not any smarter than Postgresql is,<br> >> and<br> >> > > > that<br> >> > > > resorting to a limit clause in the sql<br> >> > > (SDriver.OffsetStrategy.QUERY)<br> >> > > > would be a better solution for Oracle as well.<br> >> > > > <br> >> > > > So I propose to change the SDriverOracle to implement this<br> >> > > strategy.<br> >> > > > Does it sound ok ?<br> >> > > > <br> >> > > > Franck<br> >> > > > <br> >> > > > <br> >> > > > <br> >> > > > <br> >> > > > <br> >> > > <br> >> > > -- <br> >> > > Franck Routier <br> >> > > Logo Axège<br> >> > > Axège<br> >> > > 23,rue Saint-Simon<br> >> > > 63000 Clermont-Ferrand<br> >> > > Tél: +33 (0)4 63 05 95 40<br> >> > > Fax: +33 (0)4 73 70 65 29<br> >> > > Email: <a class=3D"moz-txt-link-rfc2396E" href=3D"mailto:franck.rout= ier%40axege.com"><mailto:franck.routier%40axege.com></a><a moz-do-not-send=3D"true" href=3D"mailto:franck.routier%40axege.com">franck.routier@a= xege.com</a><br> >> > > <br> >> > > <br> >> > > <br> >> > > <br> >> > <br> >> > <br> >> > <br> >> > <br> >> > __________________________________________________________<br= > >> > Disclaimer: <<a moz-do-not-send=3D"true" href=3D"http://www.peralex.com/disclaimer.html">http://www.= peralex.com/disclaimer.html</a>><a moz-do-not-send=3D"true" href=3D"http://www.peralex.com/disclaimer.html">http://www.= peralex.com/disclaimer.html</a><br> >> > <br> >> > <br> >> > <br> >> > <br> >> > <br> >> <br> >> -- <br> >> Franck Routier <br> >> Logo Axège<br> >> Axège<br> >> 23,rue Saint-Simon<br> >> 63000 Clermont-Ferrand<br> >> Tél: +33 (0)4 63 05 95 40<br> >> Fax: +33 (0)4 73 70 65 29<br> >> Email: <a class=3D"moz-txt-link-rfc2396E" href=3D"ma= ilto:franck.routier%40axege.com"><mailto:franck.routier%40axege.com><= /a><a moz-do-not-send=3D"true" href=3D"mailto:franck.routier%40axege.com">franck.routier@a= xege.com</a><br> >> <br> >> <br> >> <br> >> <br> >> <br> ><br> >-- <br> >Franck Routier <br> >Logo Axège<br> >Axège<br> >23,rue Saint-Simon<br> >63000 Clermont-Ferrand<br> >Tél: +33 (0)4 63 05 95 40<br> >Fax: +33 (0)4 73 70 65 29<br> >Email: <a class=3D"moz-txt-link-rfc2396E" href=3D"mailto:= franck.routier%40axege.com"><mailto:franck.routier%40axege.com></a><a moz-do-not-send=3D"true" href=3D"mailto:franck.routier%40axege.com">franck.routier@a= xege.com</a><br> ><br> ><br> <br> Spreadsheet Detective,<br> Southern Cross Software Queensland Pty Limited<br> 54 Gerler Street<br> Bardon, Queensland 4065, Australia.<br> <br> Email: <a moz-do-not-send=3D"true" href=3D"mailto:berglas%40spreadsheetdetective.com">berglas@= spreadsheetdetective.com</a><br> <a class=3D"moz-txt-link-abbreviated" href=3D"http://www.Spre= adsheetDetective.com">www.SpreadsheetDetective.com</a><br> Ph: +61 427 830248 (Australian Eastern Standard Time)<br> <br> "If the model seems correct only because the numbers look right, <br> then why build the model in the first place?"<br> <br> </p> </div> =20=20=20=20=20=20=20=20=20=20 =20=20=20=20=20=20 <!-- end group email --> </blockquote> <br> </body> </html> --------------060607000709000307010200-- --------------ms090508090105040601040108 Content-Type: application/pkcs7-signature; name="smime.p7s" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="smime.p7s" Content-Description: Signature cryptographique S/MIME MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAQAAoIINYjCC BjQwggQcoAMCAQICAR4wDQYJKoZIhvcNAQEFBQAwfTELMAkGA1UEBhMCSUwxFjAUBgNVBAoT DVN0YXJ0Q29tIEx0ZC4xKzApBgNVBAsTIlNlY3VyZSBEaWdpdGFsIENlcnRpZmljYXRlIFNp Z25pbmcxKTAnBgNVBAMTIFN0YXJ0Q29tIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA3 MTAyNDIxMDE1NVoXDTE3MTAyNDIxMDE1NVowgYwxCzAJBgNVBAYTAklMMRYwFAYDVQQKEw1T dGFydENvbSBMdGQuMSswKQYDVQQLEyJTZWN1cmUgRGlnaXRhbCBDZXJ0aWZpY2F0ZSBTaWdu aW5nMTgwNgYDVQQDEy9TdGFydENvbSBDbGFzcyAxIFByaW1hcnkgSW50ZXJtZWRpYXRlIENs aWVudCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMcJg8zOLdgasSmkLhOr lr6KMoOMpohBllVHrdRvEg/q6r8jR+EK75xCGhR8ToREoqe7zM9/UnC6TS2y9UKTpT1v7RSM zR0t6ndl0TWBuUr/UXBhPk+Kmy7bI4yW4urC+y7P3/1/X7U8ocb8VpH/Clt+4iq7nirMcNh6 qJR+xjOhV+VHzQMALuGYn5KZmc1NbJQYclsGkDxDz2UbFqE2+6vIZoL+jb9x4Pa5gNf1TwSD kOkikZB1xtB4ZqtXThaABSONdfmv/Z1pua3FYxnCFmdr/+N2JLKutIxMYqQOJebr/f/h5t95 m4JgrM3Y/w7YX9d7YAL9jvN4SydHsU6n65cCAwEAAaOCAa0wggGpMA8GA1UdEwEB/wQFMAMB Af8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRTcu2SnODaywFcfH6WNU7y1LhRgjAfBgNV HSMEGDAWgBROC+8apEBbpRdphzDKNGhD0EGu8jBmBggrBgEFBQcBAQRaMFgwJwYIKwYBBQUH MAGGG2h0dHA6Ly9vY3NwLnN0YXJ0c3NsLmNvbS9jYTAtBggrBgEFBQcwAoYhaHR0cDovL3d3 dy5zdGFydHNzbC5jb20vc2ZzY2EuY3J0MFsGA1UdHwRUMFIwJ6AloCOGIWh0dHA6Ly93d3cu c3RhcnRzc2wuY29tL3Nmc2NhLmNybDAnoCWgI4YhaHR0cDovL2NybC5zdGFydHNzbC5jb20v c2ZzY2EuY3JsMIGABgNVHSAEeTB3MHUGCysGAQQBgbU3AQIBMGYwLgYIKwYBBQUHAgEWImh0 dHA6Ly93d3cuc3RhcnRzc2wuY29tL3BvbGljeS5wZGYwNAYIKwYBBQUHAgEWKGh0dHA6Ly93 d3cuc3RhcnRzc2wuY29tL2ludGVybWVkaWF0ZS5wZGYwDQYJKoZIhvcNAQEFBQADggIBAAqD CH14qywGXLhjjF6uHLkjd02hcdh9hrw+VUsv+q1eeQWB21jWj3kJ96AUlPCoEGZ/ynJNScWy 6QMVQjbbMXltUfO4n4bGGdKo3awPWp61tjAFgraLJgDk+DsSvUD6EowjMTNx25GQgyYJ5RPI zKKR9tQW8gGK+2+RHxkUCTbYFnL6kl8Ch507rUdPPipJ9CgJFws3kDS3gOS5WFMxcjO5DwKf KSETEPrHh7p5shuuNktvsv6hxHTLhiMKX893gxdT3XLS9OKmCv87vkINQcNEcIIoFWbP9HOR z9v3vQwR4e3ksLc2JZOAFK+ssS5XMEoznzpihEP0PLc4dCBYjbvSD7kxgDwZ+Aj8Q9PkbvE9 sIPP7ON0fz095HdThKjiVJe6vofq+n6b1NBc8XdrQvBmunwxD5nvtTW4vtN6VY7mUCmxsCie uoBJ9OlqmsVWQvifIYf40dJPZkk9YgGTzWLpXDSfLSplbY2LL9C9U0ptvjcDjefLTvqSFc7t w1sEhF0n/qpA2r0GpvkLRDmcSwVyPvmjFBGqUp/pNy8ZuPGQmHwFi2/14+xeSUDG2bwnsYJQ G2EdJCB6luQ57GEnTA/yKZSTKI8dDQa8Sd3zfXb19mOgSF0bBdXbuKhEpuP9wirslFe6fQ1t 5j5R0xi72MZ8ikMu1RQZKCyDbMwazlHiMIIHJjCCBg6gAwIBAgIDBNFnMA0GCSqGSIb3DQEB BQUAMIGMMQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMi U2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzE4MDYGA1UEAxMvU3RhcnRDb20g Q2xhc3MgMSBQcmltYXJ5IEludGVybWVkaWF0ZSBDbGllbnQgQ0EwHhcNMTIwODI5MjAxNTIz WhcNMTMwODMxMDg0MTExWjBnMRkwFwYDVQQNExBmQ0cxTUdlTUM1dkZVNVlKMSEwHwYDVQQD DBhmcmFuY2sucm91dGllckBheGVnZS5jb20xJzAlBgkqhkiG9w0BCQEWGGZyYW5jay5yb3V0 aWVyQGF4ZWdlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK5kIRjbP769 72PM00wgFczTGqmiU5dAY8XlSziUNq434SJZ3rFZoL0MY6hqVb/p5+u+u6TdhsVywJclPaZE v+FgGtk74JvlX6oeSWJTOiGLTrk0TRwy7Q+80kbneFdhL+yk/ZTxxcj15IEOeWMuyG/IyePq H4GtZMkCpsuCOL5bkq9g/H0JHyLSM0tWDbMuD4vKbSeBkzwiz4pSwuANCFMFeRr3d9iZQU0P VzyKvu/cEUcdoDcVGMuMxX6FwgqrS5c70v/RPM8FafOrqprYfIxVQwxK9IhPgqM9kT6riQo6 OM62d2a21Y6iAeWe/1rssTKn+Stj8jH706LmVJlEGtcCAwEAAaOCA7MwggOvMAkGA1UdEwQC MAAwCwYDVR0PBAQDAgSwMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDBDAdBgNVHQ4E FgQUCfIkqGdMRvMTjM6TIpdcUPqdYW8wHwYDVR0jBBgwFoAUU3Ltkpzg2ssBXHx+ljVO8tS4 UYIwIwYDVR0RBBwwGoEYZnJhbmNrLnJvdXRpZXJAYXhlZ2UuY29tMIICIQYDVR0gBIICGDCC AhQwggIQBgsrBgEEAYG1NwECAjCCAf8wLgYIKwYBBQUHAgEWImh0dHA6Ly93d3cuc3RhcnRz c2wuY29tL3BvbGljeS5wZGYwNAYIKwYBBQUHAgEWKGh0dHA6Ly93d3cuc3RhcnRzc2wuY29t L2ludGVybWVkaWF0ZS5wZGYwgfcGCCsGAQUFBwICMIHqMCcWIFN0YXJ0Q29tIENlcnRpZmlj YXRpb24gQXV0aG9yaXR5MAMCAQEagb5UaGlzIGNlcnRpZmljYXRlIHdhcyBpc3N1ZWQgYWNj b3JkaW5nIHRvIHRoZSBDbGFzcyAxIFZhbGlkYXRpb24gcmVxdWlyZW1lbnRzIG9mIHRoZSBT dGFydENvbSBDQSBwb2xpY3ksIHJlbGlhbmNlIG9ubHkgZm9yIHRoZSBpbnRlbmRlZCBwdXJw b3NlIGluIGNvbXBsaWFuY2Ugb2YgdGhlIHJlbHlpbmcgcGFydHkgb2JsaWdhdGlvbnMuMIGc BggrBgEFBQcCAjCBjzAnFiBTdGFydENvbSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTADAgEC GmRMaWFiaWxpdHkgYW5kIHdhcnJhbnRpZXMgYXJlIGxpbWl0ZWQhIFNlZSBzZWN0aW9uICJM ZWdhbCBhbmQgTGltaXRhdGlvbnMiIG9mIHRoZSBTdGFydENvbSBDQSBwb2xpY3kuMDYGA1Ud HwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwuc3RhcnRzc2wuY29tL2NydHUxLWNybC5jcmwwgY4G CCsGAQUFBwEBBIGBMH8wOQYIKwYBBQUHMAGGLWh0dHA6Ly9vY3NwLnN0YXJ0c3NsLmNvbS9z dWIvY2xhc3MxL2NsaWVudC9jYTBCBggrBgEFBQcwAoY2aHR0cDovL2FpYS5zdGFydHNzbC5j b20vY2VydHMvc3ViLmNsYXNzMS5jbGllbnQuY2EuY3J0MCMGA1UdEgQcMBqGGGh0dHA6Ly93 d3cuc3RhcnRzc2wuY29tLzANBgkqhkiG9w0BAQUFAAOCAQEAGSGlokCrFniLxjc6W072LqWy ISRKEqeC9u0pYSoQGVPAy1mNbu28ThrfAk8umOfFEDkzVH0TXH33TbsCViwsE/rCk6FC0U+Q AMOn1Ajjf/9z7w8+zCHgmbLyABtYrmBO6AhCD7YLKYPE1VXkJvgdcHCKzVLIkvdIyKSkRn+R lSorTXhg64lR8vQSX8C9EAY0T/hQyjFS9SDcEhsfOjkYdAiG7fVBft24Gj+3oDgk2479W47l phG1aHhkflrDeho0h6LnGxY0+PATPuUkvDsr/RFE2VviGFH9UDxjNJmikrmTibCvS4seQFOm ppHmJzqIcxcn5dqeBDVQYZmLhDkszjGCA90wggPZAgEBMIGUMIGMMQswCQYDVQQGEwJJTDEW MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlm aWNhdGUgU2lnbmluZzE4MDYGA1UEAxMvU3RhcnRDb20gQ2xhc3MgMSBQcmltYXJ5IEludGVy bWVkaWF0ZSBDbGllbnQgQ0ECAwTRZzAJBgUrDgMCGgUAoIICHTAYBgkqhkiG9w0BCQMxCwYJ KoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0xMzAyMDQxODAxNDRaMCMGCSqGSIb3DQEJBDEW BBS9p0PsY8tHsLopElusOPbBt2xtSTBsBgkqhkiG9w0BCQ8xXzBdMAsGCWCGSAFlAwQBKjAL BglghkgBZQMEAQIwCgYIKoZIhvcNAwcwDgYIKoZIhvcNAwICAgCAMA0GCCqGSIb3DQMCAgFA MAcGBSsOAwIHMA0GCCqGSIb3DQMCAgEoMIGlBgkrBgEEAYI3EAQxgZcwgZQwgYwxCzAJBgNV BAYTAklMMRYwFAYDVQQKEw1TdGFydENvbSBMdGQuMSswKQYDVQQLEyJTZWN1cmUgRGlnaXRh bCBDZXJ0aWZpY2F0ZSBTaWduaW5nMTgwNgYDVQQDEy9TdGFydENvbSBDbGFzcyAxIFByaW1h cnkgSW50ZXJtZWRpYXRlIENsaWVudCBDQQIDBNFnMIGnBgsqhkiG9w0BCRACCzGBl6CBlDCB jDELMAkGA1UEBhMCSUwxFjAUBgNVBAoTDVN0YXJ0Q29tIEx0ZC4xKzApBgNVBAsTIlNlY3Vy ZSBEaWdpdGFsIENlcnRpZmljYXRlIFNpZ25pbmcxODA2BgNVBAMTL1N0YXJ0Q29tIENsYXNz IDEgUHJpbWFyeSBJbnRlcm1lZGlhdGUgQ2xpZW50IENBAgME0WcwDQYJKoZIhvcNAQEBBQAE ggEAftYrvFIQaurBjrxL/0xMx07xa6ezh7Dt0TwBsiZ+Q/i4Ozfjbbv0FrKECM3RyfiDKfIf KZD/8yUxba/yjDf+iUlCpqBtot7WLrMkTmzHnxHhellUKMgxHP3E0nOsZYKxtHTESFCS4+// 048GgTGSswWjSXT+hvUchXDBee0Y0V57v5j4zLhEtLp5p9D6NVh2FEN2VCZ35RI9RTC2/yBV +c9OOYW2SlWVAMddM9oXC+NIJQcRG33iqCJPyVxL8OTUtnm5CEIM4zFumZ6w+AYndQdFwQww 4ikIeUJusi+/gwqp5nuWN6PukIHnMJG2ONF0jTJKtGeO4rb96DYEYg6E2wAAAAAAAA== --------------ms090508090105040601040108--