db-derby-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From d..@apache.org
Subject svn commit: r450607 - in /db/derby/code/trunk/java/engine/org/apache/derby: iapi/sql/ impl/jdbc/ impl/sql/
Date Wed, 27 Sep 2006 22:33:07 GMT
Author: djd
Date: Wed Sep 27 15:33:06 2006
New Revision: 450607

URL: http://svn.apache.org/viewvc?view=rev&rev=450607
Log:
DERBY-1879 Save the EmbedResultSetMetaData object and the case-insensitive column name map
in the ResultDescription object
and not EmbedResultSet. This means these objects are created once per compiled plan (as needed)
and not once per
EmbedResultSet (as needed). This improves the performance by reducing the overhead for simple
queries (DERBY-1876).

Modified:
    db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/ResultDescription.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedResultSet.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedResultSetMetaData.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedResultSetMetaData40.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/GenericColumnDescriptor.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/GenericResultDescription.java

Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/ResultDescription.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/ResultDescription.java?view=diff&rev=450607&r1=450606&r2=450607
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/ResultDescription.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/sql/ResultDescription.java Wed Sep
27 15:33:06 2006
@@ -74,7 +74,8 @@
 	 * 5, then columns 5 to getColumnCount() are removed.
 	 * The new ResultDescription points to the same
 	 * ColumnDescriptors (this method performs a shallow
-	 * copy.
+	 * copy. The saved JDBC ResultSetMetaData will
+     * not be copied.
 	 *
 	 * @param truncateFrom the starting column to remove,
 	 * 1-based.
@@ -82,4 +83,41 @@
 	 * @return a new ResultDescription
 	 */
 	public ResultDescription truncateColumns(int truncateFrom);
+    
+    /**
+     * Set the JDBC ResultSetMetaData for this ResultDescription.
+     * A ResultSetMetaData object can be saved in the statement
+     * plan using this method. This only works while
+     * the ResultSetMetaData api does not contain a getConnection()
+     * method or a close method.
+     * <BR>
+     * If this object already has a saved meta data object
+     * this call will do nothing.
+     * Due to synchronization the saved ResultSetMetaData
+     * obejct may not be the one passed in, ie. if two
+     * threads call this concurrently, only one will be saved.
+     * It is assumed the JDBC layer passes in a ResultSetMetaData
+     * object based upon this.
+     */
+    public void setMetaData(java.sql.ResultSetMetaData rsmd);
+    
+    /**
+     * Get the saved JDBC ResultSetMetaData. Will return
+     * null if setMetaData() has not been called on this
+     * object. The caller then should manufacture a
+     * ResultSetMetaData object and pass it into setMetaData.
+     */
+    public java.sql.ResultSetMetaData getMetaData();
+    
+    /**
+     * Return the position of the column matching the
+     * passed in names following the JDBC rules for
+     * ResultSet.getXXX and updateXXX.
+     * Rules are the matching is case insensitive
+     * and the insensitive name matches the first
+     * column found that matches (starting at postion 1).
+     * @param name
+     * @return Position of the column (1-based), -1 if no match.
+     */
+    public int findColumnInsenstive(String name);
 }

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedResultSet.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedResultSet.java?view=diff&rev=450607&r1=450606&r2=450607
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedResultSet.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedResultSet.java Wed Sep
27 15:33:06 2006
@@ -129,7 +129,6 @@
 	// immutable state
 	private ResultSet theResults;
 	private boolean forMetaData;
-	private ResultSetMetaData rMetaData;
 	private SQLWarning topWarning;
 
 	/**
@@ -148,12 +147,6 @@
 
   
 	private final ResultDescription resultDescription;
-	
-	/**
-	 * A map which maps a column name to a column number.
-	 * Entries only added when accessing columns with the name.
-	 */
-	private Map columnNameMap;
 
     // max rows limit for this result set
     private int maxRows;
@@ -269,7 +262,6 @@
 			getLanguageConnectionFactory().getExecutionFactory();
 		final int columnCount = getMetaData().getColumnCount();
 		this.currentRow = factory.getValueRow(columnCount);
-		this.columnNameMap = null;
 		currentRow.setRowArray(null);
 
 		// Only incur the cost of allocating and maintaining
@@ -642,7 +634,6 @@
 
 			// the idea is to release resources, so:
 			currentRow.setRowArray(null);
-			rMetaData = null; // let it go, we can make a new one
 
 			// we hang on to theResults and messenger
 			// in case more calls come in on this resultSet
@@ -1612,21 +1603,21 @@
      * @return the description of a ResultSet's columns
 	 * @exception SQLException thrown on failure.
      */
-    public ResultSetMetaData getMetaData() throws SQLException {
+    public final ResultSetMetaData getMetaData() throws SQLException {
 
 	  checkIfClosed("getMetaData");	// checking result set closure does not depend
-								// on the underlying connection.  Do this
-								// outside of the connection synchronization.
-
-	  synchronized (getConnectionSynchronization()) {
+								// on the underlying connection.
 
+      ResultSetMetaData rMetaData =
+          resultDescription.getMetaData();
 
 		if (rMetaData == null) {
-			// cache this object and keep returning it
-			rMetaData = newEmbedResultSetMetaData(resultDescription);
+			// save this object at the plan level
+			rMetaData = factory.newEmbedResultSetMetaData(
+                    resultDescription.getColumnInfo());
+            resultDescription.setMetaData(rMetaData);
 		}
 		return rMetaData;
-	  }
 	}
     
     /**
@@ -4238,50 +4229,15 @@
 
 		if (columnName == null)
 			throw newSQLException(SQLState.NULL_COLUMN_NAME);
+        
+        int position = resultDescription.findColumnInsenstive(columnName);
 		
-		final Map workMap; 
-		                   
-		synchronized (this) {
-			if (columnNameMap==null) {
-				// updateXXX and getXXX methods are case insensitive and the 
-				// first column should be returned. The loop goes backward to 
-				// create a map which preserves this property.
-				columnNameMap = new HashMap();
-				for (int i = resultDescription.getColumnCount(); i>=1; i--) {
-					
-					final String key = StringUtil.
-						SQLToUpperCase(resultDescription.
-							getColumnDescriptor(i).getName());
-					
-					final Integer value = ReuseFactory.getInteger(i);
-					
-					columnNameMap.put(key, value);
-				}
-			}
-			workMap = columnNameMap;
-		}
-		
-		Integer val = (Integer) workMap.get(columnName);
-		if (val==null) {
-			val = (Integer) workMap.get(StringUtil.SQLToUpperCase(columnName));
-		}
-		if (val==null) {
+		if (position == -1) {
 			throw newSQLException(SQLState.COLUMN_NOT_FOUND, columnName);
 		} else {
-			return val.intValue();
+			return position;
 		}
 	}
-
-
-
-	//
-	// methods to be overridden in subimplementations
-	// that want to stay within their subimplementation.
-	//
-	protected EmbedResultSetMetaData newEmbedResultSetMetaData(ResultDescription resultDesc)
{
-		return factory.newEmbedResultSetMetaData(resultDesc.getColumnInfo());
-	}
-
 	/**
 	 * Documented behaviour for streams is that they are implicitly closed on
 	 * the next get*() method call.

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedResultSetMetaData.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedResultSetMetaData.java?view=diff&rev=450607&r1=450606&r2=450607
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedResultSetMetaData.java
(original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedResultSetMetaData.java
Wed Sep 27 15:33:06 2006
@@ -41,12 +41,19 @@
  * and properties of the columns in a ResultSet.
  *
  * <p>
- * We take the (cloudscape) ResultDescription and examine it, to return
+ * We take the (Derby) ResultDescription and examine it, to return
  * the appropriate information.
 
    <P>
    This class can be used outside of this package to convert a
    ResultDescription into a ResultSetMetaData object.
+   <P>
+   EmbedResultSetMetaData objects are shared across multiple threads
+   by being stored in the ResultDescription for a compiled plan.
+   If the required api for ResultSetMetaData ever changes so
+   that it has a close() method, a getConnection() method or
+   any other Connection or ResultSet specific method then
+   this sharing must be removed.
  *
  * @author ames
  */
@@ -71,8 +78,8 @@
      *
      * @return the number
      */
-	public int getColumnCount()	{
-		return columnInfo == null ? 0 : columnInfo.length;
+	public final int getColumnCount()	{
+		return columnInfo.length;
 	}
 
     /**
@@ -83,8 +90,8 @@
 	 * @exception SQLException thrown on failure
      *
      */
-	public boolean isAutoIncrement(int column) throws SQLException	{
-
+	public final boolean isAutoIncrement(int column) throws SQLException	{
+        validColumnNumber(column);
 		ResultColumnDescriptor rcd = columnInfo[column - 1];
 		return rcd.isAutoincrement();
 	}
@@ -96,7 +103,7 @@
      * @return true if so
 	 * @exception SQLException thrown on failure
      */
-	public boolean isCaseSensitive(int column) throws SQLException	{
+	public final boolean isCaseSensitive(int column) throws SQLException	{
 	  return DataTypeUtilities.isCaseSensitive(getColumnTypeDescriptor(column));
 	}
 
@@ -108,7 +115,7 @@
      * @return true if so
 	 * @exception SQLException thrown on failure
      */
-	public boolean isSearchable(int column) throws SQLException	{
+	public final boolean isSearchable(int column) throws SQLException	{
 		validColumnNumber(column);
 
 		// we have no restrictions yet, so this is always true
@@ -123,7 +130,7 @@
      * @return true if so
 	 * @exception SQLException thrown on failure
      */
-	public boolean isCurrency(int column) throws SQLException	{
+	public final boolean isCurrency(int column) throws SQLException	{
 
 		return DataTypeUtilities.isCurrency(getColumnTypeDescriptor(column));
 	}
@@ -135,7 +142,7 @@
      * @return columnNoNulls, columnNullable or columnNullableUnknown
 	 * @exception SQLException thrown on failure
      */
-	public int isNullable(int column) throws SQLException	{
+	public final int isNullable(int column) throws SQLException	{
 		return DataTypeUtilities.isNullable(getColumnTypeDescriptor(column));
 	}
 
@@ -146,7 +153,7 @@
      * @return true if so
 	 * @exception SQLException thrown on failure
      */
-	public boolean isSigned(int column) throws SQLException	{
+	public final boolean isSigned(int column) throws SQLException	{
 		return DataTypeUtilities.isSigned(getColumnTypeDescriptor(column));
 	}
 
@@ -158,7 +165,7 @@
      * @return max width
 	 * @exception SQLException thrown on failure
      */
-	public int getColumnDisplaySize(int column) throws SQLException	{
+	public final int getColumnDisplaySize(int column) throws SQLException	{
 		return DataTypeUtilities.getColumnDisplaySize(getColumnTypeDescriptor(column));
 	}
 
@@ -170,7 +177,7 @@
      * @return true if so
 	 * @exception SQLException thrown on failure
      */
-	public String getColumnLabel(int column) throws SQLException {
+	public final String getColumnLabel(int column) throws SQLException {
 		ResultColumnDescriptor cd = columnInfo[column - 1];
 		String s = cd.getName();
 
@@ -186,7 +193,7 @@
      * @return column name
 	 * @exception SQLException thrown on failure
      */
-	public String getColumnName(int column) throws SQLException	{
+	public final String getColumnName(int column) throws SQLException	{
 		ResultColumnDescriptor cd = columnInfo[column - 1];
 		String s = cd.getName();
 		// database returns null when no column name to differentiate from empty name
@@ -202,7 +209,7 @@
      * @return schema name or "" if not applicable
 	 * @exception SQLException thrown on failure
      */
-	public String getSchemaName(int column) throws SQLException	{
+	public final String getSchemaName(int column) throws SQLException	{
 		ResultColumnDescriptor cd = columnInfo[column - 1];
 
 		String s = cd.getSourceSchemaName();
@@ -217,7 +224,7 @@
      * @return precision
 	 * @exception SQLException thrown on failure
      */
-	public int getPrecision(int column) throws SQLException	{
+	public final int getPrecision(int column) throws SQLException	{
 		return DataTypeUtilities.getDigitPrecision(getColumnTypeDescriptor(column));
 	}
 
@@ -229,7 +236,7 @@
      * @return scale
 	 * @exception SQLException thrown on failure
      */
-	public int getScale(int column) throws SQLException	{
+	public final int getScale(int column) throws SQLException	{
 		DataTypeDescriptor dtd = getColumnTypeDescriptor(column);
 		// REMIND -- check it is valid to ask for scale
 		return dtd.getScale();
@@ -241,7 +248,7 @@
      * @return table name or "" if not applicable
 	 * @exception SQLException thrown on failure
      */
-	public String getTableName(int column) throws SQLException {
+	public final String getTableName(int column) throws SQLException {
 		ResultColumnDescriptor cd = columnInfo[column - 1];
 		String s = cd.getSourceTableName();
 
@@ -256,7 +263,7 @@
      * @return column name or "" if not applicable.
 	 * @exception SQLException thrown on failure
      */
-	public String getCatalogName(int column) throws SQLException {
+	public final String getCatalogName(int column) throws SQLException {
 		validColumnNumber(column);
 		return "";
 	}
@@ -269,7 +276,7 @@
      * @see Types
 	 * @exception SQLException thrown on failure
      */
-	public int getColumnType(int column) throws SQLException {
+	public final int getColumnType(int column) throws SQLException {
 		DataTypeDescriptor dtd = getColumnTypeDescriptor(column);
 		return dtd.getTypeId().getJDBCTypeId();
 	}
@@ -281,7 +288,7 @@
      * @return type name
 	 * @exception SQLException thrown on failure
      */
-	public String getColumnTypeName(int column) throws SQLException	{
+	public final String getColumnTypeName(int column) throws SQLException	{
 		DataTypeDescriptor dtd = getColumnTypeDescriptor(column);
 		return dtd.getTypeId().getSQLTypeName();
 	}
@@ -293,7 +300,7 @@
      * @return true if so
 	 * @exception SQLException thrown on failure
      */
-	public boolean isReadOnly(int column) throws SQLException {
+	public final boolean isReadOnly(int column) throws SQLException {
 		validColumnNumber(column);
 
 		// we just don't know if it is a base table column or not
@@ -307,7 +314,7 @@
      * @return true if so
 	 * @exception SQLException thrown on failure
      */
-	public boolean isWritable(int column) throws SQLException {
+	public final boolean isWritable(int column) throws SQLException {
 		validColumnNumber(column);
 		return columnInfo[column - 1].updatableByCursor();
 	}
@@ -319,7 +326,7 @@
      * @return true if so
 	 * @exception SQLException thrown on failure
      */
-	public boolean isDefinitelyWritable(int column) throws SQLException	{
+	public final boolean isDefinitelyWritable(int column) throws SQLException	{
 		validColumnNumber(column);
 
 		// we just don't know if it is a base table column or not
@@ -337,7 +344,7 @@
                       SQLState.COLUMN_NOT_FOUND, new Integer(column));
 	}
 
-	public DataTypeDescriptor getColumnTypeDescriptor(int column) throws SQLException 
+	private DataTypeDescriptor getColumnTypeDescriptor(int column) throws SQLException 
 	{
 		validColumnNumber(column);
 
@@ -362,7 +369,7 @@
 	 *
 	 * @exception SQLException Feature not inplemented for now.
      */
-    public String getColumnClassName(int column) throws SQLException {
+    public final String getColumnClassName(int column) throws SQLException {
 		
 		return getColumnTypeDescriptor(column).getTypeId().getResultSetMetaDataTypeName();
 	}

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedResultSetMetaData40.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedResultSetMetaData40.java?view=diff&rev=450607&r1=450606&r2=450607
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedResultSetMetaData40.java
(original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedResultSetMetaData40.java
Wed Sep 27 15:33:06 2006
@@ -24,7 +24,16 @@
 
 import org.apache.derby.iapi.reference.SQLState;
 import org.apache.derby.iapi.sql.ResultColumnDescriptor;
-
+/**
+ * ResultSetMetaData implementation for JDBC 4.
+   <P>
+   EmbedResultSetMetaData40 objects are shared across multiple threads
+   by being stored in the ResultDescription for a compiled plan.
+   If the required api for ResultSetMetaData ever changes so
+   that it has a close() method, a getConnection() method or
+   any other Connection or ResultSet specific method then
+   this sharing must be removed.
+ */
 public class EmbedResultSetMetaData40 extends EmbedResultSetMetaData {
     
     public EmbedResultSetMetaData40(ResultColumnDescriptor[] columnInfo) {

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/GenericColumnDescriptor.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/GenericColumnDescriptor.java?view=diff&rev=450607&r1=450606&r2=450607
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/GenericColumnDescriptor.java
(original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/GenericColumnDescriptor.java
Wed Sep 27 15:33:06 2006
@@ -201,7 +201,6 @@
 		return;
 	}	
 
-	public void djdrcd() {}
 	/**
 	 * Read this object from a stream of stored objects.
 	 *

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/GenericResultDescription.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/GenericResultDescription.java?view=diff&rev=450607&r1=450606&r2=450607
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/GenericResultDescription.java
(original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/GenericResultDescription.java
Wed Sep 27 15:33:06 2006
@@ -21,6 +21,7 @@
 
 package org.apache.derby.impl.sql;
 
+import org.apache.derby.iapi.reference.SQLState;
 import org.apache.derby.iapi.sql.ResultColumnDescriptor;
 import org.apache.derby.iapi.sql.ResultDescription;
 
@@ -29,10 +30,17 @@
 import org.apache.derby.iapi.services.io.StoredFormatIds;
 import org.apache.derby.iapi.services.io.FormatIdUtil;
 import org.apache.derby.iapi.services.io.Formatable;
+import org.apache.derby.iapi.util.ReuseFactory;
+import org.apache.derby.iapi.util.StringUtil;
 
 import java.io.ObjectOutput;
 import java.io.ObjectInput;
 import java.io.IOException;
+import java.sql.ResultSetMetaData;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
 /**
  * GenericResultDescription: basic implementation of result
  * description, used in conjunction with the other 
@@ -61,6 +69,18 @@
 
 	private ResultColumnDescriptor[] columns;
 	private String statementType;
+    
+    /**
+     * Saved JDBC ResultSetMetaData object.
+     * @see ResultDescription#setMetaData(java.sql.ResultSetMetaData)
+     */
+    private transient ResultSetMetaData metaData;
+    
+    /**
+     * A map which maps a column name to a column number.
+     * Entries only added when accessing columns with the name.
+     */
+    private Map columnNameMap;
 	
 	/**
 	 * Niladic constructor for Formatable
@@ -257,5 +277,64 @@
 			return "";
 		}
 	}
+
+    /**
+     * Set the meta data if it has not already been set.
+     */
+    public synchronized void setMetaData(ResultSetMetaData rsmd) {
+        if (metaData == null)
+            metaData = rsmd;
+    }
+
+    /**
+     * Get the saved meta data.
+     */
+    public synchronized ResultSetMetaData getMetaData() {
+        return metaData;
+    }
+
+    /**
+     * Find a column name based upon the JDBC rules for
+     * getXXX and setXXX. Name matching is case-insensitive,
+     * matching the first name (1-based) if there are multiple
+     * columns that map to the same name.
+     */
+    public int findColumnInsenstive(String columnName) {
+        
+        final Map workMap; 
+        
+        synchronized (this) {
+            if (columnNameMap==null) {
+                // updateXXX and getXXX methods are case insensitive and the 
+                // first column should be returned. The loop goes backward to 
+                // create a map which preserves this property.
+                Map map = new HashMap();
+                for (int i = getColumnCount(); i>=1; i--) {
+                    
+                    final String key = StringUtil.
+                        SQLToUpperCase(
+                            getColumnDescriptor(i).getName());
+                    
+                    final Integer value = ReuseFactory.getInteger(i);
+                    
+                    map.put(key, value);
+                }
+                
+                // Ensure this map can never change.
+                columnNameMap = Collections.unmodifiableMap(map);
+            }
+            workMap = columnNameMap;
+        }
+        
+        Integer val = (Integer) workMap.get(columnName);
+        if (val==null) {
+            val = (Integer) workMap.get(StringUtil.SQLToUpperCase(columnName));
+        }
+        if (val==null) {
+            return -1;
+        } else {
+            return val.intValue();
+        }
+    }
 }
 



Mime
View raw message