Description
For each parameter in a query the following code is generated, e.g. for the 23rd parameter INT parameter.
this.pvs.setStorableDataValue(
this.getDataValueFactory().getNullInteger(),
22, // parameter number
4, // Types.INTEGER
"java.lang.Integer");
Apart being a significant amount of code per parameter , each of these will result in a new class pool entry for:
- each parameter number (beyond 5)
- each unique Types.XXX value (beyond 5)
- each unique class name for a type
(integer constants -1 through 5 are special cased as instructions in the JVM bytecode and do not require constant pool entries)
This code is generated in the post constructor method of the generated class and its purpose is to allocate a holder DataValueDescriptor of the correct type to the ParameterValueSet for the statement. These are the parameters that will be directly set by the JDBC application.
This code is generated by the method ParameterNode.generateHolder();
The actual instanceof the ParameterValueSet is generated with a single call, by the generated code passing in the number of parameters to BaseActivation.setParameterValueSet. This then generates the structure for the parameters but does not create the DataValueDescriptors since the types are not known.
The fix is to use the type definitions stored in the associated language PreparedStatement (prepared plan) DataTypeDescriptor[] to generate the null values and initalize the parameters.
I'm looking at replacing the ParameterValueSet.setStorableDataValue with an initialize method like:
public void initialize(DataTypeDescriptor[] types)
{
for (int i = 0; i < parms.length; i++)
}
With this, no code is required in the postConstructor() for a parameter. The initialize method is called when
the activation is linked to its prepared statement.. With my prototype the generated code size for the DERBY-732 query dropped from around 70k to 60k. Of course this does not fix DERBY-732, since it is not reducing code in the where clause method.