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]