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]