Statement property maxRows incorrectly affects count(*) on table valued functions.
See original GitHub issueSetting statement property maxRows
results in faulty row count on table valued functions.
Below is the output from the supplied test program. The two functions numbers_tf
and numbers_itf
both return 10 rows. The former is table-valued function while the latter is an inlined version instead.
maxRows(0): select count(*) from dbo.numbers_itf() => 10 OK!
maxRows(5): select count(*) from dbo.numbers_itf() => 10 OK!
maxRows(0): select count(*) from dbo.numbers_tf() => 10 OK!
maxRows(5): select count(*) from dbo.numbers_tf() => 5 FAILED!
As can be seen setting maxRows to 5 changes the count to 5 instead of the expected 10. Clearly this is a bug. MaxRows should only affect the number of rows that the result set returns.
import java.math.BigInteger;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.concurrent.ThreadLocalRandom;
public class Main {
public static void main(String[] args) throws SQLException {
String url = "jdbc:sqlserver://localhost:1433";
String user = "sa";
String password = "Test1234!";
String database = randomName("test_");
try (
Connection c = DriverManager.getConnection(url, user, password);
) {
try {
executeUpdate(c, "create database " + database);
executeUpdate(c, "use " + database);
executeUpdate(c, "create function dbo.numbers_itf()\n" +
"returns table\n" +
"as return\n" +
" select * from (values (1), (2), (3), (4), (5), (6), (7), (8), (9), (10)) t(num)\n" +
"\n");
executeUpdate(c, "create function dbo.numbers_tf()\n" +
" returns @result table (\n" +
" num int\n" +
" )\n" +
" as\n" +
" begin\n" +
" insert into @result\n" +
" select * from (values (1), (2), (3), (4), (5), (6), (7), (8), (9), (10)) t(num)\n" +
" return\n" +
" end\n" +
"\n");
executeTest(c, 0, "select count(*) from dbo.numbers_itf()", 10);
executeTest(c, 5, "select count(*) from dbo.numbers_itf()", 10);
executeTest(c, 0, "select count(*) from dbo.numbers_tf()", 10);
executeTest(c, 5, "select count(*) from dbo.numbers_tf()", 10);
} finally {
executeUpdate(c,"use master");
executeUpdate(c, "drop database " + database);
}
}
}
private static int executeUpdate(Connection c, String sql) throws SQLException {
try (Statement s = c.createStatement()) {
return s.executeUpdate(sql);
}
}
private static void executeTest(Connection c, int maxRows, String sql, int expected) throws SQLException {
try (Statement s = c.createStatement()) {
s.setMaxRows(maxRows);
s.execute(sql);
try (ResultSet r = s.getResultSet()) {
r.next();
int actual = r.getInt(1);
System.out.format("maxRows(%d): %s => %d %s%n", s.getMaxRows(), sql, actual, (actual != expected ? "FAILED!" : "OK!"));
}
}
}
private static String randomName(String prefix) {
return prefix + (new BigInteger(40, ThreadLocalRandom.current())).toString(32);
}
}
Issue Analytics
- State:
- Created 7 years ago
- Comments:33 (24 by maintainers)
Top Results From Across the Web
Problem with Table-Valued Functions - Microsoft Q&A
I created a function to return a value. When I called the function, for unknown reason (to me, it is unknown), I did...
Read more >Table Valued Function Killing My Query Performance
Returning a Table Variable will make it a multi-statement table valued function and can be bad for performance due to the fact that...
Read more >12.5 Limits on Table Column Count and Row Size
The maximum row size for a table constrains the number (and possibly size) of columns because the total length of all columns cannot...
Read more >SQL error messages and exceptions - Oracle Help Center
In an ALTER TABLE statement, the column ' <columnName> ' has been specified as NOT NULL and either the DEFAULT clause was not...
Read more >Tables and Views — PostgREST 9.0.0 documentation
All views and tables in the exposed schema and accessible by the active database role for a request are available for querying.
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
Instead of not reading the remaining packets after reaching
maxRows
, we could try to read and discard them. This might result in performance degradation whensetMaxRows()
is used, but also make the API JDBC compliant. I am currently looking into this, will try to create a PR as well as a few benchmarks.@ulvii Good point. It’s the way how it should work (and how other jdbc drivers work). The point about the double parsing seems like an implementation detail. Why not parse it once and use the information to both count rows and create result set?