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 km...@apache.org on 2007/10/29 21:14:10 UTC
svn commit: r589836 - in
/db/derby/code/branches/10.1/java/engine/org/apache/derby: iapi/reference/
impl/services/bytecode/ impl/sql/compile/ loc/
Author: kmarsden
Date: Mon Oct 29 13:14:09 2007
New Revision: 589836
URL: http://svn.apache.org/viewvc?rev=589836&view=rev
Log:
DERBY-176 (partial) Improve error message for linkage error.
merge from trunk revision 358605
Modified:
db/derby/code/branches/10.1/java/engine/org/apache/derby/iapi/reference/SQLState.java
db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/services/bytecode/BCClass.java
db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/services/bytecode/BCMethod.java
db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/services/bytecode/CodeChunk.java
db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/services/bytecode/Conditional.java
db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/sql/compile/StatementNode.java
db/derby/code/branches/10.1/java/engine/org/apache/derby/loc/messages_en.properties
Modified: db/derby/code/branches/10.1/java/engine/org/apache/derby/iapi/reference/SQLState.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.1/java/engine/org/apache/derby/iapi/reference/SQLState.java?rev=589836&r1=589835&r2=589836&view=diff
==============================================================================
--- db/derby/code/branches/10.1/java/engine/org/apache/derby/iapi/reference/SQLState.java (original)
+++ db/derby/code/branches/10.1/java/engine/org/apache/derby/iapi/reference/SQLState.java Mon Oct 29 13:14:09 2007
@@ -197,6 +197,7 @@
String GENERATED_CLASS_LINKAGE_ERROR = "XBCM1.S";
String GENERATED_CLASS_INSTANCE_ERROR = "XBCM2.S";
String GENERATED_CLASS_NO_SUCH_METHOD = "XBCM3.S";
+ String GENERATED_CLASS_LIMIT_EXCEEDED = "XBCM4.S";
/*
** Cryptography
@@ -983,6 +984,7 @@
String LANG_EXPLICIT_NULLS_IN_DB2_MODE = "42Z9C";
String LANG_UNSUPPORTED_TRIGGER_STMT = "42Z9D";
String LANG_DROP_CONSTRAINT_TYPE = "42Z9E";
+ String LANG_QUERY_TOO_COMPLEX = "42ZA0";
//following 3 matches the DB2 sql states
String LANG_DECLARED_GLOBAL_TEMP_TABLE_ONLY_IN_SESSION_SCHEMA = "428EK";
Modified: db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/services/bytecode/BCClass.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/services/bytecode/BCClass.java?rev=589836&r1=589835&r2=589836&view=diff
==============================================================================
--- db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/services/bytecode/BCClass.java (original)
+++ db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/services/bytecode/BCClass.java Mon Oct 29 13:14:09 2007
@@ -80,6 +80,13 @@
*
*/
class BCClass extends GClass {
+
+ /**
+ * Simple text indicating any limits execeeded while generating
+ * the class file.
+ */
+ private String limitMsg;
+
//
// ClassBuilder interface
//
@@ -153,6 +160,10 @@
"GEN complete for class "+name);
}
}
+
+ if (limitMsg != null)
+ throw StandardException.newException(
+ SQLState.GENERATED_CLASS_LIMIT_EXCEEDED, getFullName(), limitMsg);
return bytecode;
}
@@ -376,7 +387,7 @@
chunk.addInstr(CodeChunk.RETURN_OPCODE[vmTypeId]);
int typeWidth = Type.width(vmTypeId);
- chunk.complete(classHold, method, typeWidth, 1);
+ chunk.complete(null, classHold, method, typeWidth, 1);
/*
** add the set method
@@ -398,7 +409,38 @@
chunk.addInstr(VMOpcode.RETURN);
- chunk.complete(classHold, method, typeWidth + (staticField ? 0 : 1), 1 + typeWidth);
+ chunk.complete(null, classHold, method, typeWidth + (staticField ? 0 : 1), 1 + typeWidth);
+ }
+
+ /**
+ * Add the fact that some class limit was exceeded while generating
+ * the class. We create a set ofg them and report at the end, this
+ * allows the generated class file to still be dumped.
+ * @param mb
+ * @param limitName
+ * @param limit
+ * @param value
+ */
+ void addLimitExceeded(BCMethod mb, String limitName, int limit, int value)
+ {
+ StringBuffer sb = new StringBuffer();
+ if (limitMsg != null)
+ {
+ sb.append(limitMsg);
+ sb.append(", ");
+ }
+
+ sb.append("method:");
+ sb.append(mb.getName());
+ sb.append(" ");
+ sb.append(limitName);
+ sb.append(" (");
+ sb.append(value);
+ sb.append(" > ");
+ sb.append(limit);
+ sb.append(")");
+
+ limitMsg = sb.toString();
}
}
Modified: db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/services/bytecode/BCMethod.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/services/bytecode/BCMethod.java?rev=589836&r1=589835&r2=589836&view=diff
==============================================================================
--- db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/services/bytecode/BCMethod.java (original)
+++ db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/services/bytecode/BCMethod.java Mon Oct 29 13:14:09 2007
@@ -205,7 +205,7 @@
// get the code attribute to put itself into the class
// provide the final header information needed
- myCode.complete(modClass, myEntry, maxStack, currentVarNum);
+ myCode.complete(this, modClass, myEntry, maxStack, currentVarNum);
}
/*
@@ -895,7 +895,7 @@
public void startElseCode() {
// start the else code
- Type[] entryStack = condition.startElse(myCode, copyStack());
+ Type[] entryStack = condition.startElse(this, myCode, copyStack());
for (int i = stackDepth = 0; i < entryStack.length; i++)
{
@@ -905,7 +905,7 @@
}
public void completeConditional() {
- condition = condition.end(myCode, stackTypes, stackTypeOffset);
+ condition = condition.end(this, myCode, stackTypes, stackTypeOffset);
}
public void pop() {
Modified: db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/services/bytecode/CodeChunk.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/services/bytecode/CodeChunk.java?rev=589836&r1=589835&r2=589836&view=diff
==============================================================================
--- db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/services/bytecode/CodeChunk.java (original)
+++ db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/services/bytecode/CodeChunk.java Mon Oct 29 13:14:09 2007
@@ -350,25 +350,36 @@
/**
* now that we have codeBytes, fix the lengths fields in it
* to reflect what was stored.
+ * Limits checked here are from these sections of the JVM spec.
+ * <UL>
+ * <LI> 4.7.3 The Code Attribute
+ * <LI> 4.10 Limitations of the Java Virtual Machine
+ * </UL>
*/
- void fixLengths(int maxStack, int maxLocals, int codeLength) {
+ private void fixLengths(BCMethod mb, int maxStack, int maxLocals, int codeLength) {
byte[] codeBytes = cout.getData();
// max_stack is in bytes 0-1
+ if (mb != null && maxStack > 65535)
+ mb.cb.addLimitExceeded(mb, "max_stack", 65535, maxStack);
+
codeBytes[0] = (byte)(maxStack >> 8 );
codeBytes[1] = (byte)(maxStack );
// max_locals is in bytes 2-3
+ if (mb != null && maxLocals > 65535)
+ mb.cb.addLimitExceeded(mb, "max_locals", 65535, maxLocals);
codeBytes[2] = (byte)(maxLocals >> 8 );
codeBytes[3] = (byte)(maxLocals );
// code_length is in bytes 4-7
+ if (mb != null && codeLength > 65536)
+ mb.cb.addLimitExceeded(mb, "code_length", 65536, codeLength);
codeBytes[4] = (byte)(codeLength >> 24 );
codeBytes[5] = (byte)(codeLength >> 16 );
codeBytes[6] = (byte)(codeLength >> 8 );
codeBytes[7] = (byte)(codeLength );
-
}
/**
@@ -376,7 +387,8 @@
* now that it holds all of the instructions and
* the exception table.
*/
- void complete(ClassHolder ch, ClassMember method, int maxStack, int maxLocals) {
+ void complete(BCMethod mb, ClassHolder ch,
+ ClassMember method, int maxStack, int maxLocals) {
int codeLength = getRelativePC();
@@ -412,7 +424,7 @@
} catch (IOException ioe) {
}
- fixLengths(maxStack, maxLocals, codeLength);
+ fixLengths(mb, maxStack, maxLocals, codeLength);
method.addAttribute("Code", out);
}
Modified: db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/services/bytecode/Conditional.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/services/bytecode/Conditional.java?rev=589836&r1=589835&r2=589836&view=diff
==============================================================================
--- db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/services/bytecode/Conditional.java (original)
+++ db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/services/bytecode/Conditional.java Mon Oct 29 13:14:09 2007
@@ -43,6 +43,9 @@
class Conditional {
private final Conditional parent;
+ /**
+ * Offset in the code stream of the 'if' opcode.
+ */
private final int ifOffset;
private Type[] stack;
private int thenGotoOffset;
@@ -70,7 +73,7 @@
* @param thenStack Type stack on completing the conditional then block.
* @return the type stack on entering the then block
*/
- Type[] startElse(CodeChunk chunk, Type[] thenStack) {
+ Type[] startElse(BCMethod mb, CodeChunk chunk, Type[] thenStack) {
thenGotoOffset = chunk.getRelativePC();
@@ -78,7 +81,7 @@
chunk.addInstrU2(VMOpcode.GOTO, 0);
// fill in the branch opcode
- fillIn(chunk, ifOffset);
+ fillIn(mb, chunk, ifOffset);
Type[] entryStack = stack;
stack = thenStack;
@@ -94,13 +97,13 @@
* @param stackNumber Current number of valid elements in elseStack
* @return The conditional this conditional was nested in, if any.
*/
- Conditional end(CodeChunk chunk, Type[] elseStack, int stackNumber) {
+ Conditional end(BCMethod mb, CodeChunk chunk, Type[] elseStack, int stackNumber) {
if (thenGotoOffset == 0) {
// no else condition
- fillIn(chunk, ifOffset);
+ fillIn(mb, chunk, ifOffset);
} else {
- fillIn(chunk, thenGotoOffset);
+ fillIn(mb, chunk, thenGotoOffset);
}
if (SanityManager.DEBUG)
@@ -121,16 +124,28 @@
return parent;
}
- private void fillIn(CodeChunk chunk, int where) {
+ /**
+ *
+ * @param chunk Our code chunk
+ * @param whereFrom Offset of the branch opcode in the code stream
+ */
+ private void fillIn(BCMethod mb, CodeChunk chunk, int whereFrom) {
byte[] codeBytes = chunk.getCout().getData();
- int offset = chunk.getRelativePC() - where;
-
- where += 8;
-
- codeBytes[where + 1] = (byte)(offset >> 8 );
- codeBytes[where + 2] = (byte)(offset);
+ int offset = chunk.getRelativePC() - whereFrom;
+
+ // branch offsets are a 16bit signed value, this implementation
+ // currently only generates forward branches
+ if (offset > 32767)
+ mb.cb.addLimitExceeded(mb, "branch_offset", 32767, offset);
+
+ // Skip the eight byte header at the start of the
+ // byte array, the eight bytes are the CodeAttribute header.
+ whereFrom += 8;
+
+ codeBytes[whereFrom + 1] = (byte)(offset >> 8 );
+ codeBytes[whereFrom + 2] = (byte)(offset);
}
Modified: db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/sql/compile/StatementNode.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/sql/compile/StatementNode.java?rev=589836&r1=589835&r2=589836&view=diff
==============================================================================
--- db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/sql/compile/StatementNode.java (original)
+++ db/derby/code/branches/10.1/java/engine/org/apache/derby/impl/sql/compile/StatementNode.java Mon Oct 29 13:14:09 2007
@@ -262,10 +262,24 @@
// wrap up the constructor by putting a return at the end of it
generatingClass.finishConstructor();
- // cook the completed class into a real class
- // and stuff it into activationClass
- GeneratedClass activationClass = generatingClass.getGeneratedClass(byteCode);
+ try {
+ // cook the completed class into a real class
+ // and stuff it into activationClass
+ GeneratedClass activationClass = generatingClass.getGeneratedClass(byteCode);
- return activationClass;
+ return activationClass;
+ } catch (StandardException e) {
+
+ String msgId = e.getMessageId();
+
+ if (SQLState.GENERATED_CLASS_LIMIT_EXCEEDED.equals(msgId)
+ || SQLState.GENERATED_CLASS_LINKAGE_ERROR.equals(msgId))
+ {
+ throw StandardException.newException(
+ SQLState.LANG_QUERY_TOO_COMPLEX, e);
+ }
+
+ throw e;
+ }
}
}
Modified: db/derby/code/branches/10.1/java/engine/org/apache/derby/loc/messages_en.properties
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.1/java/engine/org/apache/derby/loc/messages_en.properties?rev=589836&r1=589835&r2=589836&view=diff
==============================================================================
--- db/derby/code/branches/10.1/java/engine/org/apache/derby/loc/messages_en.properties (original)
+++ db/derby/code/branches/10.1/java/engine/org/apache/derby/loc/messages_en.properties Mon Oct 29 13:14:09 2007
@@ -52,6 +52,7 @@
XBCM1.S=Java linkage error thrown during load of generated class {0}.
XBCM2.S=Cannot create an instance of generated class {0}.
XBCM3.S=Method {1}() does not exist in generated class {0}.
+XBCM4.S=Java class file format limit(s) exceeded: {1} in generated class {0}.
# Properties
@@ -519,6 +520,7 @@
42Y00=Class ''{0}'' does not implement org.apache.derby.iapi.db.AggregateDefinition and thus cannot be used as an aggregate expression.
42Y01=Constraint ''{0}'' is invalid.
42Y03=''{0}'' is not recognized as a function or procedure.
+42ZA0=Statement too complex. Try rewriting the query to remove complexity. Eliminating many duplicate expressions or breaking up the query and storing interim results in a temporary table can often help resolve this error.
# EXTERNAL NAME is SQL keyword - do not translate
42Y04=Cannot create a procedure or function with EXTERNAL NAME ''{0}'' because it is not a list separated by periods. The expected format is <full java path>.<method name>.