I have a  few  newbie  questions about MethodBuilder and BaseActivation
and  ClassBuilder

If I look at this code in ExpressionClassBuilder:

void pushPVSReference(MethodBuilder mb)
    {
        mb.pushThis();
        mb.getField(ClassName.BaseActivation, "pvs",
ClassName.ParameterValueSet);
    }

it would seem that pushThis()  pushes an instance of  BaseActivation 
onto the stack.  How exactly does that happen?
In BCMethod  pushThis seems to push a  ClassBuilder.   I don't see how
BaseActivation gets there.

And a big  picture question:
What is the relationship between QueryTreeNode, ClassBuilder,
MethodBuilder  and BaseActivation?


Some background on why I am asking this ...
I pulled my patch for this DERBY-739 am not sure I completely understand
why what I did works, even though it did seem to work.  In addition to
adding the method to BaseActivation as described in the bug description
I made these simple changes in ParamaterNode
    - I call mb.pushThis()   to get the BaseActivation pushed on the stack.
   -  Call the new getParameter method in BaseActivation instead of the
getParameter  method on the ParameterValueSet interface.

I am not really comfortable with my fix because I don't understand how
mb.pushThis() gives me a BaseActivation.

@@ -384,12 +363,10 @@

 
         /* Generate the return value */
 
-        /* First, get the field that holds the ParameterValueSet */
-        acb.pushPVSReference(mb);
-
+        mb.pushThis();
         mb.push(parameterNumber); // arg
 
-        mb.callMethod(VMOpcode.INVOKEINTERFACE, (String) null,
"getParameter",
+        mb.callMethod(VMOpcode.INVOKEVIRTUAL, (String) null,
"getParameter",
                       ClassName.DataValueDescriptor, 1);


Attached is the full patch for anyone with interest.


Kathey

Index: java/engine/org/apache/derby/impl/sql/compile/ParameterNode.java
===================================================================
--- java/engine/org/apache/derby/impl/sql/compile/ParameterNode.java	(revision 355109)
+++ java/engine/org/apache/derby/impl/sql/compile/ParameterNode.java	(working copy)
@@ -20,44 +20,23 @@
 
 package	org.apache.derby.impl.sql.compile;
 
-import org.apache.derby.iapi.sql.compile.CompilerContext;
+import java.sql.Types;
+import java.util.Enumeration;
+import java.util.Vector;
 
-import org.apache.derby.iapi.types.JSQLType;
-
-import org.apache.derby.iapi.types.TypeId;
-
-import org.apache.derby.iapi.types.DataTypeDescriptor;
-import org.apache.derby.iapi.types.DataValueDescriptor;
-
-import org.apache.derby.iapi.sql.dictionary.DataDictionary;
-
-import org.apache.derby.iapi.sql.execute.ExecutionFactory;
-
 import org.apache.derby.iapi.error.StandardException;
-
-import org.apache.derby.iapi.services.compiler.MethodBuilder;
-
-import org.apache.derby.iapi.sql.LanguageFactory;
-import org.apache.derby.iapi.sql.ParameterValueSet;
-import org.apache.derby.iapi.sql.Activation;
 import org.apache.derby.iapi.reference.ClassName;
 import org.apache.derby.iapi.reference.SQLState;
-
-import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
-
+import org.apache.derby.iapi.services.classfile.VMOpcode;
+import org.apache.derby.iapi.services.compiler.MethodBuilder;
 import org.apache.derby.iapi.services.sanity.SanityManager;
-
+import org.apache.derby.iapi.sql.compile.CompilerContext;
 import org.apache.derby.iapi.store.access.Qualifier;
+import org.apache.derby.iapi.types.DataTypeDescriptor;
+import org.apache.derby.iapi.types.DataValueDescriptor;
+import org.apache.derby.iapi.types.JSQLType;
+import org.apache.derby.iapi.types.TypeId;
 
-import org.apache.derby.impl.sql.compile.ExpressionClassBuilder;
-import org.apache.derby.impl.sql.execute.BaseActivation;
-import org.apache.derby.iapi.services.classfile.VMOpcode;
-
-import java.sql.Types;
-
-import java.util.Enumeration;
-import java.util.Vector;
-
 /**
  * This node type represents a ? parameter.
  *
@@ -384,12 +363,10 @@
 
         /* Generate the return value */
 
-        /* First, get the field that holds the ParameterValueSet */
-        acb.pushPVSReference(mb);
-
+        mb.pushThis();
         mb.push(parameterNumber); // arg
 
-        mb.callMethod(VMOpcode.INVOKEINTERFACE, (String) null, "getParameter",
+        mb.callMethod(VMOpcode.INVOKEVIRTUAL, (String) null, "getParameter",
                       ClassName.DataValueDescriptor, 1);
 
 		// For some types perform host variable checking
Index: java/engine/org/apache/derby/impl/sql/execute/BaseActivation.java
===================================================================
--- java/engine/org/apache/derby/impl/sql/execute/BaseActivation.java	(revision 355109)
+++ java/engine/org/apache/derby/impl/sql/execute/BaseActivation.java	(working copy)
@@ -1222,8 +1222,19 @@
 			lcc.getLanguageConnectionFactory().getClassFactory().getClassInspector(),
 			paramCount, hasReturnParam);
 		}
-
+	
 	/**
+	 * This method can help reduce the amount of generated code by changing
+	 * instances of this.pvs.getParameter(position) to this.getParameter(position) 
+	 * @param position
+	 * @return
+	 * @throws StandardException
+	 */
+	protected final DataValueDescriptor getParameter(int position) throws StandardException { 
+		return pvs.getParameter(position); 
+		} 
+	
+	/**
 	 return the parameters.
 	 */
 	public ParameterValueSet	getParameterValueSet() 
Index: java/testing/org/apache/derbyTesting/functionTests/tests/lang/largeCodeGen.java
===================================================================
--- java/testing/org/apache/derbyTesting/functionTests/tests/lang/largeCodeGen.java	(revision 355109)
+++ java/testing/org/apache/derbyTesting/functionTests/tests/lang/largeCodeGen.java	(working copy)
@@ -16,7 +16,7 @@
 
 public class largeCodeGen
 {
-
+	private static boolean TEST_QUERY_EXECUTION = true;
 	
     public static void main(String argv[]) 
        throws Exception
@@ -25,7 +25,7 @@
         Connection con = ij.startJBMS();
         con.setAutoCommit(false);
         createTestTable(con);
-        testParamsInWhereClause(con);
+        testLogicalOperators(con);
         testInClause(con);
         testUnions(con);
         con.commit();
@@ -51,19 +51,62 @@
 		stmt.executeUpdate("insert into t0 values(2,3,4,5.3,5.3,5.3,31.13,123456.123, 'one','one','one')");
     }
     
-    /**
+    
+	/**
+	 * Prepares and executes query against table t0 with n parameters
+	 * The assumption is that the query will always return our one row
+	 * of data inserted into the t0 table.
+	 * 
+	 * @param con
+	 * @param testName
+	 * @param sqlBuffer  - StringBuffer with SQL Text
+	 * @param numParams  - Number of parameters
+	 * @param paramValue - Parameter value
+	 * @return true if the check fails
+	 */
+	private static boolean checkT0Query(Connection con, String testName, 
+				StringBuffer sqlBuffer, int numParams, int paramValue) {
+		PreparedStatement ps;
+		try {
+			ps = con.prepareStatement(sqlBuffer.toString());
+			
+			if (TEST_QUERY_EXECUTION)
+			{
+				for (int i = 1; i <= numParams; i++)
+				{	
+					ps.setInt(i, paramValue);
+				}
+				ResultSet rs = ps.executeQuery();
+				rs.next();
+				checkRowData(rs);
+				rs.close();
+			}
+			ps.close();
+			System.out.println("PASS: " + testName);
+			return false;
+		}catch (Exception e)
+		{
+			reportFailure(testName, e);
+			return true;
+			
+		}
+	}
+
+	/**
      * Test many parameters in the where clause
      * e.g. 
 	 * @param con  
 	 */
-	private static void testParamsInWhereClause(Connection con)  throws SQLException {
+	private static void testLogicalOperators(Connection con)  throws SQLException {
 		 
 		 for (int count = 200; count <= 10000 ; count += 100)
 		 {
-			 // keep testing until it fails.
-			 if (testWhereParams(con, count))
+			 // keep testing until it fails with linkage error
+			 if (testLogicalOperators(con, count))
 				 break;
 		 }
+		 // 10,000 causes Stack overflow and database corruption
+		 //testLogicalOperators(con, 10000);
 	}
 
 	
@@ -71,74 +114,63 @@
 	 * Tests numParam parameter markers in a where clause
 	 * 
 	 * @param con          
-	 * @param  numparams  
+	 * @param  numOperands 
 	 */
-	private static boolean testWhereParams(Connection con, int numParams) throws SQLException {
-		String pred = "(si = ? AND i = ? )";
-		String testName = "WHERE clause with " + numParams + " parameters";
-		StringBuffer sqlBuffer = new StringBuffer((numParams * 20) + 512);
-		sqlBuffer.append("DELETE FROM T0 WHERE " + pred );
-		for (int i = 2; i < numParams; i+=2)
+	private static boolean testLogicalOperators(Connection con, 
+				int numOperands) throws SQLException {
+		
+		// First with parameters
+		String pred =  "(si = ? AND si = ? )";
+		String testName = "Logical operators with " + numOperands + " parameters";
+		StringBuffer sqlBuffer = new StringBuffer((numOperands * 20) + 512);
+		sqlBuffer.append("SELECT * FROM T0 WHERE " + pred );
+		for (int i = 2; i < numOperands; i+=2)
 		{
-			sqlBuffer.append(" OR (si = ? AND i = ? ) ");
+			sqlBuffer.append(" OR " + pred);
 		}
-		try {
-			PreparedStatement ps = con.prepareStatement(sqlBuffer.toString());
-			System.out.println("PASS: " + testName);
-			ps.close();
-			return false;
-		 
-		}catch (Exception e)
-		{
-			reportFailure(testName, e);
-			return true;
-			
-		}
+		return checkT0Query(con, testName, sqlBuffer, numOperands, 2);
+		
+		
+		
+		
 	}
+	
 	private static void testInClause(Connection con)  throws SQLException {
-		 for (int count = 2500; count <= 10000 ; count += 100)
+	  
+		// DERBY-739 raised number of parameters from 2700 to 3400
+		 for (int count = 3300; count <= 10000 ; count += 100)
 		 {
 			 // keep testing until it fails.
 			 if (testInClause(con, count))
-				 break;
+			 	break;
 		 }
 	}	
+	
+	/**
+	 * Test in clause with many parameters
+	 *
+	 * @param con
+	 * @param numParams - Number of parameters to test
+	 * @return true if the test fails
+	 * @throws SQLException
+	 */
 	private static boolean testInClause(Connection con, int numParams) throws SQLException {
 		String testName = "IN clause with " + numParams + " parameters";
 		StringBuffer sqlBuffer = new StringBuffer((numParams * 20) + 512);
-		sqlBuffer.append("SELECT * FROM T0 WHERE I IN ("  );
+		sqlBuffer.append("SELECT * FROM T0 WHERE SI IN ("  );
 		for (int i = 1; i < numParams; i++)
 		{
 			sqlBuffer.append("?, ");
 		}
 		sqlBuffer.append("?)");
-		try {
-			PreparedStatement ps = con.prepareStatement(sqlBuffer.toString());
-			System.out.println("PASS: " + testName);
-			ps.close();
-			return false;
-		 
-		}catch (Exception e)
-		{
-			reportFailure(testName, e);
-			return true;
-			
-		}
+		return checkT0Query(con, testName, sqlBuffer, numParams, 2); 	
 	}
+	
 	private static void testUnions(Connection con) throws Exception
 	{
 		Statement stmt = null;
         PreparedStatement pstmt = null; 
         createTestTable(con);
-		//int numUnions = 4000;
-		//int numUnions = 2000;
-		/*
-		  We still have problems with large queries. 
-		  Passes at 4000.
-		  With size 5000 it gets "java.lang.VerifyError: 
-		  (class: db2j/exe/ac601a400fx0102xc673xe3e9x000000163ac04, method: 
-		  execute signature: ()Lcom/ibm/db2j/protocol/Database/Language/Interface/ResultSet;) Illegal target of jump or branch". My fix affects generated method "fillResultSet". With size 10000 largeCodeGen gets Java exception: 'java.io.IOException: constant_pool(70796 > 65535)'.
-		*/
 		
 		String viewName = "v0";		
 		stmt = con.createStatement();
@@ -162,8 +194,6 @@
 		//System.out.println(createViewString);
 		stmt.executeUpdate(createView.toString());
 		
-		// 2000 unions caused method too big error in verifier
-		// 10000 unions overflows the number of constant pool entries
 		
 		for (int count = 800; count <= 10000; count += 100)
 		{
@@ -171,6 +201,8 @@
 			if (largeUnionSelect(con, viewName, count))
 				break;
 		}
+		// 10000 gives a different constant pool error
+		largeUnionSelect(con, viewName, 10000);
     }
     
     private static boolean largeUnionSelect(Connection con, String viewName,

Reply via email to