haul 01/11/20 04:33:55 Modified: src/org/apache/cocoon/components/language/markup/xsp EsqlQuery.java src/org/apache/cocoon/components/language/markup/xsp/java esql.xsl documentation/xdocs/userdocs/xsp esql.xml Log: Patch from Tim Myers: Adds esql:group + esql:member tags to provide a simpler and (to the DBMS) friendlier alternative to nested queries in some cases. Revision Changes Path 1.4 +18 -0 xml-cocoon2/src/org/apache/cocoon/components/language/markup/xsp/EsqlQuery.java Index: EsqlQuery.java =================================================================== RCS file: /home/cvs/xml-cocoon2/src/org/apache/cocoon/components/language/markup/xsp/EsqlQuery.java,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- EsqlQuery.java 2001/10/26 11:31:33 1.3 +++ EsqlQuery.java 2001/11/20 12:33:55 1.4 @@ -33,6 +33,8 @@ private int position = -1; private int maxRows = -1; private int skipRows = 0; + private boolean keepgoing = true; + private java.util.Hashtable groupingVars = new java.util.Hashtable(); private String query; private int limitMethod; @@ -128,6 +130,22 @@ position++; return(resultSet.next()); } + + public boolean keepGoing() { + return(keepgoing); + } + + public void setKeepGoing( boolean still ) { + keepgoing = still; + } + + public Object setGroupingVar( String key, Object value) { + return groupingVars.put(key,value); + } + + public Object getGroupingVar( String key) { + return groupingVars.get(key); + } public ResultSetMetaData getResultSetMetaData() { return(resultSetMetaData); 1.24 +73 -7 xml-cocoon2/src/org/apache/cocoon/components/language/markup/xsp/java/esql.xsl Index: esql.xsl =================================================================== RCS file: /home/cvs/xml-cocoon2/src/org/apache/cocoon/components/language/markup/xsp/java/esql.xsl,v retrieving revision 1.23 retrieving revision 1.24 diff -u -r1.23 -r1.24 --- esql.xsl 2001/11/19 15:23:53 1.23 +++ esql.xsl 2001/11/20 12:33:55 1.24 @@ -1,5 +1,5 @@ <?xml version="1.0"?> -<!-- $Id: esql.xsl,v 1.23 2001/11/19 15:23:53 haul Exp $--> +<!-- $Id: esql.xsl,v 1.24 2001/11/20 12:33:55 haul Exp $--> <!-- ============================================================================ @@ -583,15 +583,20 @@ </xsl:template> <xsl:template match="esql:results//esql:row-results"> + <xsl:variable name="group" select=".//esql:group"/> <xsp:logic> + + //create booleans for group change watches and strings for old values. + <xsl:apply-templates select=".//esql:group" mode="vars"/> + do { - <xsp:content> + <xsp:content> <xsl:apply-templates/> - </xsp:content> - if (_esql_query.getMaxRows() != -1 && _esql_query.getCurrentRow() - _esql_query.getSkipRows() == _esql_query.getMaxRows() - 1 ) { - break; - } - } while (_esql_query.nextRow()); + </xsp:content> + <xsl:if test="count($group) < 1"> + <xsl:call-template name="nextRow"/> + </xsl:if> + } while ( _esql_query.keepGoing() ); if (_esql_query.getSkipRows() > 0 ) { <xsl:apply-templates select="ancestor::esql:results//esql:previous-results" mode="more"/> @@ -603,12 +608,73 @@ </xsp:logic> </xsl:template> +<xsl:template name="nextRow"> + //checking out early? + if (_esql_query.getMaxRows() != -1 && _esql_query.getCurrentRow() - _esql_query.getSkipRows() == _esql_query.getMaxRows() - 1 ) { + } else { //if not, advance normally + _esql_query.setKeepGoing( _esql_query.nextRow() ); + } +</xsl:template> + <xsl:template match="esql:results//esql:previous-results"/> <xsl:template match="esql:results//esql:previous-results" mode="more"> <xsp:content> <xsl:apply-templates/> </xsp:content> +</xsl:template> + +<xsl:template match="esql:group" mode="vars"> + _esql_query.setGroupingVar("<xsl:value-of select="@group-on"/>Changed", new Boolean(true)); +</xsl:template> + +<xspdoc:desc>Allows header and footer elements around groups of consecutive records with identical values in column named by @group-on. Facilitates a single query with joins to be used in lieu of some nested queries.</xspdoc:desc> +<xsl:template match="esql:group|esql:group//esql:group[.//esql:member]" priority="3"> +<xsp:logic> + if (((Boolean)_esql_query.getGroupingVar("<xsl:value-of select="@group-on"/>Changed")).booleanValue()){ + //header contents + <xsp:content> + <xsl:apply-templates> + <xsl:with-param name="group-on" select="@group-on"/> + </xsl:apply-templates> + </xsp:content> + } +</xsp:logic> +</xsl:template> + +<xsl:template match="esql:group//node()[.//esql:member]"> + <xsl:param name="group-on"/> + <xsl:copy> + <xsl:apply-templates select="@*|*|text()"> + <xsl:with-param name="group-on" select="$group-on"/> + </xsl:apply-templates> + </xsl:copy> +</xsl:template> + +<xspdoc:desc>Used in conjunction with and nested inside esql:group. Formatting for individual records goes within esql:member. Header and footer stuff goes in between group and member.</xspdoc:desc> +<xsl:template match="esql:member|esql:group//esql:member[.//esql:member]"> + <xsl:param name="group-on"/> + <xsl:variable name="group" select=".//esql:group"/> + <xsp:logic> + } + _esql_query.setGroupingVar("<xsl:value-of select="$group-on"/>Old", _esql_query.getResultSet().getString("<xsl:value-of select="$group-on"/>")); + <xsp:content> + <xsl:apply-templates> + <xsl:with-param name="group-on" select="$group-on"/> + </xsl:apply-templates> + </xsp:content> + + <xsl:if test="count($group) < 1"> + <xsl:call-template name="nextRow"/> + </xsl:if> + if ( _esql_query.keepGoing() ) { + _esql_query.setGroupingVar("<xsl:value-of select="$group-on"/>Changed", new Boolean(!((String)_esql_query.getGroupingVar("<xsl:value-of select="$group-on"/>Old")).equals(_esql_query.getResultSet().getString("<xsl:value-of select="$group-on"/>")))); + } else { + _esql_query.setGroupingVar("<xsl:value-of select="$group-on"/>Changed", new Boolean(true)); + } + if (((Boolean)_esql_query.getGroupingVar("<xsl:value-of select="$group-on"/>Changed")).booleanValue()) { + //footer contents + </xsp:logic> </xsl:template> <xsl:template match="esql:results//esql:more-results"/> 1.4 +50 -0 xml-cocoon2/documentation/xdocs/userdocs/xsp/esql.xml Index: esql.xml =================================================================== RCS file: /home/cvs/xml-cocoon2/documentation/xdocs/userdocs/xsp/esql.xml,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- esql.xml 2001/11/19 15:23:53 1.3 +++ esql.xml 2001/11/20 12:33:55 1.4 @@ -87,13 +87,57 @@ </esql:execute-query> </esql:connection>]]> </source> + + <p>For more complex lists, often nested queries are + needed. Esql allows arbitrary nesting of queries. However, + you can do table joins and then insert a header and footer + whenever a "watched" column value changes using the + <code><esql:group/></code> and + <code><esql:member/></code> tags. It follows the + nesting ideology of <code><xsp:logic> + ... <xsp:content></></></code>You can + nest <code><esql:group></code> and + <code><esql:member></code> indefinately.</p> + + <source><![CDATA[ +<esql:execute-query> + <esql:query> + select committeeName, title, firstName, middleName, lastName, suffix, +status from committeeMember left join directoryInformation using(userid) +left join committee on committee.id=committeeMember.committeeid order by +committeeName asc + </esql:query> + <esql:results> + <esql:row-results> + <esql:group group-on="committeeName"> + <h2><esql:get-string column="committeeName"/></h2> + <ul> + <esql:member> + <li> + <esql:get-string column="title"/> + <esql:get-string column="firstName"/> + <esql:get-string column="middleName"/> + <esql:get-string column="lastName"/> + <esql:get-string column="suffix"/> + </li> + </esql:member> + </ul> + </esql:group> + </esql:row-results> + </esql:results> +</esql:execute-query>]]> + </source> + <p>The ultimate reference, is of course the source code, which is an XSLT logicsheet contained in the file <code>src/org/apache/cocoon/components/language/markup/xsp/java/esql.xsl</code></p> <p>Of course, we would be very grateful for any improvements on this documentation or further examples - please send them to <link href="mailto:[EMAIL PROTECTED]">[EMAIL PROTECTED]</link>!</p> + </s1> + + <s1 title="Template Descriptions"> <table> <tr> @@ -185,6 +229,12 @@ <tr><td>esql:results/esql:get-resultset</td> <td>returns the current resultset</td> </tr> + <tr><td>esql:group</td> + <td>Allows header and footer elements around groups of consecutive records with identical values in column named by @group-on. Facilitates a single query with joins to be used in lieu of some nested queries.</td> + </tr> + <tr><td>esql:member</td> + <td>Used in conjunction with and nested inside esql:group. Formatting for individual records goes within esql:member. Header and footer stuff goes in between group and member.</td> + </tr> <tr><td>@*|node()</td> <td>used internally to determine which column is the given column. if a column attribute exists and its value is a number, it is taken to be the column's position. if the value is not a number, it is taken to be the column's name. if a column attribute does not exist, an esql:column element is assumed to exist and to render as a string (after all of the xsp instructions have been evaluated), which is taken to be the column's name.</td> </tr>
---------------------------------------------------------------------- In case of troubles, e-mail: [EMAIL PROTECTED] To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]