postgresql-jdbc.git / summary / log / commit / refs

commit    282536bbfedc015f6fadb375521d3ef93f9f4e67
Author:   Alexis Meneses <alexismeneses@users.noreply.github.com>
Date:     Mon Jun 01 20:18:29 2015 +0000

    Fix: ResultSet positioning methods in some particular cases
    
    Returned values of isFirst/isLast/isBeforeFirst/isAfterLast are correct event when setting a
    non-zero fetchsize or when working with an empty resultset.
    
    Bug reported by Luis Michel Pinta Da Costa in
    http://www.postgresql.org/message-id/flat/OFF3D569C5.9BC4DC3D-ONC1257E1B.0045CF5C-C1257E1B.00472393@retraite.lan


org/postgresql/jdbc2/AbstractJdbc2ResultSet.java | 12 ++- org/postgresql/test/jdbc2/CursorFetchTest.java | 113 +++++++++++++++++++++++ 2 files changed, 124 insertions(+), 1 deletion(-) diff --git a/org/postgresql/jdbc2/AbstractJdbc2ResultSet.java b/org/postgresql/jdbc2/AbstractJdbc2ResultSet.java index dd4f8940..3d7902e4 100644 --- a/org/postgresql/jdbc2/AbstractJdbc2ResultSet.java +++ b/org/postgresql/jdbc2/AbstractJdbc2ResultSet.java @@ -645,7 +645,11 @@ public abstract class AbstractJdbc2ResultSet implements BaseResultSet, org.postg return false; final int rows_size = rows.size(); - return (current_row >= rows_size && rows_size > 0); + if (row_offset + rows_size == 0) + { + return false; + } + return (current_row >= rows_size); } @@ -665,6 +669,12 @@ public abstract class AbstractJdbc2ResultSet implements BaseResultSet, org.postg if (onInsertRow) return false; + final int rows_size = rows.size(); + if (row_offset + rows_size == 0) + { + return false; + } + return ((row_offset + current_row) == 0); } diff --git a/org/postgresql/test/jdbc2/CursorFetchTest.java b/org/postgresql/test/jdbc2/CursorFetchTest.java index 3fc37564..af96033d 100644 --- a/org/postgresql/test/jdbc2/CursorFetchTest.java +++ b/org/postgresql/test/jdbc2/CursorFetchTest.java @@ -429,4 +429,117 @@ public class CursorFetchTest extends TestCase assertEquals(3, count); } + // isLast() may change the results of other positioning methods as it has to + // buffer some more results. This tests avoid using it so as to test robustness + // other positioning methods + public void testRowResultPositioningWithoutIsLast() throws Exception + { + String msg; + + int rowCount = 4; + createRows(rowCount); + + int[] sizes = { 1, 2, 3, 4, 5 }; + for (int i = 0; i < sizes.length; ++i) + { + Statement stmt = con.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE); + stmt.setFetchSize(sizes[i]); + + ResultSet rs = stmt.executeQuery("select * from test_fetch order by value"); + msg = "before-first row positioning error with fetchsize=" + sizes[i]; + assertTrue(msg, rs.isBeforeFirst()); + assertTrue(msg, !rs.isAfterLast()); + assertTrue(msg, !rs.isFirst()); + + for (int j = 0; j < rowCount; ++j) + { + msg = "row " + j + " positioning error with fetchsize=" + sizes[i]; + assertTrue(msg, rs.next()); + assertEquals(msg, j, rs.getInt(1)); + + assertTrue(msg, !rs.isBeforeFirst()); + assertTrue(msg, !rs.isAfterLast()); + if (j == 0) + assertTrue(msg, rs.isFirst()); + else + assertTrue(msg, !rs.isFirst()); + } + + msg = "after-last row positioning error with fetchsize=" + sizes[i]; + assertTrue(msg, !rs.next()); + + assertTrue(msg, !rs.isBeforeFirst()); + assertTrue(msg, rs.isAfterLast()); + assertTrue(msg, !rs.isFirst()); + assertTrue(msg, !rs.isLast()); + + rs.close(); + stmt.close(); + } + } + + + // Empty resultsets require all row positioning methods to return false + public void testNoRowResultPositioning() throws Exception + { + String msg; + + int[] sizes = { 0, 1, 50, 100 }; + for (int i = 0; i < sizes.length; ++i) + { + Statement stmt = con.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE); + stmt.setFetchSize(sizes[i]); + + ResultSet rs = stmt.executeQuery("select * from test_fetch order by value"); + msg = "no row (empty resultset) positioning error with fetchsize=" + sizes[i]; + assertTrue(msg, !rs.isBeforeFirst()); + assertTrue(msg, !rs.isAfterLast()); + assertTrue(msg, !rs.isFirst()); + assertTrue(msg, !rs.isLast()); + + assertTrue(msg, !rs.next()); + assertTrue(msg, !rs.isBeforeFirst()); + assertTrue(msg, !rs.isAfterLast()); + assertTrue(msg, !rs.isFirst()); + assertTrue(msg, !rs.isLast()); + + rs.close(); + stmt.close(); + } + } + + // Empty resultsets require all row positioning methods to return false + public void testScrollableNoRowResultPositioning() throws Exception + { + String msg; + + int[] sizes = { 0, 1, 50, 100 }; + for (int i = 0; i < sizes.length; ++i) + { + Statement stmt = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE); + stmt.setFetchSize(sizes[i]); + + ResultSet rs = stmt.executeQuery("select * from test_fetch order by value"); + msg = "no row (empty resultset) positioning error with fetchsize=" + sizes[i]; + assertTrue(msg, !rs.isBeforeFirst()); + assertTrue(msg, !rs.isAfterLast()); + assertTrue(msg, !rs.isFirst()); + assertTrue(msg, !rs.isLast()); + + assertTrue(msg, !rs.first()); + assertTrue(msg, !rs.isBeforeFirst()); + assertTrue(msg, !rs.isAfterLast()); + assertTrue(msg, !rs.isFirst()); + assertTrue(msg, !rs.isLast()); + + assertTrue(msg, !rs.next()); + assertTrue(msg, !rs.isBeforeFirst()); + assertTrue(msg, !rs.isAfterLast()); + assertTrue(msg, !rs.isFirst()); + assertTrue(msg, !rs.isLast()); + + rs.close(); + stmt.close(); + } + } } [parent: 7b500209a297]