@@ -282,7 +282,8 @@ private static CachedMessage getCachedMessage(int errorCode) {
282282 */
283283 public static SQLException ioWriteError (IOException e ) {
284284 CachedMessage error = getCachedMessage (isc_net_write_err );
285- return new SQLNonTransientConnectionException (error .message , error .sqlState , isc_net_write_err , e );
285+ return stripBuilderStackTraceElements (
286+ new SQLNonTransientConnectionException (error .message , error .sqlState , isc_net_write_err , e ));
286287 }
287288
288289 /**
@@ -295,7 +296,8 @@ public static SQLException ioWriteError(IOException e) {
295296 */
296297 public static SQLException ioReadError (IOException e ) {
297298 CachedMessage error = getCachedMessage (isc_net_read_err );
298- return new SQLNonTransientConnectionException (error .message , error .sqlState , isc_net_read_err , e );
299+ return stripBuilderStackTraceElements (
300+ new SQLNonTransientConnectionException (error .message , error .sqlState , isc_net_read_err , e ));
299301 }
300302
301303 /**
@@ -306,7 +308,8 @@ public static SQLException ioReadError(IOException e) {
306308 */
307309 public static SQLException connectionClosed () {
308310 CachedMessage error = getCachedMessage (jb_connectionClosed );
309- return new SQLNonTransientConnectionException (error .message , error .sqlState , jb_connectionClosed );
311+ return stripBuilderStackTraceElements (
312+ new SQLNonTransientConnectionException (error .message , error .sqlState , jb_connectionClosed ));
310313 }
311314
312315 /**
@@ -600,7 +603,7 @@ public SQLException toFlatSQLException() {
600603 SQLException exception = exceptionType .createSQLException (
601604 fullExceptionMessage .toString (), interestingExceptionInfo .sqlState , interestingExceptionInfo .errorCode );
602605 exception .initCause (chain .getException ());
603- return exception ;
606+ return stripBuilderStackTraceElements ( exception ) ;
604607 }
605608
606609 private void checkNonEmpty () {
@@ -718,6 +721,58 @@ private void checkExceptionInformation() throws IllegalStateException {
718721 }
719722 }
720723
724+ /**
725+ * Removes the {@link StackTraceElement} from this builder class or its nested classes from {@code exception}.
726+ *
727+ * @param exception
728+ * exception to modify
729+ * @return same object as {@exception} after modification
730+ * @since 6
731+ */
732+ private static SQLException stripBuilderStackTraceElements (SQLException exception ) {
733+ exception .setStackTrace (stripBuilderStackTraceElements (exception .getStackTrace ()));
734+ return exception ;
735+ }
736+
737+ /**
738+ * Removes the {@link StackTraceElement} from this builder class or its nested classes from
739+ * {@code stackTraceElements}.
740+ *
741+ * @param stackTraceElements
742+ * original stacktrace elements
743+ * @return new array of {@link StackTraceElement} with the elements of this builder class or its nested classes
744+ * removed (original array if there were no such elements, or all elements are from this builder class)
745+ * @since 6
746+ */
747+ private static StackTraceElement [] stripBuilderStackTraceElements (StackTraceElement [] stackTraceElements ) {
748+ int startIndex = findFirstNonBuilderElement (stackTraceElements );
749+ // No elements or all elements from this class, return original.
750+ // This is unlikely to happen in practice, unless this method is called multiple times on the same exception
751+ if (startIndex <= 0 ) return stackTraceElements ;
752+ return Arrays .copyOfRange (stackTraceElements , startIndex , stackTraceElements .length );
753+ }
754+
755+ /**
756+ * Finds the first {@link StackTraceElement} that was not produced by this builder class or its nested classes.
757+ *
758+ * @param stackTraceElements
759+ * stacktrace elements to search
760+ * @return position of first element that was not produce by this builder class or its nested classes, {@code -1} if
761+ * all elements are from this builder class
762+ * @since 6
763+ */
764+ private static int findFirstNonBuilderElement (StackTraceElement [] stackTraceElements ) {
765+ final String thisClassName = FbExceptionBuilder .class .getName ();
766+ final String nestedClassPrefix = thisClassName + "$" ;
767+ for (int idx = 0 ; idx < stackTraceElements .length ; idx ++) {
768+ String className = stackTraceElements [idx ].getClassName ();
769+ if (!className .equals (thisClassName ) && !className .startsWith (nestedClassPrefix )) {
770+ return idx ;
771+ }
772+ }
773+ return -1 ;
774+ }
775+
721776 private static final class ExceptionInformation {
722777 private final Type type ;
723778 private final List <String > messageParameters = new ArrayList <>();
@@ -793,7 +848,7 @@ SQLException toSQLException() {
793848 if (cause != null ) {
794849 result .initCause (cause );
795850 }
796- return result ;
851+ return stripBuilderStackTraceElements ( result ) ;
797852 }
798853
799854 FBSQLExceptionInfo toSQLExceptionInfo () {
0 commit comments