You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-dev@db.apache.org by "Bernt M. Johnsen" <Be...@Sun.COM> on 2005/05/27 14:31:39 UTC

[PATCH] (DERBY-276) ResultSet.relative(int row) cannot be called when the cursor is not positioned on a row.

Could anybody review this?

This patch will make relative() allowed when the cursor is before
first or after last. It will also let absolute(0) be equivalent to
beforeFirst().

This should be in accordance with JDBC 3.0 (although the tutorial and
javadoc as a bit inconsistent on relative()).

The patch will also cause the Network clinet to deviate from the
behaviour of DB2JCC.

derbyall is run with one fail which should not be related to this patch:
derbyall/derbynetclientmats/derbynetmats.fail:lang/updatableResultSet.java

derbyall run on:
Java Version:    1.5.0_03
Java Vendor:     Sun Microsystems Inc.
OS name:         Linux
OS architecture: i386
OS version:      2.4.20-31.9

Attached are the patch and the stat.
-- 
Bernt Marius Johnsen, Database Technology Group, 
Sun Microsystems, Trondheim, Norway

Re: [PATCH] (DERBY-276) ResultSet.relative(int row) cannot be called when the cursor is not positioned on a row.

Posted by "Bernt M. Johnsen" <Be...@Sun.COM>.
Comment: EmbeddedDriver relative() gives exception when the resultset
is empty, but this was not introduced by this patch:

Exception in thread "main" org.apache.derby.iapi.services.sanity.AssertFailure: ASSERT FAILED hashRowArray expected to be non-null
    at org.apache.derby.iapi.services.sanity.SanityManager.ASSERT(SanityManager.java:121)
   at org.apache.derby.impl.sql.execute.ScrollInsensitiveResultSet.getRowFromHashTable(ScrollInsensitiveResultSet.java:911)
        at org.apache.derby.impl.sql.execute.ScrollInsensitiveResultSet.getRelativeRow(ScrollInsensitiveResultSet.java:340)
     at org.apache.derby.impl.jdbc.EmbedResultSet.movePosition(EmbedResultSet.java:366)
      at org.apache.derby.impl.jdbc.EmbedResultSet.relative(EmbedResultSet.java:1840)
 at Relative.main(Relative.java:30)

Correct behvaiour would most likely be to return false (as long as
relative() should be equivalent to next()/previous().


-- 
Bernt Marius Johnsen, Database Technology Group, 
Sun Microsystems, Trondheim, Norway

Re: [PATCH] (DERBY-276) ResultSet.relative(int row) cannot be called when the cursor is not positioned on a row.

Posted by "Bernt M. Johnsen" <Be...@Sun.COM>.
>>>>>>>>>>>> Bernt M. Johnsen wrote (2005-06-13 11:17:33):
> >>>>>>>>>>>> Myrna van Lunteren wrote (2005-06-10 07:08:14):
> >  Well, I must have made a mistake of some sort - I rebuild & rerun & that 
> > test (scrollCursors2) *is* fine.
> > Apologies...
> 
> Anyway. Don't apply the patch. I have found a minor issue with the
> paych that should be fixed. I will make and test a new patch and
> attach it to the issue.

New patch attached to the issue.

-- 
Bernt Marius Johnsen, Database Technology Group, 
Sun Microsystems, Trondheim, Norway

Re: [PATCH] (DERBY-276) ResultSet.relative(int row) cannot be called when the cursor is not positioned on a row.

Posted by "Bernt M. Johnsen" <Be...@Sun.COM>.
>>>>>>>>>>>> Myrna van Lunteren wrote (2005-06-10 07:08:14):
>  Well, I must have made a mistake of some sort - I rebuild & rerun & that 
> test (scrollCursors2) *is* fine.
> Apologies...

Anyway. Don't apply the patch. I have found a minor issue with the
paych that should be fixed. I will make and test a new patch and
attach it to the issue.

-- 
Bernt Marius Johnsen, Database Technology Group, 
Sun Microsystems, Trondheim, Norway

Re: [PATCH] (DERBY-276) ResultSet.relative(int row) cannot be called when the cursor is not positioned on a row.

Posted by Myrna van Lunteren <m....@gmail.com>.
On 6/10/05, Bernt M. Johnsen <Be...@sun.com> wrote: 
> 
> >>>>>>>>>>>> Myrna van Lunteren wrote (2005-06-09 14:17:51):
> > On 6/8/05, Bernt M. Johnsen <Be...@sun.com> wrote:
> > >
> > > >>>>>>>>>>>> Bernt M. Johnsen wrote (2005-05-27 14:31:39):
> > > > Could anybody review this?
> > >
> > > Well?
> > >
> > > > This patch will make relative() allowed when the cursor is before
> > > > first or after last. It will also let absolute(0) be equivalent to
> > > > beforeFirst().
> > > [..snip..]
> >
> > Well, well!
> > I applied the patch without trouble (I feared it would be out of date
> > already :-) ), built without trouble. It all looks reasonable to me.
> > However, your patch doesn't include a modified master for 
> scrollCursors2?
> > Did you run derbyall?
> 
> The patch does include changes to scrollCursors2 and I have run derbyall
> 
> > Could this change create trouble for any existing applications? i.e. 
> What
> > if someone has programmed an app to do relative(1) in a loop, breaking 
> out
> > when the exception is hit?
> 
> That's a problem since JDBC 2.0 and 3.0 is not compatible for this
> example. I think, anyway, that it's better to be 3.0 compliant than
> 2.0 compliant.
> 
> --
> Bernt Marius Johnsen, Database Technology Group,
> Sun Microsystems, Trondheim, Norway
> 

 Well, I must have made a mistake of some sort - I rebuild & rerun & that 
test (scrollCursors2) *is* fine.
Apologies...
 Myrna

Re: [PATCH] (DERBY-276) ResultSet.relative(int row) cannot be called when the cursor is not positioned on a row.

Posted by "Bernt M. Johnsen" <Be...@sun.com>.
>>>>>>>>>>>> Myrna van Lunteren wrote (2005-06-09 14:17:51):
> On 6/8/05, Bernt M. Johnsen <Be...@sun.com> wrote: 
> > 
> > >>>>>>>>>>>> Bernt M. Johnsen wrote (2005-05-27 14:31:39):
> > > Could anybody review this?
> > 
> > Well?
> > 
> > > This patch will make relative() allowed when the cursor is before
> > > first or after last. It will also let absolute(0) be equivalent to
> > > beforeFirst().
> > [..snip..]
> 
>   Well, well! 
> I applied the patch without trouble (I feared it would be out of date 
> already :-) ), built without trouble. It all looks reasonable to me.
> However, your patch doesn't include a modified master for scrollCursors2?
> Did you run derbyall?

The patch does include changes to scrollCursors2 and I have run derbyall

>  Could this change create trouble for any existing applications? i.e. What 
> if someone has programmed an app to do relative(1) in a loop, breaking out 
> when the exception is hit?

That's a problem since JDBC 2.0 and 3.0 is not compatible for this
example. I think, anyway, that it's better to be 3.0 compliant than
2.0 compliant.

-- 
Bernt Marius Johnsen, Database Technology Group, 
Sun Microsystems, Trondheim, Norway

Re: [PATCH] (DERBY-276) ResultSet.relative(int row) cannot be called when the cursor is not positioned on a row.

Posted by Myrna van Lunteren <m....@gmail.com>.
On 6/9/05, Daniel John Debrunner <dj...@debrunners.com> wrote: 
> 
> Myrna van Lunteren wrote:
> 
> > On 6/8/05, *Bernt M. Johnsen* <Bernt.Johnsen@sun.com
> > <ma...@sun.com>> wrote:
> >
> > >>>>>>>>>>>> Bernt M. Johnsen wrote (2005-05-27 14:31:39):
> > > Could anybody review this?
> >
> > Well?
> >
> > > This patch will make relative() allowed when the cursor is before
> > > first or after last. It will also let absolute(0) be equivalent to
> > > beforeFirst().
> > [..snip..]
> >
> >
> >
> > Well, well!
> > I applied the patch without trouble (I feared it would be out of date
> > already :-) ), built without trouble. It all looks reasonable to me.
> > However, your patch doesn't include a modified master for 
> scrollCursors2?
> > Did you run derbyall?
> >
> > Could this change create trouble for any existing applications? i.e.
> > What if someone has programmed an app to do relative(1) in a loop,
> > breaking out when the exception is hit?
> 
> It could cause trouble for existing applications, but the Derby JDBC
> driver at this level is documented for users by the JDBC spec and
> javadoc from Sun.
> 
> Thus if someone wrote a Derby application against JDBC 2.1 they could
> depend on the current behaviour. More likely, given the time frames,
> they would have written an application against JDBC 3.0 and thus can not
> rely on undocumented behaviour.
> 
> Thus it's probably ok to change this, if we were paranoid we could
> change it so that Derby running in JDK 1.3 throws an exception but
> otherwise the JDBC 3.0 behaviour occurs. Not sure that is worth it.
> 
> Dan.
> 
> It doesn't seem worth it to me. But the question needed to be asked. Also, 
if we're going to have some kind of release notes this time it should get 
listed in there. (If this is going in for 10.1). 
 Myrna

Re: [PATCH] (DERBY-276) ResultSet.relative(int row) cannot be called when the cursor is not positioned on a row.

Posted by Daniel John Debrunner <dj...@debrunners.com>.
Myrna van Lunteren wrote:

> On 6/8/05, *Bernt M. Johnsen* <Bernt.Johnsen@sun.com
> <ma...@sun.com>> wrote:
> 
>     >>>>>>>>>>>> Bernt M. Johnsen wrote (2005-05-27 14:31:39):
>     > Could anybody review this?
> 
>     Well?
> 
>     > This patch will make relative() allowed when the cursor is before
>     > first or after last. It will also let absolute(0) be equivalent to
>     > beforeFirst().
>     [..snip..]
> 
>  
>  
> Well, well!
> I applied the patch without trouble (I feared it would be out of date
> already :-) ), built without trouble. It all looks reasonable to me.
> However, your patch doesn't include a modified master for scrollCursors2?
> Did you run derbyall?
>  
> Could this change create trouble for any existing applications? i.e.
> What if someone has programmed an app to do relative(1) in a loop,
> breaking out when the exception is hit?

It could cause trouble for existing applications, but the Derby JDBC
driver at this level is documented for users by the JDBC spec and
javadoc from Sun.

Thus if someone wrote a Derby application against JDBC 2.1 they could
depend on the current behaviour. More likely, given the time frames,
they would have written an application against JDBC 3.0 and thus can not
rely on undocumented behaviour.

Thus it's probably ok to change this, if we were paranoid we could
change it so that Derby running in JDK 1.3 throws an exception but
otherwise the JDBC 3.0 behaviour occurs. Not sure that is worth it.

Dan.


Re: [PATCH] (DERBY-276) ResultSet.relative(int row) cannot be called when the cursor is not positioned on a row.

Posted by "Bernt M. Johnsen" <Be...@sun.com>.
>>>>>>>>>>>> Myrna van Lunteren wrote (2005-06-09 14:20:39):
> Oh - maybe better to attach your next patch to the bug?

I should of course have done that. 

But, then, shouldn't all patches be attached to a Jira issue? Today
both mailing the patch and attaching the patch to a Jira issue is
praticed. (And if there is no Jira issue for a patch, an issue should
definitely be created).

> Myrna
> 
> 
>  On 6/9/05, Myrna van Lunteren <m....@gmail.com> wrote: 
> > 
> > On 6/8/05, Bernt M. Johnsen <Be...@sun.com> wrote: 
> > > 
> > > >>>>>>>>>>>> Bernt M. Johnsen wrote (2005-05-27 14:31:39):
> > > > Could anybody review this? 
> > > 
> > > Well?
> > > 
> > > > This patch will make relative() allowed when the cursor is before
> > > > first or after last. It will also let absolute(0) be equivalent to
> > > > beforeFirst().
> > > [..snip..]
> > 
> >   Well, well! 
> > I applied the patch without trouble (I feared it would be out of date 
> > already :-) ), built without trouble. It all looks reasonable to me.
> > However, your patch doesn't include a modified master for scrollCursors2?
> > Did you run derbyall?
> >  Could this change create trouble for any existing applications? i.e. What 
> > if someone has programmed an app to do relative(1) in a loop, breaking out 
> > when the exception is hit?
> >  Thx,
> > Myrna
> >

-- 
Bernt Marius Johnsen, Database Technology Group, 
Sun Microsystems, Trondheim, Norway

Re: [PATCH] (DERBY-276) ResultSet.relative(int row) cannot be called when the cursor is not positioned on a row.

Posted by Myrna van Lunteren <m....@gmail.com>.
Oh - maybe better to attach your next patch to the bug?
Myrna


 On 6/9/05, Myrna van Lunteren <m....@gmail.com> wrote: 
> 
> On 6/8/05, Bernt M. Johnsen <Be...@sun.com> wrote: 
> > 
> > >>>>>>>>>>>> Bernt M. Johnsen wrote (2005-05-27 14:31:39):
> > > Could anybody review this? 
> > 
> > Well?
> > 
> > > This patch will make relative() allowed when the cursor is before
> > > first or after last. It will also let absolute(0) be equivalent to
> > > beforeFirst().
> > [..snip..]
> 
>   Well, well! 
> I applied the patch without trouble (I feared it would be out of date 
> already :-) ), built without trouble. It all looks reasonable to me.
> However, your patch doesn't include a modified master for scrollCursors2?
> Did you run derbyall?
>  Could this change create trouble for any existing applications? i.e. What 
> if someone has programmed an app to do relative(1) in a loop, breaking out 
> when the exception is hit?
>  Thx,
> Myrna
>

Re: [PATCH] (DERBY-276) ResultSet.relative(int row) cannot be called when the cursor is not positioned on a row.

Posted by Myrna van Lunteren <m....@gmail.com>.
On 6/8/05, Bernt M. Johnsen <Be...@sun.com> wrote: 
> 
> >>>>>>>>>>>> Bernt M. Johnsen wrote (2005-05-27 14:31:39):
> > Could anybody review this?
> 
> Well?
> 
> > This patch will make relative() allowed when the cursor is before
> > first or after last. It will also let absolute(0) be equivalent to
> > beforeFirst().
> [..snip..]

  Well, well! 
I applied the patch without trouble (I feared it would be out of date 
already :-) ), built without trouble. It all looks reasonable to me.
However, your patch doesn't include a modified master for scrollCursors2?
Did you run derbyall?
 Could this change create trouble for any existing applications? i.e. What 
if someone has programmed an app to do relative(1) in a loop, breaking out 
when the exception is hit?
 Thx,
Myrna

Re: [PATCH] (DERBY-276) ResultSet.relative(int row) cannot be called when the cursor is not positioned on a row.

Posted by "Bernt M. Johnsen" <Be...@Sun.COM>.
>>>>>>>>>>>> Bernt M. Johnsen wrote (2005-05-27 14:31:39):
> Could anybody review this?

Well?

> This patch will make relative() allowed when the cursor is before
> first or after last. It will also let absolute(0) be equivalent to
> beforeFirst().
> 
> This should be in accordance with JDBC 3.0 (although the tutorial and
> javadoc as a bit inconsistent on relative()).
> 
> The patch will also cause the Network clinet to deviate from the
> behaviour of DB2JCC.
> 
> derbyall is run with one fail which should not be related to this patch:
> derbyall/derbynetclientmats/derbynetmats.fail:lang/updatableResultSet.java
> 
> derbyall run on:
> Java Version:    1.5.0_03
> Java Vendor:     Sun Microsystems Inc.
> OS name:         Linux
> OS architecture: i386
> OS version:      2.4.20-31.9
> 
> Attached are the patch and the stat.
> -- 
> Bernt Marius Johnsen, Database Technology Group, 
> Sun Microsystems, Trondheim, Norway

> Index: java/tools/org/apache/derby/impl/tools/ij/utilMain.java
> ===================================================================
> --- java/tools/org/apache/derby/impl/tools/ij/utilMain.java	(revision 178761)
> +++ java/tools/org/apache/derby/impl/tools/ij/utilMain.java	(working copy)
> @@ -693,12 +693,7 @@
>  			throw ijException.forwardOnlyCursor("ABSOLUTE");
>  		}
>  
> -		// 0 is an invalid value for row
> -		if (row == 0)
> -		{
> -			throw ijException.zeroInvalidForAbsolute();
> -		}
> -
> +		// 0 is an *VALID* value for row
>  		return new ijRowResult(rs, rs.absolute(row));
>  	}
>  
> Index: java/engine/org/apache/derby/impl/sql/execute/ScrollInsensitiveResultSet.java
> ===================================================================
> --- java/engine/org/apache/derby/impl/sql/execute/ScrollInsensitiveResultSet.java	(revision 178761)
> +++ java/engine/org/apache/derby/impl/sql/execute/ScrollInsensitiveResultSet.java	(working copy)
> @@ -232,10 +232,11 @@
>  			}
>  		}
>  
> -		// 0 is an invalid parameter
> +                // Absolute 0 is defined to be before first!
>  		if (row == 0)
>  		{
> -			throw StandardException.newException(SQLState.LANG_ZERO_INVALID_FOR_R_S_ABSOLUTE);
> +                    setBeforeFirstRow();
> +                    return null;
>  		}
>  
>  		if (row > 0)
> @@ -330,16 +331,14 @@
>  			}
>  		}
>  
> -		/* Throw exception if before first or after last */
> -		if (beforeFirst || afterLast)
> -		{
> -			throw StandardException.newException(SQLState.LANG_NO_CURRENT_ROW_FOR_RELATIVE);
> -		}
> -
>  		// Return the current row for 0
>  		if (row == 0)
>  		{
> +                    if (beforeFirst || afterLast) {
> +                        return null;
> +                    } else {
>  			return getRowFromHashTable(currentPosition);
> +                    }
>  		}
>  		else if (row > 0)
>  		{
> Index: java/testing/org/apache/derbyTesting/functionTests/tests/lang/scrollCursors2.java
> ===================================================================
> --- java/testing/org/apache/derbyTesting/functionTests/tests/lang/scrollCursors2.java	(revision 178761)
> +++ java/testing/org/apache/derbyTesting/functionTests/tests/lang/scrollCursors2.java	(working copy)
> @@ -613,6 +613,16 @@
>  			System.out.println("expected to be before the 1st row");
>  			passed = false;
>  		}
> +                if (rs.absolute(0))
> +                {
> +			System.out.println("absolute(0) expected to return false");
> +			passed = false;
> +                }
> +		if (! rs.isBeforeFirst())
> +		{
> +			System.out.println("still expected to be before the 1st row");
> +			passed = false;
> +		}
>  		// go to first row
>  		if (! rs.first())
>  		{
> @@ -1002,19 +1012,6 @@
>  			passed = passed && checkException(sqle, "XJ062");
>  		}
>  
> -		// absolute(0)
> -		try
> -		{
> -			rs.absolute(0);
> -			System.out.println("absolute(0) expected to fail");
> -			passed = false;
> -		}
> -		catch (SQLException sqle)
> -		{
> -			/* Check to be sure the exception is the one we expect */
> -			passed = passed && checkException(sqle, "X0X86");
> -		}
> -
>  		s_i_r.close();
>  
>  		return passed;
> Index: java/testing/org/apache/derbyTesting/functionTests/tests/lang/scrollCursors1.sql
> ===================================================================
> --- java/testing/org/apache/derbyTesting/functionTests/tests/lang/scrollCursors1.sql	(revision 178761)
> +++ java/testing/org/apache/derbyTesting/functionTests/tests/lang/scrollCursors1.sql	(working copy)
> @@ -25,19 +25,15 @@
>  close c1;
>  
>  get scroll insensitive cursor c1 as 'select * from t1';
> --- 0 is invalid value for absolute
>  absolute 0 c1;
>  close c1;
>  get scroll insensitive cursor c1 as 'select * from t1';
> --- relative is invalid when not positioned on a row
>  relative 0 c1;
>  close c1;
>  get scroll insensitive cursor c1 as 'select * from t1';
> --- relative is invalid when not positioned on a row
>  relative 2 c1;
>  close c1;
>  
> -
>  -- positive
>  
>  -- test positioning
> Index: java/testing/org/apache/derbyTesting/functionTests/master/DerbyNet/scrollCursors1.out
> ===================================================================
> --- java/testing/org/apache/derbyTesting/functionTests/master/DerbyNet/scrollCursors1.out	(revision 178761)
> +++ java/testing/org/apache/derbyTesting/functionTests/master/DerbyNet/scrollCursors1.out	(working copy)
> @@ -34,18 +34,15 @@
>  IJ ERROR: RELATIVE is not allowed on a forward only cursor.
>  ij> close c1;
>  ij> get scroll insensitive cursor c1 as 'select * from t1';
> -ij> -- 0 is invalid value for absolute
> -absolute 0 c1;
> -IJ ERROR: 0 is an invalid value for ABSOLUTE <integer> <cursorname>
> +ij> absolute 0 c1;
> +No current row
>  ij> close c1;
>  ij> get scroll insensitive cursor c1 as 'select * from t1';
> -ij> -- relative is invalid when not positioned on a row
> -relative 0 c1;
> +ij> relative 0 c1;
>  ERROR (no SQLState): Cursor is Not on a Valid Row
>  ij> close c1;
>  ij> get scroll insensitive cursor c1 as 'select * from t1';
> -ij> -- relative is invalid when not positioned on a row
> -relative 2 c1;
> +ij> relative 2 c1;
>  ERROR (no SQLState): Cursor is Not on a Valid Row
>  ij> close c1;
>  ij> -- positive
> Index: java/testing/org/apache/derbyTesting/functionTests/master/DerbyNetClient/scrollCursors1.out
> ===================================================================
> --- java/testing/org/apache/derbyTesting/functionTests/master/DerbyNetClient/scrollCursors1.out	(revision 178761)
> +++ java/testing/org/apache/derbyTesting/functionTests/master/DerbyNetClient/scrollCursors1.out	(working copy)
> @@ -34,19 +34,18 @@
>  IJ ERROR: RELATIVE is not allowed on a forward only cursor.
>  ij> close c1;
>  ij> get scroll insensitive cursor c1 as 'select * from t1';
> -ij> -- 0 is invalid value for absolute
> -absolute 0 c1;
> -IJ ERROR: 0 is an invalid value for ABSOLUTE <integer> <cursorname>
> +ij> absolute 0 c1;
> +No current row
>  ij> close c1;
>  ij> get scroll insensitive cursor c1 as 'select * from t1';
> -ij> -- relative is invalid when not positioned on a row
> -relative 0 c1;
> -ERROR (no SQLState): Cursor is Not on a Valid Row
> +ij> relative 0 c1;
> +No current row
>  ij> close c1;
>  ij> get scroll insensitive cursor c1 as 'select * from t1';
> -ij> -- relative is invalid when not positioned on a row
> -relative 2 c1;
> -ERROR (no SQLState): Cursor is Not on a Valid Row
> +ij> relative 2 c1;
> +C50 |I          
> +-----
> +c |3          
>  ij> close c1;
>  ij> -- positive
>  ----- test positioning
> Index: java/testing/org/apache/derbyTesting/functionTests/master/scrollCursors1.out
> ===================================================================
> --- java/testing/org/apache/derbyTesting/functionTests/master/scrollCursors1.out	(revision 178761)
> +++ java/testing/org/apache/derbyTesting/functionTests/master/scrollCursors1.out	(working copy)
> @@ -34,19 +34,18 @@
>  IJ ERROR: RELATIVE is not allowed on a forward only cursor.
>  ij> close c1;
>  ij> get scroll insensitive cursor c1 as 'select * from t1';
> -ij> -- 0 is invalid value for absolute
> -absolute 0 c1;
> -IJ ERROR: 0 is an invalid value for ABSOLUTE <integer> <cursorname>
> +ij> absolute 0 c1;
> +No current row
>  ij> close c1;
>  ij> get scroll insensitive cursor c1 as 'select * from t1';
> -ij> -- relative is invalid when not positioned on a row
> -relative 0 c1;
> -ERROR X0X87: ResultSet.relative(int row) cannot be called when the cursor is not positioned on a row.
> +ij> relative 0 c1;
> +No current row
>  ij> close c1;
>  ij> get scroll insensitive cursor c1 as 'select * from t1';
> -ij> -- relative is invalid when not positioned on a row
> -relative 2 c1;
> -ERROR X0X87: ResultSet.relative(int row) cannot be called when the cursor is not positioned on a row.
> +ij> relative 2 c1;
> +C50                                               |I          
> +--------------------------------------------------------------
> +c                                                 |3          
>  ij> close c1;
>  ij> -- positive
>  -- test positioning
> Index: java/client/org/apache/derby/client/am/ResultSet.java
> ===================================================================
> --- java/client/org/apache/derby/client/am/ResultSet.java	(revision 178761)
> +++ java/client/org/apache/derby/client/am/ResultSet.java	(working copy)
> @@ -1804,18 +1804,51 @@
>          // discard all previous updates when moving the cursor.
>          resetUpdatedColumns();
>  
> -        // this method may only be called when the cursor on a valid row,
> -        // not after the last row, before the first row, or on the insert row.
> -        // throw exception if result set contains no rows, because there is no current row.
> -        if (isBeforeFirstX() || isAfterLastX() || isOnInsertRow_ || resultSetContainsNoRows()) {
> +        // this method may not be called when the cursor on the insert row
> +        if (isOnInsertRow_) {
>              throw new SqlException(agent_.logWriter_, "Cursor is Not on a Valid Row");
>          }
>  
> +        // If the resultset is empty, relative(n) is a null operation
> +        if (resultSetContainsNoRows()) {
> +            isValidCursorPosition_ = false;
> +            return isValidCursorPosition_;
> +        }
> +        
> +        // relative(0) is a null-operation, but the retruned result is
> +        // dependent on wether the cursorposition is on a row or not.
>          if (rows == 0) {
> -            isValidCursorPosition_ = true;
> +            if (isBeforeFirstX() || isAfterLastX()) {
> +                isValidCursorPosition_ = false;
> +            } else {
> +                isValidCursorPosition_ = true;
> +            }
>              return isValidCursorPosition_;
>          }
>  
> +        // Handle special cases when the cursor is before first or
> +        // after last, since the following code assumes we ar on a
> +        // valid cursor
> +        if (isBeforeFirstX()) {
> +            if (rows > 0) {
> +                nextX();
> +                return relativeX(rows-1);
> +            } else {
> +                isValidCursorPosition_ = false;
> +                return isValidCursorPosition_;
> +            }
> +        }
> +        if (isAfterLastX()) {
> +            if (rows < 0) {
> +                previousX();
> +                return relativeX(rows+1);
> +            } else {
> +                isValidCursorPosition_ = false;
> +                return isValidCursorPosition_;
> +            }
> +        }
> +        // Ok, now we are on a row and ready to do some real positioning.....
> +
>          resetRowsetFlags();
>  
>          // currentAbsoluteRowNumber is used for static cursors only.

> M      java/tools/org/apache/derby/impl/tools/ij/utilMain.java
> M      java/engine/org/apache/derby/impl/sql/execute/ScrollInsensitiveResultSet.java
> M      java/testing/org/apache/derbyTesting/functionTests/tests/lang/scrollCursors2.java
> M      java/testing/org/apache/derbyTesting/functionTests/tests/lang/scrollCursors1.sql
> M      java/testing/org/apache/derbyTesting/functionTests/master/DerbyNet/scrollCursors1.out
> M      java/testing/org/apache/derbyTesting/functionTests/master/DerbyNetClient/scrollCursors1.out
> M      java/testing/org/apache/derbyTesting/functionTests/master/scrollCursors1.out
> M      java/client/org/apache/derby/client/am/ResultSet.java


-- 
Bernt Marius Johnsen, Database Technology Group, 
Sun Microsystems, Trondheim, Norway