-
-
Notifications
You must be signed in to change notification settings - Fork 82
Increase bind parameters limit #298
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@MahdiBM thanks for bringing this up. And sorry for taking so long to get back to you. Since we are testing the boundaries of Postgres here, would you mind adding an integration test, that ensures that Postgres supports what we allow?
The best way to integration test this will be a test case like this:
However we will need to extend this a bit:
|
Codecov Report
Additional details and impacted files@@ Coverage Diff @@
## main #298 +/- ##
==========================================
- Coverage 43.91% 43.90% -0.01%
==========================================
Files 115 115
Lines 9680 9677 -3
==========================================
- Hits 4251 4249 -2
+ Misses 5429 5428 -1
Flags with carried forward coverage won't be shown. Click here to find out more.
|
I corrected the equality checks and added the integration test. Please let me know if there are any problems or if any improvements can be made. |
Looking at your original test example, i think it would have been better if i asserted that the inserted rows count is what we expect after the insertion query. |
I went ahead and added a query to assert that all the rows were inserted successfully. Since all columns are As an alternative, in the Postgres documentation I read that the |
// Mac binds limit is UInt16.max which is 65535 which is 3 * 5 * 17 * 257 | ||
// Max columns limit is 1664, so we will only make 5 * 257 columns which is less | ||
// Then we will insert 3 * 17 rows | ||
// In the insertion, there will be a total of 3 * 17 * 5 * 257 == UInt16.max bindings | ||
// If the test is successful, it means Postgres supports UInt16.max bindings | ||
let columnsCount = 5 * 257 | ||
let rowsCount = 3 * 17 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Huge props to the prime factorization here! 🥰
|
||
let insertionValues = (0..<rowsCount).map { rowIndex in | ||
let indices = (0..<columnsCount).map { columnIndex -> String in | ||
"$\(rowIndex * 1_000 + columnIndex + 1)" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where is the 1_000
coming from? I would suspect this to be 1285
(5 * 257 which is the columns per row).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll need to fix that. I probably forgot about it after the first stages of writing the test function.
let insertionValues = (0..<rowsCount).map { rowIndex in | ||
let indices = (0..<columnsCount).map { columnIndex -> String in | ||
"$\(rowIndex * 1_000 + columnIndex + 1)" | ||
} | ||
return "(\(indices.joined(separator: ", ")))" | ||
}.joined(separator: ", ") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we know, we want to write exactly 65535
values, it might be easier to just reach for:
let insertionValues = (0..<UInt16.max).map { "$\(Int($0) + 1)" }.joined(separator: ", ")
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
However, doesn't seem to work since we'll be missing some parentheses.
Currently, and correctly, the values will look like ($1, $2, ...), ($x, $x+1, ...), ...
but with the simplified calculation, we'll be missing the parentheses, which postgres doesn't like.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes makes sense!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is really awesome. One question remaining
The problem
Right now PostgresNIO doesn't allow queries with bind parameters count more than Int16.max (32768).
This is despite Postgres 10+ supporting up to
(UInt16.max - 1)UInt16.max parameters (65535).For reference for Postgres 14, see https://www.postgresql.org/docs/14/postgres-fdw.html and search the page for "batch_size". I couldn't find documentation on this on lower Postgres versions, but manually tested the PR (see below).
Solution
This PR increases that limit to 65535 which is more appropriate.
Tests
I don't think there is a need for adding a test, but I changed one of the test's to reflect the changes. We'll see if there is anything I missed, when the CI runs the test.
Other than that, I've manually tested this on Postgres Docker images 10, 11, 12, 13, 14 (The currently supported-by-Postgres versions).