You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-commits@db.apache.org by bp...@apache.org on 2009/04/25 22:21:04 UTC

svn commit: r768597 [3/4] - in /db/derby/code/trunk/java: engine/org/apache/derby/ engine/org/apache/derby/catalog/ engine/org/apache/derby/iapi/sql/conn/ engine/org/apache/derby/iapi/sql/dictionary/ engine/org/apache/derby/iapi/sql/execute/ engine/org...

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/rts/RealSetOpResultSetStatistics.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/rts/RealSetOpResultSetStatistics.java?rev=768597&r1=768596&r2=768597&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/rts/RealSetOpResultSetStatistics.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/rts/RealSetOpResultSetStatistics.java Sat Apr 25 20:21:03 2009
@@ -22,6 +22,11 @@
 package org.apache.derby.impl.sql.execute.rts;
 
 import org.apache.derby.iapi.services.i18n.MessageService;
+import org.apache.derby.catalog.UUID;
+import org.apache.derby.impl.sql.catalog.XPLAINResultSetDescriptor;
+import org.apache.derby.impl.sql.catalog.XPLAINResultSetTimingsDescriptor;
+import org.apache.derby.impl.sql.execute.xplain.XPLAINUtil;
+import org.apache.derby.iapi.sql.execute.xplain.XPLAINVisitor;
 import org.apache.derby.iapi.reference.SQLState;
 
 import org.apache.derby.impl.sql.compile.IntersectOrExceptNode;
@@ -205,4 +210,67 @@
 		
         return MessageService.getTextMessage(nodeName);
     }
+    
+    // -----------------------------------------------------
+    // XPLAINable Implementation
+    // -----------------------------------------------------
+    
+      public void accept(XPLAINVisitor visitor) {
+          int noChildren = 0;
+          if(this.leftResultSetStatistics!=null) noChildren++;
+          if(this.rightResultSetStatistics!=null) noChildren++;
+          
+          //inform the visitor
+          visitor.setNumberOfChildren(noChildren);
+          
+          // pre-order, depth-first traversal
+          // me first
+          visitor.visit(this);
+          // then visit first my left child
+          if(leftResultSetStatistics!=null){
+              leftResultSetStatistics.accept(visitor);
+          }
+          // and then my right child
+          if(rightResultSetStatistics!=null){
+              rightResultSetStatistics.accept(visitor);
+          }
+      }
+    public String getRSXplainType() { return XPLAINUtil.OP_SET; }
+    public String getRSXplainDetails()
+    {
+        String op_details = "("+this.resultSetNumber + ")";
+        // the details are weird, because the semantics are exchanged
+        op_details += (this.opType == IntersectOrExceptNode.INTERSECT_OP)?
+                      ", "+XPLAINUtil.OP_SET_EXCEPT:
+                      ", "+XPLAINUtil.OP_SET_INTERSECT;
+        return op_details;
+    }
+    public Object getResultSetDescriptor(Object rsID, Object parentID,
+            Object scanID, Object sortID, Object stmtID, Object timingID)
+    {
+        return new XPLAINResultSetDescriptor(
+           (UUID)rsID,
+           getRSXplainType(),
+           getRSXplainDetails(),
+           new Integer(this.numOpens),
+           null,                              // the number of index updates 
+           null,                           // lock mode
+           null,                           // lock granularity
+           (UUID)parentID,
+           new Double(this.optimizerEstimatedRowCount),
+           new Double(this.optimizerEstimatedCost),
+           null,                              // the affected rows
+           null,                              // the deferred rows
+           null,                              // the input rows
+           new Integer(this.rowsSeenLeft),        // the seen rows left
+           new Integer(this.rowsSeenRight),       // the seen rows right
+           new Integer(this.rowsFiltered),        // the filtered rows
+           new Integer(this.rowsReturned),        // the returned rows
+           null,                              // the empty right rows
+           null,                           // index key optimization
+           (UUID)scanID,
+           (UUID)sortID,
+           (UUID)stmtID,
+           (UUID)timingID);
+    }
 } 

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/rts/RealSortStatistics.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/rts/RealSortStatistics.java?rev=768597&r1=768596&r2=768597&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/rts/RealSortStatistics.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/rts/RealSortStatistics.java Sat Apr 25 20:21:03 2009
@@ -21,6 +21,12 @@
 
 package org.apache.derby.impl.sql.execute.rts;
 
+import org.apache.derby.catalog.UUID;
+import org.apache.derby.impl.sql.catalog.XPLAINResultSetDescriptor;
+import org.apache.derby.impl.sql.catalog.XPLAINResultSetTimingsDescriptor;
+import org.apache.derby.impl.sql.catalog.XPLAINSortPropsDescriptor;
+import org.apache.derby.impl.sql.execute.xplain.XPLAINUtil;
+
 import org.apache.derby.iapi.services.io.StoredFormatIds;
 
 import org.apache.derby.iapi.services.i18n.MessageService;
@@ -28,6 +34,7 @@
 
 import org.apache.derby.iapi.services.io.FormatableHashtable;
 import org.apache.derby.iapi.services.io.FormatableProperties;
+import org.apache.derby.iapi.sql.execute.xplain.XPLAINVisitor;
 import org.apache.derby.iapi.util.PropertyUtil;
 
 import java.io.ObjectOutput;
@@ -180,4 +187,77 @@
   public String getNodeName(){
     return MessageService.getTextMessage(SQLState.RTS_SORT);
   }
+  
+  // -----------------------------------------------------
+  // XPLAINable Implementation
+  // -----------------------------------------------------
+  
+    public void accept(XPLAINVisitor visitor) {
+        int noChildren = 0;
+        if(this.childResultSetStatistics!=null) noChildren++;
+        
+        //inform the visitor
+        visitor.setNumberOfChildren(noChildren);
+        
+        // pre-order, depth-first traversal
+        // me first
+        visitor.visit(this);
+        // then my child
+        if(childResultSetStatistics!=null){
+            childResultSetStatistics.accept(visitor);
+        }
+    }
+  
+    public String getRSXplainType() { return XPLAINUtil.OP_SORT; }
+    public Object getResultSetDescriptor(Object rsID, Object parentID,
+            Object scanID, Object sortID, Object stmtID, Object timingID)
+    {
+        return new XPLAINResultSetDescriptor(
+           (UUID)rsID,
+           getRSXplainType(),
+           getRSXplainDetails(),
+           new Integer(this.numOpens),
+           null,                              // the number of index updates 
+           null,                           // lock mode
+           null,                           // lock granularity
+           (UUID)parentID,
+           new Double(this.optimizerEstimatedRowCount),
+           new Double(this.optimizerEstimatedCost),
+           null,                              // the affected rows
+           null,                              // the deferred rows
+           new Integer(this.rowsInput),
+           new Integer(this.rowsSeen),
+           null,                              // the seen rows right
+           new Integer(this.rowsFiltered),
+           new Integer(this.rowsReturned),
+           null,                              // the empty right rows
+           null,                           // index key optimization
+           (UUID)scanID,
+           (UUID)sortID,
+           (UUID)stmtID,
+           (UUID)timingID);
+    }
+    public Object getSortPropsDescriptor(Object sortPropsID)
+    {
+        FormatableProperties props = this.sortProperties;
+        
+        // create new scan info descriptor with some basic information
+        XPLAINSortPropsDescriptor sortRSDescriptor =            
+          new XPLAINSortPropsDescriptor(
+              (UUID)sortPropsID,      // the sort props UUID
+              null,             // the sort type, either (C)onstraint, (I)ndex or (T)able
+              null,                // the number of input rows
+              null,                // the number of output rows
+              null,                // the number of merge runs
+              null,             // merge run details
+              XPLAINUtil.getYesNoCharFromBoolean(
+                    this.eliminateDuplicates),// eliminate duplicates
+              XPLAINUtil.getYesNoCharFromBoolean(
+                    this.inSortedOrder),      // in sorted order
+              null              // distinct_aggregate
+            );
+        
+        // fill additional information from scan properties
+        return XPLAINUtil.extractSortProps(sortRSDescriptor,props);
+    }
 }

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/rts/RealTableScanStatistics.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/rts/RealTableScanStatistics.java?rev=768597&r1=768596&r2=768597&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/rts/RealTableScanStatistics.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/rts/RealTableScanStatistics.java Sat Apr 25 20:21:03 2009
@@ -29,6 +29,12 @@
 
 import org.apache.derby.iapi.services.io.FormatableHashtable;
 import org.apache.derby.iapi.services.io.FormatableProperties;
+import org.apache.derby.catalog.UUID;
+import org.apache.derby.impl.sql.catalog.XPLAINResultSetDescriptor;
+import org.apache.derby.impl.sql.catalog.XPLAINResultSetTimingsDescriptor;
+import org.apache.derby.impl.sql.catalog.XPLAINScanPropsDescriptor;
+import org.apache.derby.impl.sql.execute.xplain.XPLAINUtil;
+import org.apache.derby.iapi.sql.execute.xplain.XPLAINVisitor;
 
 import java.io.ObjectOutput;
 import java.io.ObjectInput;
@@ -272,4 +278,116 @@
 												tableName,
 												indexName);
   }
+  
+  // -----------------------------------------------------
+  // XPLAINable Implementation
+  // -----------------------------------------------------
+  
+    public void accept(XPLAINVisitor visitor) {
+        // I have no children
+        visitor.setNumberOfChildren(0);
+        // pre-order, depth-first traversal
+        // me first
+        visitor.visit(this);
+        // I´m a leaf node, I have no children ...
+    }
+
+    public String getRSXplainType()
+    {
+        if (this.indexName!=null)
+            return this.isConstraint ? XPLAINUtil.OP_CONSTRAINTSCAN :
+                                       XPLAINUtil.OP_INDEXSCAN;
+        else
+            return XPLAINUtil.OP_TABLESCAN;
+    }
+    public String getRSXplainDetails()
+    {
+        if (this.indexName!=null)
+            return (this.isConstraint ? "C: " : "I: ") + this.indexName;
+        else
+            return "T: " + this.tableName;
+    }
+    public Object getScanPropsDescriptor(Object scanPropsID)
+    {
+        String scanObjectType, scanObjectName;
+
+        if (this.indexName!=null)
+        {
+            if (this.isConstraint)
+            {
+                scanObjectType = "C";  // constraint
+                scanObjectName = this.indexName;
+            }
+            else
+            {
+                scanObjectType = "I";  // index
+                scanObjectName = this.indexName;
+            }
+        }
+        else
+        {
+            scanObjectType = "T";      // table
+            scanObjectName = this.tableName;
+        }
+        
+        String isoLevel = XPLAINUtil.getIsolationLevelCode(this.isolationLevel);
+        
+        XPLAINScanPropsDescriptor scanRSDescriptor =            
+              new XPLAINScanPropsDescriptor(
+              (UUID)scanPropsID,
+              scanObjectName,
+              scanObjectType,
+              null,             // the scan type: heap, btree, sort
+              isoLevel,         // the isolation level
+              null,             // the number of visited pages
+              null,             // the number of visited rows
+              null,             // the number of qualified rows
+              null,             // the number of visited deleted rows
+              null,             // the number of fetched columns
+              null,             // the bitset of fetched columns
+              null,             // the btree height
+              new Integer(this.fetchSize),
+              this.startPosition,
+              this.stopPosition,
+              this.qualifiers,
+              null,             // the next qualifiers
+              null,             // the hash key column numbers
+              null                 // the hash table size
+            );
+        
+        FormatableProperties props = this.scanProperties;
+
+        return XPLAINUtil.extractScanProps(scanRSDescriptor,props);
+    }
+    public Object getResultSetDescriptor(Object rsID, Object parentID,
+            Object scanID, Object sortID, Object stmtID, Object timingID)
+    {
+        String lockMode = XPLAINUtil.getLockModeCode(this.lockString);
+        String lockGran = XPLAINUtil.getLockGranularityCode(this.lockString);
+        
+        return new XPLAINResultSetDescriptor(
+           (UUID)rsID,
+           getRSXplainType(),
+           getRSXplainDetails(),
+           new Integer(this.numOpens),
+           null,                           // the number of index updates 
+           lockMode,                       // lock mode
+           lockGran,                       // lock granularity
+           (UUID)parentID,
+           new Double(this.optimizerEstimatedRowCount),
+           new Double(this.optimizerEstimatedCost),
+           null,                              // the affected rows
+           null,                              // the deferred rows
+           null,                              // the input rows
+           new Integer(this.rowsSeen),            // the seen rows
+           null,                              // the seen rows right
+           new Integer(this.rowsFiltered),        // the filtered rows
+           new Integer(this.rowsSeen-this.rowsFiltered),// the returned rows
+           null,                              // the empty right rows
+           null,                           // index key optimization
+           (UUID)scanID,
+           (UUID)sortID,
+           (UUID)stmtID,                       // the stmt UUID
+           (UUID)timingID);
+    }
 }

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/rts/RealUnionResultSetStatistics.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/rts/RealUnionResultSetStatistics.java?rev=768597&r1=768596&r2=768597&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/rts/RealUnionResultSetStatistics.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/rts/RealUnionResultSetStatistics.java Sat Apr 25 20:21:03 2009
@@ -31,6 +31,11 @@
 import java.io.ObjectOutput;
 import java.io.ObjectInput;
 import java.io.IOException;
+import org.apache.derby.catalog.UUID;
+import org.apache.derby.impl.sql.catalog.XPLAINResultSetDescriptor;
+import org.apache.derby.impl.sql.catalog.XPLAINResultSetTimingsDescriptor;
+import org.apache.derby.impl.sql.execute.xplain.XPLAINUtil;
+import org.apache.derby.iapi.sql.execute.xplain.XPLAINVisitor;
 
 /**
   ResultSetStatistics implemenation for UnionResultSet.
@@ -167,4 +172,62 @@
   public String getNodeName(){
     return MessageService.getTextMessage(SQLState.RTS_UNION);
   }
+  
+  // -----------------------------------------------------
+  // XPLAINable Implementation
+  // -----------------------------------------------------
+  
+    public void accept(XPLAINVisitor visitor) {
+        int noChildren = 0;
+        if(this.leftResultSetStatistics!=null) noChildren++;
+        if(this.rightResultSetStatistics!=null) noChildren++;
+        
+        //inform the visitor
+        visitor.setNumberOfChildren(noChildren);
+        
+        // pre-order, depth-first traversal
+        // me first
+        visitor.visit(this);
+        // then visit first my left child
+        if(leftResultSetStatistics!=null){
+            leftResultSetStatistics.accept(visitor);
+        }
+        // and then my right child
+        if(rightResultSetStatistics!=null){
+            rightResultSetStatistics.accept(visitor);
+        }
+    }  
+    public String getRSXplainType() { return XPLAINUtil.OP_UNION; }
+    public String getRSXplainDetails()
+    {
+        return "("+this.resultSetNumber + ")";
+    }
+    public Object getResultSetDescriptor(Object rsID, Object parentID,
+            Object scanID, Object sortID, Object stmtID, Object timingID)
+    {
+        return new XPLAINResultSetDescriptor(
+           (UUID)rsID,
+           getRSXplainType(),
+           getRSXplainDetails(),
+           new Integer(this.numOpens),
+           null,                           // index updates
+           null,                           // lock mode
+           null,                           // lock granularity
+           (UUID)parentID,
+           new Double(this.optimizerEstimatedRowCount),
+           new Double(this.optimizerEstimatedCost),
+           null,                              // affected rows
+           null,                              // deferred rows
+           null,                              // the input rows
+           new Integer(this.rowsSeenLeft),
+           new Integer(this.rowsSeenRight),
+           new Integer(this.rowsFiltered),
+           new Integer(this.rowsReturned),
+           null,                           // the empty right rows
+           null,                           // index key optimization
+           (UUID)scanID,
+           (UUID)sortID,
+           (UUID)stmtID,
+           (UUID)timingID);
+    }
 }

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/rts/RealUpdateResultSetStatistics.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/rts/RealUpdateResultSetStatistics.java?rev=768597&r1=768596&r2=768597&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/rts/RealUpdateResultSetStatistics.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/rts/RealUpdateResultSetStatistics.java Sat Apr 25 20:21:03 2009
@@ -27,6 +27,11 @@
 import org.apache.derby.iapi.reference.SQLState;
 
 import org.apache.derby.iapi.services.io.FormatableHashtable;
+import org.apache.derby.catalog.UUID;
+import org.apache.derby.impl.sql.catalog.XPLAINResultSetDescriptor;
+import org.apache.derby.impl.sql.catalog.XPLAINResultSetTimingsDescriptor;
+import org.apache.derby.impl.sql.execute.xplain.XPLAINUtil;
+import org.apache.derby.iapi.sql.execute.xplain.XPLAINVisitor;
 
 import java.io.ObjectOutput;
 import java.io.ObjectInput;
@@ -142,4 +147,53 @@
   public String getNodeName(){
     return MessageService.getTextMessage(SQLState.RTS_UPDATE);
   }
+  
+  // -----------------------------------------------------
+  // XPLAINable Implementation
+  // -----------------------------------------------------
+  
+    public void accept(XPLAINVisitor visitor) {
+        int noChildren = 0;
+        if(this.sourceResultSetStatistics!=null) noChildren++;
+        
+        //inform the visitor
+        visitor.setNumberOfChildren(noChildren);
+
+        // pre-order, depth-first traversal
+        // me first
+        visitor.visit(this);
+        // then my child
+        if(sourceResultSetStatistics!=null){
+            sourceResultSetStatistics.accept(visitor);
+		}
+    }  
+    public String getRSXplainType() { return XPLAINUtil.OP_UPDATE; }
+    public Object getResultSetDescriptor(Object rsID, Object parentID,
+            Object scanID, Object sortID, Object stmtID, Object timingID)
+    {
+        return new XPLAINResultSetDescriptor(
+           (UUID)rsID,
+           getRSXplainType(),
+           getRSXplainDetails(),
+           null,                              // the number of opens
+           new Integer(this.indexesUpdated),
+           null,                           // lock mode
+           this.tableLock?"T":"R",
+           (UUID)parentID,
+           null,                             // estimated row count
+           null,                             // estimated cost
+           new Integer(this.rowCount),
+           XPLAINUtil.getYesNoCharFromBoolean(this.deferred),
+           null,                              // the input rows
+           null,                              // the seen rows left
+           null,                              // the seen rows right
+           null,                              // the filtered rows
+           null,                              // the returned rows
+           null,                              // the empty right rows
+           null,                           // index key optimization
+           (UUID)scanID,
+           (UUID)sortID,
+           (UUID)stmtID,
+           (UUID)timingID);
+    }
 }

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/rts/RealVTIStatistics.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/rts/RealVTIStatistics.java?rev=768597&r1=768596&r2=768597&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/rts/RealVTIStatistics.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/rts/RealVTIStatistics.java Sat Apr 25 20:21:03 2009
@@ -27,6 +27,8 @@
 import org.apache.derby.iapi.reference.SQLState;
 
 import org.apache.derby.iapi.services.io.FormatableHashtable;
+import org.apache.derby.impl.sql.execute.xplain.XPLAINUtil;
+import org.apache.derby.iapi.sql.execute.xplain.XPLAINVisitor;
 
 import java.io.ObjectOutput;
 import java.io.ObjectInput;
@@ -149,4 +151,25 @@
   public String getNodeName(){
     return MessageService.getTextMessage(SQLState.RTS_VTI);
   }
+  
+  // -----------------------------------------------------
+  // XPLAINable Implementation
+  // -----------------------------------------------------
+  
+    public void accept(XPLAINVisitor visitor) {
+        
+        //inform the visitor
+        visitor.setNumberOfChildren(0);
+        
+        // pre-order, depth-first traversal
+        // me first
+        visitor.visit(this);
+        // I´m a leaf node, I have no children ...
+        
+	}  
+    public String getRSXplainType() { return XPLAINUtil.OP_VTI_RS; }
+    public String getRSXplainDetails()
+    {
+        return this.javaClassName + ", (" + this.resultSetNumber+")";
+    }
 }

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/rts/RealWindowResultSetStatistics.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/rts/RealWindowResultSetStatistics.java?rev=768597&r1=768596&r2=768597&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/rts/RealWindowResultSetStatistics.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/rts/RealWindowResultSetStatistics.java Sat Apr 25 20:21:03 2009
@@ -22,6 +22,8 @@
 package org.apache.derby.impl.sql.execute.rts;
 
 import org.apache.derby.iapi.services.i18n.MessageService;
+import org.apache.derby.impl.sql.execute.xplain.XPLAINUtil;
+import org.apache.derby.iapi.sql.execute.xplain.XPLAINVisitor;
 import org.apache.derby.iapi.reference.SQLState;
 
 /**
@@ -153,4 +155,21 @@
 	{
 		return childResultSetStatistics;
 	}
+
+  // -----------------------------------------------------
+  // XPLAINable Implementation
+  // -----------------------------------------------------
+  
+    public void accept(XPLAINVisitor visitor) {
+        // I have only one child
+        visitor.setNumberOfChildren(1);
+        
+        // pre-order, depth-first traversal
+        // me first
+        visitor.visit(this);
+        // then my child
+        childResultSetStatistics.accept(visitor);
+	}
+
+    public String getRSXplainType() { return XPLAINUtil.OP_WINDOW; }
 }

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/rts/ResultSetStatistics.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/rts/ResultSetStatistics.java?rev=768597&r1=768596&r2=768597&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/rts/ResultSetStatistics.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/rts/ResultSetStatistics.java Sat Apr 25 20:21:03 2009
@@ -21,6 +21,8 @@
 
 package org.apache.derby.impl.sql.execute.rts;
 
+import org.apache.derby.iapi.sql.execute.xplain.XPLAINable;
+
 /**
  * The ResultSetStatistics interface is used to provide run time
  * statistics information on a specific ResultSet.
@@ -29,7 +31,7 @@
  * this interface can be easily saved to the database.
  *
  */
-public interface ResultSetStatistics 
+public interface ResultSetStatistics extends XPLAINable
 {
 	/**
 	 * Return the statement execution plan as a String.

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/rts/RunTimeStatisticsImpl.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/rts/RunTimeStatisticsImpl.java?rev=768597&r1=768596&r2=768597&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/rts/RunTimeStatisticsImpl.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/rts/RunTimeStatisticsImpl.java Sat Apr 25 20:21:03 2009
@@ -30,6 +30,8 @@
 import org.apache.derby.iapi.services.io.FormatableHashtable;
 
 import org.apache.derby.iapi.sql.execute.RunTimeStatistics;
+import org.apache.derby.iapi.sql.execute.xplain.XPLAINVisitor;
+
 import java.util.Vector;
 
 import java.io.ObjectOutput;
@@ -379,5 +381,15 @@
     children.addElement(topResultSetStatistics);
     return children;
   }
+  
+  /**
+   * initiate a visit of an XPLAINVisitor from the top of the RS tree
+   */
+  public void acceptFromTopResultSet(XPLAINVisitor v)
+  {
+      if (topResultSetStatistics != null)
+          topResultSetStatistics.accept(v);
+  }
+  
 
 }

Added: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/xplain/XPLAINDefaultVisitor.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/xplain/XPLAINDefaultVisitor.java?rev=768597&view=auto
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/xplain/XPLAINDefaultVisitor.java (added)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/xplain/XPLAINDefaultVisitor.java Sat Apr 25 20:21:03 2009
@@ -0,0 +1,62 @@
+package org.apache.derby.impl.sql.execute.xplain;
+
+import java.sql.SQLException;
+
+import org.apache.derby.iapi.services.monitor.Monitor;
+import org.apache.derby.iapi.services.stream.HeaderPrintWriter;
+import org.apache.derby.iapi.sql.Activation;
+import org.apache.derby.iapi.sql.conn.ConnectionUtil;
+import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
+import org.apache.derby.iapi.sql.execute.RunTimeStatistics;
+import org.apache.derby.iapi.sql.execute.xplain.XPLAINVisitor;
+import org.apache.derby.impl.sql.execute.rts.ResultSetStatistics;
+/**
+ * This is the Default Visitor which produces explain information like the 
+ * old getRuntimeStatistics() approach. <br/>
+ * It exists to support backward-compatibility.
+ * The only thing this visitor does, is to log the output of the statistics to the 
+ * default log stream. (the file derby.log)
+ *
+ */
+public class XPLAINDefaultVisitor implements XPLAINVisitor {
+
+    public XPLAINDefaultVisitor(){
+        // System.out.println("Default Style XPLAIN Visitor created");
+    }
+
+    public void visit(ResultSetStatistics statistics) {
+        // default do nothing, because no traversal is done
+    }
+
+    public void reset() {
+        // TODO Auto-generated method stub
+        
+    }
+
+    public void doXPLAIN(RunTimeStatistics rss, Activation activation) {
+        LanguageConnectionContext lcc;
+        try {
+            lcc = ConnectionUtil.getCurrentLCC();
+            HeaderPrintWriter istream = lcc.getLogQueryPlan() ? Monitor.getStream() : null;
+            if (istream != null){
+                istream.printlnWithHeader(LanguageConnectionContext.xidStr + 
+                      lcc.getTransactionExecute().getTransactionIdString() +
+                      "), " +
+                      LanguageConnectionContext.lccStr +
+                      lcc.getInstanceNumber() +
+                      "), " +
+                      rss.getStatementText() + " ******* " +
+                      rss.getStatementExecutionPlanText());
+            }
+        } catch (SQLException e) {
+            e.printStackTrace();
+        }
+        
+    }
+
+    public void setNumberOfChildren(int noChildren) {
+        // do nothing
+        
+    }
+
+}

Propchange: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/xplain/XPLAINDefaultVisitor.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/xplain/XPLAINFactory.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/xplain/XPLAINFactory.java?rev=768597&view=auto
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/xplain/XPLAINFactory.java (added)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/xplain/XPLAINFactory.java Sat Apr 25 20:21:03 2009
@@ -0,0 +1,65 @@
+package org.apache.derby.impl.sql.execute.xplain;
+
+import java.sql.SQLException;
+
+import org.apache.derby.iapi.error.StandardException;
+import org.apache.derby.iapi.sql.conn.ConnectionUtil;
+import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
+import org.apache.derby.iapi.sql.execute.xplain.XPLAINFactoryIF;
+import org.apache.derby.iapi.sql.execute.xplain.XPLAINVisitor;
+import org.apache.derby.iapi.sql.dictionary.SchemaDescriptor;
+
+/**
+ * This is the module implementation of the XPLAINFactoryIF. It gets lazy-loaded
+ * when needed. The factory method determines which visitor to use. 
+ * The visitor is cached in this factory for later reuse. 
+ *
+ */
+public class XPLAINFactory implements XPLAINFactoryIF {
+    
+    /** the last instance of a visitor is cached */
+    private XPLAINVisitor currentVisitor = new XPLAINDefaultVisitor();
+    
+    /** the current cached schema */ 
+    private String       currentSchema = null;
+    
+    public XPLAINFactory(){
+    }
+    
+    /**
+     * the factory method, which gets called to determine 
+     * and return an appropriate XPLAINVisitor instance
+     */
+    public XPLAINVisitor getXPLAINVisitor()
+        throws StandardException
+    {
+        try
+        {
+            LanguageConnectionContext lcc = ConnectionUtil.getCurrentLCC();
+            String schema = lcc.getXplainSchema();
+            if (schema != currentSchema)
+            {
+                currentSchema = schema;
+                if (currentSchema == null)
+                    currentVisitor = new XPLAINDefaultVisitor();
+                else
+                    currentVisitor = new XPLAINSystemTableVisitor();
+            }
+        }
+        catch (SQLException e)
+        {
+            throw StandardException.plainWrapException(e);
+        }
+        return currentVisitor;
+    }
+
+    /**
+     * uncache the visitor and reset the factory state
+     */
+    public void freeResources() {
+        // let the garbage collector destroy the visitor and schema
+        currentVisitor = null;
+        currentSchema = null;
+    }
+
+}

Propchange: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/xplain/XPLAINFactory.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/xplain/XPLAINSystemTableVisitor.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/xplain/XPLAINSystemTableVisitor.java?rev=768597&view=auto
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/xplain/XPLAINSystemTableVisitor.java (added)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/xplain/XPLAINSystemTableVisitor.java Sat Apr 25 20:21:03 2009
@@ -0,0 +1,451 @@
+package org.apache.derby.impl.sql.execute.xplain;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.sql.Timestamp;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Properties;
+import java.util.Stack;
+
+import org.apache.derby.catalog.UUID;
+import org.apache.derby.jdbc.InternalDriver;
+import org.apache.derby.impl.jdbc.Util;
+import org.apache.derby.iapi.jdbc.ConnectionContext;
+import org.apache.derby.iapi.error.StandardException;
+import org.apache.derby.iapi.services.info.JVMInfo;
+import org.apache.derby.iapi.services.io.FormatableProperties;
+import org.apache.derby.iapi.sql.Activation;
+import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
+import org.apache.derby.iapi.sql.dictionary.DataDescriptorGenerator;
+import org.apache.derby.iapi.sql.dictionary.DataDictionary;
+import org.apache.derby.iapi.sql.dictionary.SchemaDescriptor;
+import org.apache.derby.iapi.sql.dictionary.TupleDescriptor;
+import org.apache.derby.impl.sql.catalog.XPLAINResultSetDescriptor;
+import org.apache.derby.impl.sql.catalog.XPLAINResultSetTimingsDescriptor;
+import org.apache.derby.impl.sql.catalog.XPLAINScanPropsDescriptor;
+import org.apache.derby.impl.sql.catalog.XPLAINSortPropsDescriptor;
+import org.apache.derby.impl.sql.catalog.XPLAINStatementDescriptor;
+import org.apache.derby.impl.sql.catalog.XPLAINStatementTimingsDescriptor;
+import org.apache.derby.iapi.sql.execute.RunTimeStatistics;
+import org.apache.derby.iapi.sql.execute.xplain.XPLAINVisitor;
+import org.apache.derby.iapi.store.access.TransactionController;
+import org.apache.derby.impl.sql.compile.IntersectOrExceptNode;
+import org.apache.derby.impl.sql.execute.rts.RealAnyResultSetStatistics;
+import org.apache.derby.impl.sql.execute.rts.RealDeleteCascadeResultSetStatistics;
+import org.apache.derby.impl.sql.execute.rts.RealDeleteResultSetStatistics;
+import org.apache.derby.impl.sql.execute.rts.RealDeleteVTIResultSetStatistics;
+import org.apache.derby.impl.sql.execute.rts.RealDistinctScalarAggregateStatistics;
+import org.apache.derby.impl.sql.execute.rts.RealDistinctScanStatistics;
+import org.apache.derby.impl.sql.execute.rts.RealGroupedAggregateStatistics;
+import org.apache.derby.impl.sql.execute.rts.RealHashJoinStatistics;
+import org.apache.derby.impl.sql.execute.rts.RealHashLeftOuterJoinStatistics;
+import org.apache.derby.impl.sql.execute.rts.RealHashScanStatistics;
+import org.apache.derby.impl.sql.execute.rts.RealHashTableStatistics;
+import org.apache.derby.impl.sql.execute.rts.RealIndexRowToBaseRowStatistics;
+import org.apache.derby.impl.sql.execute.rts.RealInsertResultSetStatistics;
+import org.apache.derby.impl.sql.execute.rts.RealInsertVTIResultSetStatistics;
+import org.apache.derby.impl.sql.execute.rts.RealLastIndexKeyScanStatistics;
+import org.apache.derby.impl.sql.execute.rts.RealMaterializedResultSetStatistics;
+import org.apache.derby.impl.sql.execute.rts.RealNestedLoopJoinStatistics;
+import org.apache.derby.impl.sql.execute.rts.RealNestedLoopLeftOuterJoinStatistics;
+import org.apache.derby.impl.sql.execute.rts.RealNormalizeResultSetStatistics;
+import org.apache.derby.impl.sql.execute.rts.RealOnceResultSetStatistics;
+import org.apache.derby.impl.sql.execute.rts.RealProjectRestrictStatistics;
+import org.apache.derby.impl.sql.execute.rts.RealRowResultSetStatistics;
+import org.apache.derby.impl.sql.execute.rts.RealScalarAggregateStatistics;
+import org.apache.derby.impl.sql.execute.rts.RealScrollInsensitiveResultSetStatistics;
+import org.apache.derby.impl.sql.execute.rts.RealSetOpResultSetStatistics;
+import org.apache.derby.impl.sql.execute.rts.RealSortStatistics;
+import org.apache.derby.impl.sql.execute.rts.RealTableScanStatistics;
+import org.apache.derby.impl.sql.execute.rts.RealUnionResultSetStatistics;
+import org.apache.derby.impl.sql.execute.rts.RealUpdateResultSetStatistics;
+import org.apache.derby.impl.sql.execute.rts.RealVTIStatistics;
+import org.apache.derby.impl.sql.execute.rts.ResultSetStatistics;
+
+/**
+ * This is the Visitor, which explains the information and stores the statistics in 
+ * the system catalogs. It traverses the result set statistics tree and extracts the
+ * information.  
+ *
+ */
+public class XPLAINSystemTableVisitor implements XPLAINVisitor {
+    
+    private boolean no_call_stmts = true;
+    
+    
+    // ---------------------------------------------------------
+    // member variables
+    // ---------------------------------------------------------
+    
+    // the needed system objects for writing to the dictionary
+    private LanguageConnectionContext lcc;
+    private DataDictionary dd;
+    private TransactionController tc;
+    private DataDescriptorGenerator ddg;
+    
+    // the stmt activation object
+    private Activation activation;
+
+    // a flag which is used to reflect if the statistics timings is on
+    private boolean considerTimingInformation = false;
+    
+    // the different tuple descriptors describing the query characteristics
+    // regarding the stmt
+    private XPLAINStatementDescriptor stmt;
+    private XPLAINStatementTimingsDescriptor stmtTimings = null;
+    private UUID stmtUUID; // the UUID to save for the resultsets
+    
+    // now the lists of descriptors regarding the resultsets
+    private List rsets; // for the resultset descriptors
+    private List rsetsTimings; // for the resultset timings descriptors
+    private List sortrsets; // for the sort props descriptors
+    private List scanrsets; // fot the scan props descriptors
+    
+    // the number of children of the current explained node
+    private int noChildren;
+    
+    // this stack keeps track of the result set UUIDs, which get popped by the
+    // children of the current explained node
+    private Stack UUIDStack;
+    
+    // ---------------------------------------------------------
+    // Constructor
+    // ---------------------------------------------------------
+    
+    public XPLAINSystemTableVisitor(){
+        // System.out.println("System Table Visitor created...");
+        // initialize lists
+        rsets        = new ArrayList();
+        rsetsTimings = new ArrayList();
+        sortrsets    = new ArrayList();
+        scanrsets    = new ArrayList();
+        
+        // init UUIDStack
+        UUIDStack    = new Stack();
+        
+    }
+
+    
+    /** helper method, which pushes the UUID,
+     *  "number of Children" times onto the UUIDStack.
+     * @param uuid the UUID to push
+     */
+    private void pushUUIDnoChildren(UUID uuid){
+        for (int i=0;i<noChildren;i++){
+            UUIDStack.push(uuid);
+        }
+    }
+    
+    // ---------------------------------------------------------
+    // XPLAINVisitor Implementation
+    // ---------------------------------------------------------
+    
+    /**
+     * this method only stores the current number of children of the current explained node.
+     * The child nodes then can re-use this information.
+     */
+    public void setNumberOfChildren(int noChildren) {
+        this.noChildren = noChildren;
+    }
+    
+    /** 
+      * Visit this node, calling back to it to get details.
+      *
+      * This method visits the RS Statisitcs node, calling back to the
+      * node to get detailed descriptor information about it.
+      */
+    public void visit(ResultSetStatistics statistics)
+    {
+        UUID timingID = null;
+        
+        if(considerTimingInformation){
+            timingID = dd.getUUIDFactory().createUUID();
+            rsetsTimings.add( 
+                    statistics.getResultSetTimingsDescriptor(timingID));
+        }
+        
+        UUID sortID = dd.getUUIDFactory().createUUID();
+        Object sortRSDescriptor = statistics.getSortPropsDescriptor(sortID);
+        if (sortRSDescriptor != null)
+            sortrsets.add(sortRSDescriptor);
+        else
+            sortID = null;
+        
+        UUID scanID = dd.getUUIDFactory().createUUID();
+        Object scanRSDescriptor = statistics.getScanPropsDescriptor(scanID);
+        if (scanRSDescriptor != null)
+            scanrsets.add(scanRSDescriptor);
+        else
+            scanID = null;
+
+        UUID rsID = dd.getUUIDFactory().createUUID();
+        rsets.add(statistics.getResultSetDescriptor(rsID,
+           UUIDStack.empty()?  null: (UUID)UUIDStack.pop(),
+           scanID, sortID, stmtUUID, timingID));
+        
+        pushUUIDnoChildren(rsID);
+    }
+    
+    /**
+     * This method resets the visitor. Gets called right before explanation
+     * to make sure all needed objects exist and are up to date and the lists are cleared
+     */
+    public void reset() {
+        lcc = activation.getLanguageConnectionContext();
+        dd  = lcc.getDataDictionary();
+        tc  = lcc.getTransactionExecute();
+        ddg = dd.getDataDescriptorGenerator(); 
+    }
+    
+    /** the interface method, which gets called by the Top-ResultSet, which starts
+     *  the tree traversal. 
+     */
+    public void doXPLAIN(RunTimeStatistics rss, Activation activation)
+        throws StandardException
+    {
+         // save this activation
+         this.activation = activation;
+         
+         // reset this visitor
+         reset();
+         
+         // get the timings settings
+         considerTimingInformation = lcc.getStatisticsTiming();
+         
+         // placeholder for the stmt timings UUID 
+         UUID stmtTimingsUUID = null;
+         
+         //1. create new stmt timings descriptor 
+         if (considerTimingInformation){
+             stmtTimingsUUID = dd.getUUIDFactory().createUUID();
+             Timestamp endExeTS   = rss.getEndExecutionTimestamp();
+             Timestamp beginExeTS = rss.getBeginExecutionTimestamp();
+             long exeTime;
+             if (endExeTS!=null && beginExeTS!=null){
+                 exeTime = endExeTS.getTime() - beginExeTS.getTime();
+             } else {
+                 exeTime = 0;
+             }
+             
+             stmtTimings = new XPLAINStatementTimingsDescriptor(
+                 stmtTimingsUUID,                    // the Timing UUID
+                 new Long(rss.getParseTimeInMillis()),         // the Parse Time
+                 new Long(rss.getBindTimeInMillis()),          // the Bind Time
+                 new Long(rss.getOptimizeTimeInMillis()),      // the Optimize Time
+                 new Long(rss.getGenerateTimeInMillis()),      // the Generate Time
+                 new Long(rss.getCompileTimeInMillis()),       // the Compile Time
+                 new Long(exeTime),                            // the Execute Time, TODO resolve why getExecutionTime() returns 0
+                 rss.getBeginCompilationTimestamp(), // the Begin Compilation TS
+                 rss.getEndCompilationTimestamp(),   // the End   Compilation TS
+                 rss.getBeginExecutionTimestamp(),   // the Begin Execution   TS
+                 rss.getEndExecutionTimestamp()      // the End   Execution   TS
+             );
+         }
+         
+         // 2. create new Statement Descriptor 
+
+         // create new UUID
+         stmtUUID = dd.getUUIDFactory().createUUID();
+         // extract stmt type
+         String type = XPLAINUtil.getStatementType(rss.getStatementText());
+         
+         // don`t explain CALL Statements, quick implementation
+         // TODO improve usability to switch between call stmt explanation on or off
+         if (type.equalsIgnoreCase("C") && no_call_stmts) return;
+         
+         // get transaction ID
+         String xaID = lcc.getTransactionExecute().getTransactionIdString();
+         // get session ID
+         String sessionID = Integer.toString(lcc.getInstanceNumber());
+         // get the JVM ID
+         String jvmID = Integer.toString(JVMInfo.JDK_ID); 
+         // get the OS ID 
+         String osID  = System.getProperty("os.name"); 
+         // the current system time
+         long current = System.currentTimeMillis();
+         // the xplain type
+         String XPLAINtype = lcc.getXplainOnlyMode() ?
+             XPLAINUtil.XPLAIN_ONLY : XPLAINUtil.XPLAIN_FULL;
+         // the xplain time
+         Timestamp time = new Timestamp(current);
+         // the thread id
+         String threadID = Thread.currentThread().toString();
+         
+         stmt = new XPLAINStatementDescriptor(
+            stmtUUID,               // unique statement UUID
+            rss.getStatementName(), // the statement name
+            type,                   // the statement type
+            rss.getStatementText(), // the statement text
+            jvmID,                  // the JVM ID
+            osID,                   // the OS ID
+            XPLAINtype,             // the EXPLAIN tpye
+            time,                   // the EXPLAIN Timestamp
+            threadID,               // the Thread ID
+            xaID,                   // the transaction ID
+            sessionID,              // the Session ID
+            lcc.getDbname(),        // the Database name
+            lcc.getDrdaID(),        // the DRDA ID
+            stmtTimingsUUID         // Timing ID, if available
+            );
+         
+        try {
+         // add it to system catalog
+         addStmtDescriptorsToSystemCatalog();                 
+         
+         // get TopRSS and start the traversal of the RSS-tree
+         rss.acceptFromTopResultSet(this);
+         
+         // add the filled lists to the dictionary
+         addArraysToSystemCatalogs();
+        }
+        catch (SQLException e)
+        {
+            e.printStackTrace();
+            throw StandardException.plainWrapException(e);
+        }
+         
+         // clean up to free kept resources
+         clean();
+    }
+
+    // ---------------------------------------------------------
+    // helper methods
+    // ---------------------------------------------------------
+    
+    /**
+     * This method cleans up things after explanation. It frees kept 
+     * resources and still holded references.
+     */
+    private void clean(){
+        
+        
+        // forget about all the system objects
+        activation = null;
+        lcc = null;
+        dd = null;
+        tc = null;
+        
+        // forget about the stmt descriptors and the Stmt UUID
+        stmtUUID = null;
+        stmt = null;
+        stmtTimings = null;
+        
+        // reset the descriptor lists to keep memory low
+        rsets.clear();
+        rsetsTimings.clear();
+        sortrsets.clear();
+        scanrsets.clear();
+        
+        // clear stack, although it must be already empty...
+        UUIDStack.clear();
+    }
+    
+    /**
+      * Open a nested Connection with which to execute INSERT statements.
+      */
+    private Connection getDefaultConn()throws SQLException
+    {
+        ConnectionContext cc = (ConnectionContext)
+            lcc.getContextManager().getContext(ConnectionContext.CONTEXT_ID);
+        return cc.getNestedConnection(true);
+    }
+    /**
+     * This method writes only the stmt and its timing descriptor
+     * to the dataDictionary
+     *
+     */
+    private void addStmtDescriptorsToSystemCatalog()
+        throws StandardException, SQLException
+    {
+        boolean statsSave = lcc.getRunTimeStatisticsMode();
+        lcc.setRunTimeStatisticsMode(false);
+        Connection conn = getDefaultConn();
+        PreparedStatement ps = conn.prepareStatement(
+            (String)lcc.getXplainStatement("SYSXPLAIN_STATEMENTS"));
+        stmt.setStatementParameters(ps);
+        ps.executeUpdate();
+        ps.close();
+            
+        if(considerTimingInformation)
+        {
+            ps = conn.prepareStatement(
+                (String)lcc.getXplainStatement("SYSXPLAIN_STATEMENT_TIMINGS"));
+            stmtTimings.setStatementParameters(ps);
+            ps.executeUpdate();
+            ps.close();
+        }
+        conn.close();
+        lcc.setRunTimeStatisticsMode(statsSave);
+    }
+    
+    /**
+     * This method writes the created descriptor arrays 
+     * to the cooresponding system catalogs.
+     */
+    private void addArraysToSystemCatalogs()
+        throws StandardException, SQLException
+    {
+        Iterator iter;
+        boolean statsSave = lcc.getRunTimeStatisticsMode();
+        lcc.setRunTimeStatisticsMode(false);
+        Connection conn = getDefaultConn();
+
+        PreparedStatement ps = conn.prepareStatement(
+            (String)lcc.getXplainStatement("SYSXPLAIN_RESULTSETS"));
+        iter = rsets.iterator();
+        while (iter.hasNext())
+        {
+            XPLAINResultSetDescriptor rset =
+                (XPLAINResultSetDescriptor)iter.next();
+            rset.setStatementParameters(ps);
+            ps.executeUpdate();
+        }
+        ps.close();
+
+        // add the resultset timings descriptors, if timing is on
+        if(considerTimingInformation)
+        {
+            ps = conn.prepareStatement(
+                (String)lcc.getXplainStatement("SYSXPLAIN_RESULTSET_TIMINGS"));
+            iter = rsetsTimings.iterator();
+            while (iter.hasNext())
+            {
+                XPLAINResultSetTimingsDescriptor rsetT =
+                    (XPLAINResultSetTimingsDescriptor)iter.next();
+                rsetT.setStatementParameters(ps);
+                ps.executeUpdate();
+            }
+            ps.close();
+        }
+        ps = conn.prepareStatement(
+            (String)lcc.getXplainStatement("SYSXPLAIN_SCAN_PROPS"));
+        iter = scanrsets.iterator();
+        while (iter.hasNext())
+        {
+            XPLAINScanPropsDescriptor scanProps =
+                (XPLAINScanPropsDescriptor)iter.next();
+            scanProps.setStatementParameters(ps);
+            ps.executeUpdate();
+        }
+        ps.close();
+
+        ps = conn.prepareStatement(
+            (String)lcc.getXplainStatement("SYSXPLAIN_SORT_PROPS"));
+        iter = sortrsets.iterator();
+        while (iter.hasNext())
+        {
+            XPLAINSortPropsDescriptor sortProps =
+                (XPLAINSortPropsDescriptor)iter.next();
+            sortProps.setStatementParameters(ps);
+            ps.executeUpdate();
+        }
+        ps.close();
+
+        conn.close();
+        lcc.setRunTimeStatisticsMode(statsSave);
+    }
+
+}

Propchange: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/xplain/XPLAINSystemTableVisitor.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/xplain/XPLAINUtil.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/xplain/XPLAINUtil.java?rev=768597&view=auto
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/xplain/XPLAINUtil.java (added)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/xplain/XPLAINUtil.java Sat Apr 25 20:21:03 2009
@@ -0,0 +1,406 @@
+package org.apache.derby.impl.sql.execute.xplain;
+
+import java.util.Properties;
+
+import org.apache.derby.iapi.reference.SQLState;
+import org.apache.derby.iapi.services.i18n.MessageService;
+import org.apache.derby.impl.sql.catalog.XPLAINScanPropsDescriptor;
+import org.apache.derby.impl.sql.catalog.XPLAINSortPropsDescriptor;
+/**
+ * This class contains helper methods, which support the System Table Visitor. 
+ *
+ */
+public class XPLAINUtil {
+     
+     /** isolation level codes */
+     public static final String ISOLATION_READ_UNCOMMITED     =   "RU"; // 0
+     public static final String ISOLATION_READ_COMMIT         =   "RC"; // 1
+     public static final String ISOLATION_REPEAT_READ         =   "RR"; // 2
+     public static final String ISOLATION_SERIALIZABLE        =   "SE"; // 3
+     
+     
+     /** lock  modes */
+     public static final String LOCK_MODE_EXCLUSIVE              =   "EX";
+     public static final String LOCK_MODE_INSTANTENOUS_EXCLUSIVE =   "IX";
+
+     public static final String LOCK_MODE_SHARE                  =   "SH";
+     public static final String LOCK_MODE_INSTANTENOUS_SHARE     =   "IS";
+
+     /** lock granularity */
+     public static final String LOCK_GRANULARITY_TABLE           =   "T";
+     public static final String LOCK_GRANULARITY_ROW             =   "R";
+     
+     /** the rs operator codes */
+     // scan operations
+     // ---------------
+     public static final String OP_TABLESCAN                  =   "TABLESCAN";
+     public static final String OP_INDEXSCAN                  =   "INDEXSCAN";
+     public static final String OP_HASHSCAN                   =   "HASHSCAN";
+     public static final String OP_DISTINCTSCAN               =   "DISTINCTSCAN";
+     public static final String OP_LASTINDEXKEYSCAN           =   "LASTINDEXKEYSCAN";
+     public static final String OP_HASHTABLE                  =   "HASHTABLE";
+     public static final String OP_ROWIDSCAN                  =   "ROWIDSCAN";
+     public static final String OP_CONSTRAINTSCAN             =   "CONSTRAINTSCAN";
+     
+     // join operations
+     // ---------------
+     public static final String OP_JOIN_NL                    =   "NLJOIN";
+     public static final String OP_JOIN_HASH                  =   "HASHJOIN";
+     public static final String OP_JOIN_NL_LO                 =   "LONLJOIN";
+     public static final String OP_JOIN_HASH_LO               =   "LOHASHJOIN";
+     public static final String OP_UNION                      =   "UNION";
+     public static final String OP_SET                        =   "SET";
+     
+     // set operation details
+     public static final String OP_SET_INTERSECT              =   "EXCEPT";
+     public static final String OP_SET_EXCEPT                 =   "INTERSECT";
+     
+     // dml write operations
+     // --------------------
+     // basic operations
+     public static final String OP_INSERT                     =   "INSERT";
+     public static final String OP_UPDATE                     =   "UPDATE";
+     public static final String OP_DELETE                     =   "DELETE";
+     
+     // specialized op_details
+     public static final String OP_CASCADE                    =   "CASCADE";
+     public static final String OP_VTI                        =   "VTI";
+     public static final String OP_BULK                       =   "BULK";
+     public static final String OP_DISTINCT                   =   "DISTINCT";
+     
+     // other operations
+     // ----------------
+     public static final String OP_NORMALIZE                  =   "NORMALIZE";
+     public static final String OP_ANY                        =   "ANY";     
+     public static final String OP_SCROLL                     =   "SCROLL";     
+     public static final String OP_MATERIALIZE                =   "MATERIALIZE";     
+     public static final String OP_ONCE                       =   "ONCE";     
+     public static final String OP_VTI_RS                     =   "VTI";     
+     public static final String OP_ROW                        =   "ROW";     
+     public static final String OP_PROJECT                    =   "PROJECTION";     
+     public static final String OP_FILTER                     =   "FILTER";     
+     public static final String OP_AGGREGATE                  =   "AGGREGATION";     
+     public static final String OP_PROJ_RESTRICT              =   "PROJECT-FILTER";
+     // sort operations
+     // ----------------
+     public static final String OP_SORT                       =   "SORT";     
+     public static final String OP_GROUP                      =   "GROUPBY";     
+     public static final String OP_CURRENT_OF                 =   "CURRENT-OF";
+     public static final String OP_ROW_COUNT                  =   "ROW-COUNT";
+     public static final String OP_WINDOW                     =   "WINDOW";
+     
+     /** the scan info codes */
+     public static final String SCAN_HEAP                     =   "HEAP";
+     public static final String SCAN_BTREE                    =   "BTREE";
+     public static final String SCAN_SORT                     =   "SORT";
+     public static final String SCAN_BITSET_ALL               =   "ALL";
+     
+     /** the different statement type constants */
+     public static final String SELECT_STMT_TYPE             = "S";
+     public static final String SELECT_APPROXIMATE_STMT_TYPE = "SA";
+     public static final String INSERT_STMT_TYPE             = "I";
+     public static final String UPDATE_STMT_TYPE             = "U";
+     public static final String DELETE_STMT_TYPE             = "D";
+     public static final String CALL_STMT_TYPE               = "C";
+     public static final String DDL_STMT_TYPE                = "DDL";
+     
+     /** the explain type constants */
+     public static final String XPLAIN_ONLY                  = "O";
+     public static final String XPLAIN_FULL                  = "F";
+     
+     /** sort info properties */ 
+     public static final String SORT_EXTERNAL                = "EX";
+     public static final String SORT_INTERNAL                = "IN";
+     
+     /** yes no codes */ 
+     public static final String YES_CODE                     = "Y";
+     public static final String NO_CODE                      = "N";
+     
+     // ---------------------------------------------
+     // utility functions 
+     // ---------------------------------------------
+     
+     public static String getYesNoCharFromBoolean(boolean test){
+         if(test){
+             return YES_CODE;
+         } else {
+             return NO_CODE;
+         }
+     }
+     
+     public static String getHashKeyColumnNumberString(int[] hashKeyColumns){
+        // original derby encoding
+        String hashKeyColumnString;
+        if (hashKeyColumns.length == 1)
+        {
+            hashKeyColumnString = MessageService.getTextMessage(
+                                                        SQLState.RTS_HASH_KEY) +
+                                    " " + hashKeyColumns[0];
+        }
+        else
+        {
+            hashKeyColumnString = MessageService.getTextMessage(
+                                                    SQLState.RTS_HASH_KEYS) +
+                                    " (" + hashKeyColumns[0];
+            for (int index = 1; index < hashKeyColumns.length; index++)
+            {
+                hashKeyColumnString = hashKeyColumnString + "," + hashKeyColumns[index];
+            }
+            hashKeyColumnString = hashKeyColumnString + ")";
+        }
+         return hashKeyColumnString;
+     }
+     
+     
+     /** util function, to resolve the lock mode, and return a lock mode code */
+     public static String getLockModeCode(String lockString){
+         lockString = lockString.toUpperCase();
+         if(lockString.startsWith("EXCLUSIVE")){
+             return LOCK_MODE_EXCLUSIVE;
+         } else
+         if(lockString.startsWith("SHARE")){
+             return LOCK_MODE_SHARE;
+         } else
+         if(lockString.startsWith("INSTANTANEOUS")){
+             int start = "INSTANTANEOUS".length();
+             int length = lockString.length();
+             String sub = lockString.substring(start+1, length);
+             if (sub.startsWith("EXCLUSIVE")){
+                 return LOCK_MODE_INSTANTENOUS_EXCLUSIVE;
+             } else 
+             if (sub.startsWith("SHARE")){
+                 return LOCK_MODE_INSTANTENOUS_SHARE;
+             } else 
+             return null;
+         } else
+         return null;
+     }
+
+     /** util function, to resolve the isolation level and return a isolation level code */
+     public static String getIsolationLevelCode(String isolationLevel){
+         if(isolationLevel==null) return null;
+         if(isolationLevel.equals(MessageService.getTextMessage(
+                 SQLState.LANG_SERIALIZABLE))){
+             return ISOLATION_SERIALIZABLE;    // 3
+         } else 
+         if(isolationLevel.equals(MessageService.getTextMessage(
+                 SQLState.LANG_REPEATABLE_READ))){
+             return ISOLATION_REPEAT_READ;     // 2
+         } else 
+         if(isolationLevel.equals(MessageService.getTextMessage(
+                 SQLState.LANG_READ_COMMITTED))){
+             return ISOLATION_READ_COMMIT;     // 1
+         } else 
+         if(isolationLevel.equals(MessageService.getTextMessage(
+                 SQLState.LANG_READ_UNCOMMITTED))){
+             return ISOLATION_READ_UNCOMMITED; // 0
+         } else
+         return null;
+   
+     }
+     
+     
+     /** util function, to resolve the lock granularity and return a lock granularity code */
+     public static String getLockGranularityCode(String lockString){
+         lockString = lockString.toUpperCase();
+         if(lockString.endsWith("TABLE")){
+             return LOCK_GRANULARITY_TABLE;
+         } else {
+             return LOCK_GRANULARITY_ROW;
+         }
+     }
+     /**
+      * This method helps to figure out the statement type and returns
+      * an appropriate return code, characterizing the stmt type.
+      */
+     public static String getStatementType(String SQLText){
+         String type = "";
+         String text = SQLText.toUpperCase().trim();
+         if (text.startsWith("CALL")){
+             type = CALL_STMT_TYPE;
+         } else 
+         if (text.startsWith("SELECT")){
+             if (text.indexOf("~")>-1){
+                 type = SELECT_APPROXIMATE_STMT_TYPE;
+             } else {
+                 type = SELECT_STMT_TYPE;
+             }
+         } else
+         if (text.startsWith("DELETE")){
+             type = DELETE_STMT_TYPE;
+         } else
+         if (text.startsWith("INSERT")){
+             type = INSERT_STMT_TYPE;
+         } else
+         if (text.startsWith("UPDATE")){
+             type = UPDATE_STMT_TYPE;
+         } else
+         if (text.startsWith("CREATE") ||
+             text.startsWith("ALTER")  ||
+             text.startsWith("DROP")     ){
+             type = DDL_STMT_TYPE;
+         }
+         return type;
+     }
+     
+     /** helper method which extracts the right (non-internationalzed) scan
+      *  properties of the scan info properties 
+      * @param descriptor the descriptor to fill with properties
+      * @param scanProps the provided scan props
+      * @return the filled descriptor
+      */
+     public static XPLAINScanPropsDescriptor extractScanProps(
+                     XPLAINScanPropsDescriptor descriptor,
+                     Properties scanProps){
+
+         
+         // Heap Scan Info Properties
+         // extract scan type with the help of the international message service 
+         String scan_type = "";
+         String scan_type_property = scanProps.getProperty(
+                 MessageService.getTextMessage(SQLState.STORE_RTS_SCAN_TYPE));
+         if (scan_type_property!=null){
+             if(scan_type_property.equalsIgnoreCase(
+                 MessageService.getTextMessage(SQLState.STORE_RTS_HEAP))){
+                 scan_type = SCAN_HEAP;
+             } else 
+             if(scan_type_property.equalsIgnoreCase(
+                 MessageService.getTextMessage(SQLState.STORE_RTS_SORT))){
+                 scan_type = SCAN_SORT;
+             } else 
+             if(scan_type_property.equalsIgnoreCase(
+                 MessageService.getTextMessage(SQLState.STORE_RTS_BTREE))){
+                 scan_type = SCAN_BTREE;
+             }             
+         } else {
+             scan_type = null;
+         }
+         descriptor.setScan_type(scan_type);
+         
+         // extract the number of visited pages 
+         String vp_property = scanProps.getProperty(
+            MessageService.getTextMessage(SQLState.STORE_RTS_NUM_PAGES_VISITED));
+         if(vp_property!=null){
+             descriptor.setNo_visited_pages(new Integer(vp_property));
+         }
+         
+         // extract the number of visited rows 
+         String vr_property = scanProps.getProperty(
+            MessageService.getTextMessage(SQLState.STORE_RTS_NUM_ROWS_VISITED));
+         if(vr_property!=null){
+             descriptor.setNo_visited_rows(new Integer(vr_property));
+         }
+         
+         // extract the number of qualified rows 
+         String qr_property = scanProps.getProperty(
+            MessageService.getTextMessage(SQLState.STORE_RTS_NUM_ROWS_QUALIFIED));
+         if(qr_property!=null){
+             descriptor.setNo_qualified_rows(new Integer(qr_property));
+         }
+         
+         // extract the number of fetched columns 
+         String fc_property = scanProps.getProperty(
+            MessageService.getTextMessage(SQLState.STORE_RTS_NUM_COLUMNS_FETCHED));
+         if(fc_property!=null){
+             descriptor.setNo_fetched_columns(new Integer(fc_property));
+         }
+         
+         // extract the number of deleted visited rows 
+         String dvr_property = scanProps.getProperty(
+            MessageService.getTextMessage(SQLState.STORE_RTS_NUM_DELETED_ROWS_VISITED));
+         if(dvr_property!=null){
+             descriptor.setNo_visited_deleted_rows(new Integer(dvr_property));
+         }
+         
+         // extract the btree height 
+         String bth_property = scanProps.getProperty(
+            MessageService.getTextMessage(SQLState.STORE_RTS_TREE_HEIGHT));
+         if(bth_property!=null){
+             descriptor.setBtree_height(new Integer(bth_property));
+         }
+         
+         // extract the fetched bit set 
+         String bs_property = scanProps.getProperty(
+            MessageService.getTextMessage(SQLState.STORE_RTS_COLUMNS_FETCHED_BIT_SET));
+         if(bs_property!=null){
+             if (bs_property.equalsIgnoreCase(
+                 MessageService.getTextMessage(SQLState.STORE_RTS_ALL))){
+                 descriptor.setBitset_of_fetched_columns(SCAN_BITSET_ALL);
+             } else {
+                 descriptor.setBitset_of_fetched_columns(bs_property);
+                 
+             }
+         }
+         
+         // return the filled descriptor
+         return descriptor;
+         
+     }
+
+     /** helper method which extracts the right (non-internationalzed) sort
+      *  properties of the sort info properties object 
+      * @param descriptor the descriptor to fill with properties
+      * @param sortProps the provided sort props
+      * @return the filled descriptor
+      */
+     public static XPLAINSortPropsDescriptor extractSortProps(
+             XPLAINSortPropsDescriptor descriptor,
+             Properties sortProps){
+         
+         String sort_type = null;
+         String sort_type_property = sortProps.getProperty(
+                 MessageService.getTextMessage(SQLState.STORE_RTS_SORT_TYPE));
+         if(sort_type_property!=null){
+         if(sort_type_property.equalsIgnoreCase(
+             MessageService.getTextMessage(SQLState.STORE_RTS_EXTERNAL))){
+             sort_type = SORT_EXTERNAL;
+         } else {
+             sort_type = SORT_INTERNAL;
+         }}
+         descriptor.setSort_type(sort_type);
+
+         
+         String ir_property = sortProps.getProperty(
+                 MessageService.getTextMessage(SQLState.STORE_RTS_NUM_ROWS_INPUT));
+         if(ir_property!=null){
+              descriptor.setNo_input_rows(new Integer(ir_property));
+         }
+
+          String or_property = sortProps.getProperty(
+                  MessageService.getTextMessage(SQLState.STORE_RTS_NUM_ROWS_OUTPUT));
+          if(or_property!=null){
+               descriptor.setNo_output_rows(new Integer(or_property));
+          }
+              
+          if (sort_type == SORT_EXTERNAL){
+              String nomr_property = sortProps.getProperty(
+              MessageService.getTextMessage(SQLState.STORE_RTS_NUM_MERGE_RUNS));
+              
+              if(nomr_property!=null){
+                 descriptor.setNo_merge_runs(new Integer(nomr_property));
+              }
+             
+              String nomrd_property = sortProps.getProperty(
+              MessageService.getTextMessage(SQLState.STORE_RTS_MERGE_RUNS_SIZE));
+              
+              if(nomrd_property!=null){
+                  descriptor.setMerge_run_details(nomrd_property);
+              }
+          
+         }
+         
+         return descriptor;
+     }
+     /**
+       * Compute average, avoiding divide-by-zero problems.
+       *
+      * @param dividend the long value for the dividend (the whole next time)
+      * @param divisor the long value for the divisor (the sum of all rows seen)
+      * @return the quotient or null
+      */
+     public static Long getAVGNextTime(long dividend, long divisor){
+         if(divisor==0) return null;
+         if(dividend==0) return new Long(0);
+         return new Long(dividend/divisor);
+     }
+}

Propchange: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/xplain/XPLAINUtil.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: db/derby/code/trunk/java/engine/org/apache/derby/modules.properties
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/modules.properties?rev=768597&r1=768596&r2=768597&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/modules.properties (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/modules.properties Sat Apr 25 20:21:03 2009
@@ -257,6 +257,13 @@
 #
 cloudscape.config.resultSetStatisticsFactory=all
 
+derby.module.XPLAINFactory=org.apache.derby.impl.sql.execute.xplain.XPLAINFactory
+#
+#cloudscape.config.xplainFactory=derby
+#
+cloudscape.config.XPLAINFactory=all
+
+
 derby.module.optimizer=org.apache.derby.impl.sql.compile.Level2OptimizerFactoryImpl
 #
 # cloudscape.config.optimizer=derby