Team,

I'm currently considering ORDBMS support in esql, well, actually, I
do have a version here that does it for C2. Davanum asked me to post
any patches to esql.xsl to this list before applying them. So please
comment the attached diff.

This mail is largely based on my posting from jul-04 on ordbms support
for esql with few modifications and comments what is already in
place.
 
The simplest ORDBMS support would be to allow the user to get an
object from the query and to leave it to her/him how to deal with it.
(done) 

In addition one could extend get-columns to extract advanced datatypes
as well. Over here on Informix IUS 9.21 these are mostly of
java.sql.Types.STRUCT for row types and java.sql.Types.OTHER for
everything else like sets, lists, bags. One way to determine the
correct type would be to try to cast the object to an appropriate
interface, say java.util.Set.
(done -- C2 only) 


How should the structure of an attribute be represented? Nesting alone
wouldn't do since it wouldn't be possible to distinguish sets from
structs. So we should introduce something like "sql-list", "sql-row",
"sql-set", plus some "sql-item" elements to capture e.g. the list
members. So far I didn't find a way e.g. to name the components of a
struct.
(done -- C2 only)

 
Another issue arises: encoding. "First class" attributes can be read
through getBytes() and converted afterwards. But nested attributes
only offer a toString() method, right? Would it be right to disable
the encoding parameter on nested attributes?
(currently no encoding for complex attributes)

 
Another feature could be, to manipulate the type mapping table for a
jdbc connection and allow to map advanced or user defined types to
map to a user provided java class. Jdbc drivers sometimes come with a
utility to create such a class from a db schema.
(not done -- should this be done? should this be done in cocoon.xconf
per connection pool?)

 
Other features I'd like to see in esql:

<esql:row-results> &c. "swallow" nested text which is not what users
expect (see cocoon-users list). Therefore it would be nice if the text
would be automtically enclosed in <xsp:content>.
(done --  example query is "select count(*) from mytable":
          <esql:row-results>
              Currently <esql:get-int column="1"/> rows are present.
          </esql:row-results>
) 

 
Supplying column names / numbers from a XSP variable (esql differs
from other taglibs in that it doesn't use the
"<esql:param name="column">1</esql:param>" notation, instead it uses
"<esql:column></esql:column>". I would like to change that.)
(done, you can now <esql:get-column>
                      <esql:param name="column">
                          <xsp:expr>i</xsp:expr>
                      </esql:param>
                   </esql:get-column>
)

 
Offer some direct paths to the esql code, like "get-metadata",
"get-column-type", "get-object", or even "get-resultset"
(done)

 
Make "get-xml" more powerful so that the db needs only to store
fragments of an xml document. Currently, only a root element without
any attributes is allowed here. Thus it is not possible e.g. to
specify a namespace for the fragment. 
(not done yet -- why doesn't it inherit the namespaces from the
original xsp? Is there a way to figure them out?)

 
BTW since it is possible to include other logicsheets, would it be
wise to put all utility tags (copy-all, get-nested-content,
get-parameter and the like) to a common logicsheet so that they could
easily be used by new logicsheets?


        Chris.

-- 
C h r i s t i a n       H a u l
[EMAIL PROTECTED]
    fingerprint: 99B0 1D9D 7919 644A 4837  7D73 FEF9 6856 335A 9E08
Index: src/org/apache/cocoon/components/language/markup/xsp/java/esql.xsl
===================================================================
RCS file: 
/home/cvs/xml-cocoon2/src/org/apache/cocoon/components/language/markup/xsp/java/esql.xsl,v
retrieving revision 1.11
diff -u -r1.11 esql.xsl
--- src/org/apache/cocoon/components/language/markup/xsp/java/esql.xsl  2001/07/10 
14:04:15     1.11
+++ src/org/apache/cocoon/components/language/markup/xsp/java/esql.xsl  2001/07/11 
+11:18:07
@@ -71,6 +71,8 @@
 <xsl:variable 
name="cocoon1-xsp-namespace-uri">http://www.apache.org/1999/XSP/Core</xsl:variable>
 <xsl:variable name="cocoon2-xsp-namespace-uri">http://apache.org/xsp</xsl:variable>
 
+<xsl:variable name="prefix">esql</xsl:variable>
+
 <xsl:variable name="environment">
   <xsl:choose>
     <xsl:when test="starts-with($XSP-ENVIRONMENT,$cocoon1-environment)">
@@ -159,6 +161,44 @@
   </xsl:choose>
 </xsl:template>
 
+
+  <xsl:template name="get-parameter">
+    <xsl:param name="name"/>
+    <xsl:param name="default"/>
+    <xsl:param name="required">false</xsl:param>
+
+    <xsl:variable name="qname">
+      <xsl:value-of select="concat($prefix, ':param')"/>
+    </xsl:variable>
+
+    <xsl:choose>
+      <xsl:when test="@*[name(.) = $name]">"<xsl:value-of select="@*[name(.) = 
+$name]"/>"</xsl:when>
+      <xsl:when test="(*[name(.) = $qname])[@name = $name]">
+        <xsl:call-template name="get-nested-content">
+          <xsl:with-param name="content"
+                          select="(*[name(.) = $qname])[@name = $name]"/>
+        </xsl:call-template>
+      </xsl:when>
+      <xsl:otherwise>
+        <xsl:choose>
+          <xsl:when test="string-length($default) = 0">
+            <xsl:choose>
+              <xsl:when test="$required = 'true'">
+                <xsl:call-template name="error">
+                  <xsl:with-param name="message">[Logicsheet processor]
+Parameter '<xsl:value-of select="$name"/>' missing in dynamic tag &lt;<xsl:value-of 
+select="name(.)"/>&gt;
+                  </xsl:with-param>
+                </xsl:call-template>
+              </xsl:when>
+              <xsl:otherwise>""</xsl:otherwise>
+            </xsl:choose>
+          </xsl:when>
+          <xsl:otherwise><xsl:copy-of select="$default"/></xsl:otherwise>
+        </xsl:choose>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+
 <xsl:template match="xsp:page">
   <xsp:page>
     <xsl:apply-templates select="@*"/>
@@ -177,6 +217,12 @@
       <xsp:include>java.io.PrintWriter</xsp:include>
       <xsp:include>java.io.BufferedInputStream</xsp:include>
       <xsp:include>java.io.InputStream</xsp:include>
+      <xsp:include>java.util.Set</xsp:include>
+      <xsp:include>java.util.List</xsp:include>
+      <xsp:include>java.util.Iterator</xsp:include>
+      <xsp:include>java.util.ListIterator</xsp:include>
+      <xsp:include>java.sql.Struct</xsp:include>
+      <xsp:include>java.sql.Types</xsp:include>
       <xsl:if test="$environment = 'cocoon2'">
           
<xsp:include>org.apache.cocoon.components.language.markup.xsp.XSPUtil</xsp:include>
       </xsl:if>
@@ -268,6 +314,44 @@
 
         return new String(buffer);
       }
+
+      <xsl:choose>
+        <xsl:when test="$environment = 'cocoon1'">
+        </xsl:when>
+        <xsl:when test="$environment = 'cocoon2'">
+            protected void _esql_printObject ( Object obj, AttributesImpl xspAttr) 
+throws SAXException
+            {
+               try {
+                  ListIterator j=((List)obj).listIterator();
+                  <xsp:element name="sql-list">
+                    <xsp:logic>
+                      while (j.hasNext()){
+                         <xsp:element name="sql-list-item">
+                           <xsp:attribute 
+name="pos"><xsp:expr>j.nextIndex()</xsp:expr></xsp:attribute>
+                           
+<xsp:logic>this._esql_printObject(j.next(),xspAttr);</xsp:logic>
+                         </xsp:element>
+                      };
+                    </xsp:logic>
+                  </xsp:element>
+               } catch (Exception e){
+                  try {
+                      Iterator j=((Set)obj).iterator();
+                      <xsp:element name="sql-set">
+                        <xsp:logic>
+                          while (j.hasNext()){
+                             <xsp:element name="sql-set-item">
+                                
+<xsp:logic>this._esql_printObject(j.next(),xspAttr);</xsp:logic>
+                             </xsp:element>
+                          };
+                        </xsp:logic>
+                      </xsp:element>
+                  } catch (Exception f) {
+                      <xsp:content><xsp:expr>obj</xsp:expr></xsp:content>;
+                  }
+              }
+           }
+        </xsl:when>
+      </xsl:choose>
     </xsp:logic>
     <xsl:apply-templates/>
   </xsp:page>
@@ -554,17 +638,23 @@
 <xsl:template match="esql:query//esql:parameter">"?"</xsl:template>
 
 <xsl:template match="esql:execute-query//esql:results">
-  <xsl:apply-templates/>
+  <xsp:content>
+    <xsl:apply-templates/>
+  </xsp:content>
 </xsl:template>
 
 <xsl:template match="esql:execute-query//esql:error-results">
-  <xsl:apply-templates/>
+  <xsp:content>
+    <xsl:apply-templates/>
+  </xsp:content>
 </xsl:template>
 
 <xsl:template match="esql:execute-query//esql:no-results">
   <xsp:logic>
     if (_esql_query.position == _esql_query.skip_rows) {
-      <xsl:apply-templates/>
+      <xsp:content>
+        <xsl:apply-templates/>
+      </xsp:content>
     }
   </xsp:logic>
 </xsl:template>
@@ -576,7 +666,9 @@
 <xsl:template match="esql:results//esql:row-results">
   <xsp:logic>
     while (_esql_query.resultset.next()) {
-      <xsl:apply-templates/>
+      <xsp:content>
+        <xsl:apply-templates/>
+      </xsp:content>
       if (_esql_connection.use_limit_clause == 0 &amp;&amp; _esql_query.max_rows != 
-1 &amp;&amp; _esql_query.position - _esql_query.skip_rows == _esql_query.max_rows-1) {
         _esql_query.position++;
         break;
@@ -584,7 +676,7 @@
       _esql_query.position++;
     }
     if (_esql_query.resultset.next()) {
-      <xsl:apply-templates select="following-sibling::esql:more-results" mode="more"/>
+        <xsl:apply-templates select="following-sibling::esql:more-results" 
+mode="more"/>
       _esql_query.position++;
     }
   </xsp:logic>
@@ -593,7 +685,9 @@
 <xsl:template match="esql:results//esql:more-results"/>
 
 <xsl:template match="esql:results//esql:more-results" mode="more">
-  <xsl:apply-templates/>
+  <xsp:content>
+    <xsl:apply-templates/>
+  </xsp:content>
 </xsl:template>
 
 <xspdoc:desc>results in a set of elements whose names are the names of the columns. 
the elements each have one text child, whose value is the value of the column 
interpreted as a string. No special formatting is allowed here. If you want to mess 
around with the names of the elements or the value of the text field, use the 
type-specific get methods and write out the result fragment yourself.</xspdoc:desc>
@@ -644,12 +738,35 @@
                 </xsl:otherwise>
               </xsl:choose>
             </xsp:param>
-            <xsp:expr>
-              <xsl:call-template name="get-string-encoded">
-                <xsl:with-param name="column-spec">_esql_i</xsl:with-param>
-                <xsl:with-param 
name="resultset">_esql_query.resultset</xsl:with-param>
-              </xsl:call-template>
-            </xsp:expr>
+            <xsp:logic>
+              switch(_esql_query.resultset.getMetaData().getColumnType(_esql_i)){
+                 case java.sql.Types.ARRAY:
+                 case java.sql.Types.STRUCT:
+                    <xsp:element name="sql-row">
+                      <xsp:logic>
+                        Object[] _esql_struct = ((Struct) 
+_esql_query.resultset.getObject(_esql_i)).getAttributes();
+                        for ( int _esql_k=0; _esql_k&lt;_esql_struct.length; 
+_esql_k++){
+                        <xsp:element 
+name="sql-row-item"><xsp:logic>this._esql_printObject(_esql_struct[_esql_k],xspAttr);</xsp:logic></xsp:element>
+                        }
+                      </xsp:logic>
+                    </xsp:element>
+                    break;
+                   
+                 case java.sql.Types.OTHER: // This is what Informix uses for Sets, 
+Bags, Lists
+                    this._esql_printObject(_esql_query.resultset.getObject(_esql_i), 
+xspAttr);
+                    break;
+                   
+                 default:
+                    // standard type
+                    <xsp:content>
+                    <xsp:expr>
+                      <xsl:call-template name="get-string-encoded">
+                        <xsl:with-param name="column-spec">_esql_i</xsl:with-param>
+                        <xsl:with-param 
+name="resultset">_esql_query.resultset</xsl:with-param>
+                      </xsl:call-template>
+                    </xsp:expr></xsp:content>
+              }
+            </xsp:logic>
           </xsp:element>
         }
         this.characters("\n");
@@ -738,6 +855,16 @@
   </xsl:choose>
 </xsl:template>
 
+<xspdoc:desc>returns the current result set</xspdoc:desc>
+<xsl:template match="esql:results//esql:get-resultset">
+  <xsp:expr><xsl:call-template name="get-resultset"/></xsp:expr>
+</xsl:template>
+
+<xspdoc:desc>returns the value of the given column as an object</xspdoc:desc>
+<xsl:template match="esql:row-results//esql:get-object">
+  <xsp:expr><xsl:call-template name="get-resultset"/>.getObject(<xsl:call-template 
+name="get-column"/>)</xsp:expr>
+</xsl:template>
+
 <xspdoc:desc>returns the value of the given column as an integer</xspdoc:desc>
 <xsl:template match="esql:row-results//esql:get-int">
   <xsp:expr><xsl:call-template name="get-resultset"/>.getInt(<xsl:call-template 
name="get-column"/>)</xsp:expr>
@@ -831,6 +958,11 @@
   <xsp:expr><xsl:call-template 
name="get-resultset"/>.getMetaData().getColumnCount()</xsp:expr>
 </xsl:template>
 
+<xspdoc:desc>returns the metadata of the resultset.</xspdoc:desc>
+<xsl:template match="esql:results//esql:get-metadata">
+  <xsp:expr><xsl:call-template name="get-resultset"/>.getMetaData()</xsp:expr>
+</xsl:template>
+
 <xspdoc:desc>returns the position of the current row in the result set</xspdoc:desc>
 <xsl:template 
match="esql:row-results//esql:get-row-position|esql:results//esql:get-row-position">
   <xsp:expr>_esql_query.position</xsp:expr>
@@ -838,17 +970,22 @@
 
 <xspdoc:desc>returns the name of the given column. the column mus tbe specified by 
number, not name.</xspdoc:desc>
 <xsl:template match="esql:row-results//esql:get-column-name">
-  <xsp:expr><xsl:call-template 
name="get-resultset"/>.getMetaData().getColumnName(<xsl:value-of 
select="@column"/>)</xsp:expr>
+  <xsp:expr><xsl:call-template 
+name="get-resultset"/>.getMetaData().getColumnName(<xsl:call-template 
+name="get-column"/>)</xsp:expr>
 </xsl:template>
 
 <xspdoc:desc>returns the label of the given column. the column mus tbe specified by 
number, not name.</xspdoc:desc>
 <xsl:template match="esql:row-results//esql:get-column-label">
-  <xsp:expr><xsl:call-template 
name="get-resultset"/>.getMetaData().getColumnLabel(<xsl:value-of 
select="@column"/>)</xsp:expr>
+  <xsp:expr><xsl:call-template 
+name="get-resultset"/>.getMetaData().getColumnLabel(<xsl:call-template 
+name="get-column"/>)</xsp:expr>
 </xsl:template>
 
 <xspdoc:desc>returns the name of the type of the given column. the column must be 
specified by number, not name.</xspdoc:desc>
 <xsl:template match="esql:row-results//esql:get-column-type-name">
-  <xsp:expr><xsl:call-template 
name="get-resultset"/>.getMetaData().getColumnTypeName(<xsl:value-of 
select="@column"/>)</xsp:expr>
+  <xsp:expr><xsl:call-template 
+name="get-resultset"/>.getMetaData().getColumnTypeName(<xsl:call-template 
+name="get-column"/>)</xsp:expr>
+</xsl:template>
+
+<xspdoc:desc>returns the type of the given column as int. the column must be 
+specified by number, not name.</xspdoc:desc>
+<xsl:template match="esql:row-results//esql:get-column-type">
+  <xsp:expr><xsl:call-template 
+name="get-resultset"/>.getMetaData().getColumnType(<xsl:call-template 
+name="get-column"/>)</xsp:expr>
 </xsl:template>
 
 <xspdoc:desc>allows null-column testing. Evaluates to a Java expression, which is 
true when the referred column contains a null-value for the current resultset 
row</xspdoc:desc>
@@ -890,24 +1027,29 @@
 
 <xspdoc:desc>used internally to determine which column is the given column. if a 
column attribute exists and itcvs server: Diffing 
src/org/apache/cocoon/components/language/programming
s 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.</xspdoc:desc>
 <xsl:template name="get-column">
+  <xsl:variable name="column">
+     <xsl:call-template name="get-parameter">
+       <xsl:with-param name="name">column</xsl:with-param>
+       <xsl:with-param name="required">true</xsl:with-param>
+     </xsl:call-template>
+  </xsl:variable>
   <xsl:choose>
-    <xsl:when test="@column">
+    <xsl:when test="starts-with($column,'&quot;')">
+      <xsl:variable name="raw-column">
+        <xsl:value-of select="substring($column,2,string-length($column)-2)"/>
+      </xsl:variable>
       <xsl:choose>
-        <xsl:when test="not(string(number(@column))='NaN')">
-          <xsl:value-of select="@column"/>
+        <xsl:when test="not(string(number($raw-column))='NaN')">
+          <xsl:value-of select="$raw-column"/>
         </xsl:when>
         <xsl:otherwise>
-          <xsl:text>"</xsl:text>
-          <xsl:value-of select="@column"/>
-          <xsl:text>"</xsl:text>
+          <xsl:value-of select="$column"/>
         </xsl:otherwise>
       </xsl:choose>
-    </xsl:when>
-    <xsl:when test="esql:column">
-      <xsl:call-template name="get-nested-string">
-        <xsl:with-param name="content" select="esql:column"/>
-      </xsl:call-template>
     </xsl:when>
+    <xsl:otherwise>
+      <xsl:copy-of select="$column"/>
+    </xsl:otherwise>
   </xsl:choose>
 </xsl:template>
 

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, email: [EMAIL PROTECTED]

Reply via email to