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 &eacute;crit&nbsp;:<br>
    </div>
    <blockquote
      cite=3D"mid:[email protected]=
m"
      type=3D"cite">
      <span style=3D"display:none">&nbsp;</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 &lt;original query&gt; 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 &amp; 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>
              &gt; <br>
              &gt;<br>
              &gt;I have set SDriverOracle offsetStrategy to SCAN, ie
              let Simpleorm drop<br>
              &gt;records we want to skip. Anyway, this is already what
              Oracle driver is<br>
              &gt;doing (but instead of dropping the records, it keeps
              them in a cache<br>
              &gt;that eats all memory...).<br>
              &gt;<br>
              &gt;At least, this will always work.<br>
              &gt;<br>
              &gt;Franck<br>
              &gt;<br>
              &gt;Le vendredi 01 octobre 2010 &Atilde; 15:42 +0200, Franck
              Routier a &Atilde;&copy;crit :<br>
              &gt;&gt; <br>
              &gt;&gt; Yes, I also found this :<br>
              &gt;&gt; <br>
              &gt;&gt; &lt;<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>&gt;<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>
              &gt;&gt; <br>
              &gt;&gt; Oracle seems to be one of the worse database
              regarding this issue.<br>
              &gt;&gt; But the rownum path is not easy in Simpleorm, as
              it won't fit in the<br>
              &gt;&gt; sql<br>
              &gt;&gt; structure that we rely on...<br>
              &gt;&gt; <br>
              &gt;&gt; Le vendredi 01 octobre 2010 &Atilde; 15:01 +0200, No=
el
              Grandin a &Atilde;&copy;crit :<br>
              &gt;&gt; &gt; <br>
              &gt;&gt; &gt; these 2 links have some solutions:<br>
              &gt;&gt; &gt; <br>
              &gt;&gt; &gt; &lt;<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>
              &gt;&gt; &gt; <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>
              &gt;&gt; &gt; <br>
              &gt;&gt; &gt; the basic syntax looks like this:<br>
              &gt;&gt; &gt; <br>
              &gt;&gt; &gt; select * <br>
              &gt;&gt; &gt; from ( <br>
              &gt;&gt; &gt; select rownum rnum, a.* <br>
              &gt;&gt; &gt; from (your_query) a <br>
              &gt;&gt; &gt; where rownum &lt;=3D :M ) <br>
              &gt;&gt; &gt; where rnum &gt;=3D :N; <br>
              &gt;&gt; &gt; <br>
              &gt;&gt; &gt; in order to get rows n through m from 'your
              query.'<br>
              &gt;&gt; &gt; <br>
              &gt;&gt; &gt; -- Noel.<br>
              &gt;&gt; &gt; <br>
              &gt;&gt; &gt; Franck Routier wrote: <br>
              &gt;&gt; &gt; &gt; <br>
              &gt;&gt; &gt; &gt; <br>
              &gt;&gt; &gt; &gt; Seems I spoke too quickly. Oracle does
              not seem to support the<br>
              &gt;&gt; ansi<br>
              &gt;&gt; &gt; &gt; (2008) "OFFSET x FETCH y ROWS" syntax,
              nor any proprietary syntax<br>
              &gt;&gt; to<br>
              &gt;&gt; &gt; &gt; do<br>
              &gt;&gt; &gt; &gt; that...<br>
              &gt;&gt; &gt; &gt; <br>
              &gt;&gt; &gt; &gt; Le vendredi 01 octobre 2010 &Atilde; 13:55
              +0200, Franck Routier a<br>
              &gt;&gt; &Atilde;&copy;crit :<br>
              &gt;&gt; &gt; &gt; &gt; <br>
              &gt;&gt; &gt; &gt; &gt; Hi,<br>
              &gt;&gt; &gt; &gt; &gt; <br>
              &gt;&gt; &gt; &gt; &gt; I am bitten by an oom exception
              using offset/limit with<br>
              &gt;&gt; &gt; &gt; SDriverOracle.<br>
              &gt;&gt; &gt; &gt; &gt; The driver uses
              SDriver.OffsetStrategy.JDBC. The was done<br>
              &gt;&gt; assuming<br>
              &gt;&gt; &gt; &gt; &gt; (from<br>
              &gt;&gt; &gt; &gt; &gt; various reading but without any
              evidence) that the Oracle Driver<br>
              &gt;&gt; &gt; &gt; was<br>
              &gt;&gt; &gt; &gt; &gt; smart enought to use a cursor on
              the server side to handle this.<br>
              &gt;&gt; &gt; &gt; &gt; <br>
              &gt;&gt; &gt; &gt; &gt; But I definitely get an oom caused
              by OracleResultCacheImpl<br>
              &gt;&gt; eating<br>
              &gt;&gt; &gt; &gt; all<br>
              &gt;&gt; &gt; &gt; &gt; memory.<br>
              &gt;&gt; &gt; &gt; &gt; <br>
              &gt;&gt; &gt; &gt; &gt; So I searched again and found
              this, on<br>
              &gt;&gt; &gt; &gt; &gt;<br>
              &gt;&gt; &gt; &gt;<br>
              &gt;&gt; &lt;<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>&gt;<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>
              &gt;&gt; &gt; &gt; &gt; <br>
              &gt;&gt; &gt; &gt; &gt; "Oracle JDBC Implementation for
              Result Set Scrollability<br>
              &gt;&gt; &gt; &gt; &gt; <br>
              &gt;&gt; &gt; &gt; &gt; Because the underlying server does
              not support scrollable<br>
              &gt;&gt; cursors,<br>
              &gt;&gt; &gt; &gt; &gt; (sic!) Oracle JDBC must implement
              scrollability in a separate<br>
              &gt;&gt; &gt; &gt; layer.<br>
              &gt;&gt; &gt; &gt; &gt; <br>
              &gt;&gt; &gt; &gt; &gt; It is important to be aware that
              this is accomplished by using a<br>
              &gt;&gt; &gt; &gt; &gt; client-side memory cache to store
              rows of a scrollable result<br>
              &gt;&gt; set.<br>
              &gt;&gt; &gt; &gt; &gt; <br>
              &gt;&gt; &gt; &gt; &gt; Important:<br>
              &gt;&gt; &gt; &gt; &gt; Because all rows of any scrollable
              result set are stored in the<br>
              &gt;&gt; &gt; &gt; &gt; client-side cache, a situation
              where the result set contains<br>
              &gt;&gt; many<br>
              &gt;&gt; &gt; &gt; &gt; rows,<br>
              &gt;&gt; &gt; &gt; &gt; many columns, or very large
              columns might cause the client-side<br>
              &gt;&gt; &gt; &gt; Java<br>
              &gt;&gt; &gt; &gt; &gt; Virtual Machine (JVM) to fail. Do
              not specify scrollability for<br>
              &gt;&gt; a<br>
              &gt;&gt; &gt; &gt; &gt; large<br>
              &gt;&gt; &gt; &gt; &gt; result set."<br>
              &gt;&gt; &gt; &gt; &gt; <br>
              &gt;&gt; &gt; &gt; &gt; So it seems that Oracle is not any
              smarter than Postgresql is,<br>
              &gt;&gt; and<br>
              &gt;&gt; &gt; &gt; &gt; that<br>
              &gt;&gt; &gt; &gt; &gt; resorting to a limit clause in the
              sql<br>
              &gt;&gt; &gt; &gt; (SDriver.OffsetStrategy.QUERY)<br>
              &gt;&gt; &gt; &gt; &gt; would be a better solution for
              Oracle as well.<br>
              &gt;&gt; &gt; &gt; &gt; <br>
              &gt;&gt; &gt; &gt; &gt; So I propose to change the
              SDriverOracle to implement this<br>
              &gt;&gt; &gt; &gt; strategy.<br>
              &gt;&gt; &gt; &gt; &gt; Does it sound ok ?<br>
              &gt;&gt; &gt; &gt; &gt; <br>
              &gt;&gt; &gt; &gt; &gt; Franck<br>
              &gt;&gt; &gt; &gt; &gt; <br>
              &gt;&gt; &gt; &gt; &gt; <br>
              &gt;&gt; &gt; &gt; &gt; <br>
              &gt;&gt; &gt; &gt; &gt; <br>
              &gt;&gt; &gt; &gt; &gt; <br>
              &gt;&gt; &gt; &gt; <br>
              &gt;&gt; &gt; &gt; -- <br>
              &gt;&gt; &gt; &gt; Franck Routier <br>
              &gt;&gt; &gt; &gt; Logo Ax&Atilde;&uml;ge<br>
              &gt;&gt; &gt; &gt; Ax&Atilde;&uml;ge<br>
              &gt;&gt; &gt; &gt; 23,rue Saint-Simon<br>
              &gt;&gt; &gt; &gt; 63000 Clermont-Ferrand<br>
              &gt;&gt; &gt; &gt; T&Atilde;&copy;l: +33 (0)4 63 05 95 40<br>
              &gt;&gt; &gt; &gt; Fax: +33 (0)4 73 70 65 29<br>
              &gt;&gt; &gt; &gt; Email:
              <a class=3D"moz-txt-link-rfc2396E" href=3D"mailto:franck.rout=
ier%40axege.com">&lt;mailto:franck.routier%40axege.com&gt;</a><a
                moz-do-not-send=3D"true"
                href=3D"mailto:franck.routier%40axege.com">franck.routier@a=
xege.com</a><br>
              &gt;&gt; &gt; &gt; <br>
              &gt;&gt; &gt; &gt; <br>
              &gt;&gt; &gt; &gt; <br>
              &gt;&gt; &gt; &gt; <br>
              &gt;&gt; &gt; <br>
              &gt;&gt; &gt; <br>
              &gt;&gt; &gt; <br>
              &gt;&gt; &gt; <br>
              &gt;&gt; &gt;
              __________________________________________________________<br=
>
              &gt;&gt; &gt; Disclaimer: &lt;<a moz-do-not-send=3D"true"
                href=3D"http://www.peralex.com/disclaimer.html">http://www.=
peralex.com/disclaimer.html</a>&gt;<a
                moz-do-not-send=3D"true"
                href=3D"http://www.peralex.com/disclaimer.html">http://www.=
peralex.com/disclaimer.html</a><br>
              &gt;&gt; &gt; <br>
              &gt;&gt; &gt; <br>
              &gt;&gt; &gt; <br>
              &gt;&gt; &gt; <br>
              &gt;&gt; &gt; <br>
              &gt;&gt; <br>
              &gt;&gt; -- <br>
              &gt;&gt; Franck Routier <br>
              &gt;&gt; Logo Ax&Atilde;&uml;ge<br>
              &gt;&gt; Ax&Atilde;&uml;ge<br>
              &gt;&gt; 23,rue Saint-Simon<br>
              &gt;&gt; 63000 Clermont-Ferrand<br>
              &gt;&gt; T&Atilde;&copy;l: +33 (0)4 63 05 95 40<br>
              &gt;&gt; Fax: +33 (0)4 73 70 65 29<br>
              &gt;&gt; Email: <a class=3D"moz-txt-link-rfc2396E" href=3D"ma=
ilto:franck.routier%40axege.com">&lt;mailto:franck.routier%40axege.com&gt;<=
/a><a
                moz-do-not-send=3D"true"
                href=3D"mailto:franck.routier%40axege.com">franck.routier@a=
xege.com</a><br>
              &gt;&gt; <br>
              &gt;&gt; <br>
              &gt;&gt; <br>
              &gt;&gt; <br>
              &gt;&gt; <br>
              &gt;<br>
              &gt;-- <br>
              &gt;Franck Routier <br>
              &gt;Logo Ax&Atilde;&uml;ge<br>
              &gt;Ax&Atilde;&uml;ge<br>
              &gt;23,rue Saint-Simon<br>
              &gt;63000 Clermont-Ferrand<br>
              &gt;T&Atilde;&copy;l: +33 (0)4 63 05 95 40<br>
              &gt;Fax: +33 (0)4 73 70 65 29<br>
              &gt;Email: <a class=3D"moz-txt-link-rfc2396E" href=3D"mailto:=
franck.routier%40axege.com">&lt;mailto:franck.routier%40axege.com&gt;</a><a
                moz-do-not-send=3D"true"
                href=3D"mailto:franck.routier%40axege.com">franck.routier@a=
xege.com</a><br>
              &gt;<br>
              &gt;<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--