-
Notifications
You must be signed in to change notification settings - Fork 11
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
binding: fix by-name parameter binding and enable corresponding IT #187
binding: fix by-name parameter binding and enable corresponding IT #187
Conversation
I don't get it. Rust Driver prepares the statements underneath and should be able to handle named bind markers in queries.
|
You are right. Probably, the custom |
93fdd2f
to
f7bb42a
Compare
I updated the description. |
f7bb42a
to
f9a965e
Compare
v2: rebased on #200. We don't match the specific |
f9a965e
to
9fe9d95
Compare
v3: rewritten the |
9fe9d95
to
1c117a8
Compare
1c117a8
to
0b7cf56
Compare
Rebased on master |
The PR's name is a bit misleading. It sounds like it changes only tests and enables them; instead, it fixes bugs in the driver! This should definitely be indicated in the name, and also prioritised higher. |
0b7cf56
to
e6d4f31
Compare
a7e6028
to
f36a5f3
Compare
v3.1: Applied some of the suggestions by @Lorak-mmk |
f36a5f3
to
95015a1
Compare
v4:
|
Current binding code is fairly complicated. This is because we need to match against the &[mut] self.statement in each function. To prevent this, we move the bound_values to lower layer - i.e. BoundPreparedStatement and BoundSimpleQuery. This commit does not change the logic at all. It is equivalent to the previous version.
`cass_statement_reset_paramters` should reset the name-to-index mapping used in simple queries.
I reduced mutability scope of some variables, renamed some variables so they have more descriptive names, and added some comments.
I refactored the function, so we get rid of early returns. Thanks to that, we can discover a bug: Previously, if we did not find a free index for a value with given name, we returned CASS_OK. cpp-driver returns an error in such case. Co-authored-by: Wojciech Przytuła <[email protected]>
95015a1
to
c6a1e6b
Compare
Rebased on master |
c6a1e6b
to
658f1cf
Compare
Previously, we would search for the first value in `bound_values` vector that is `Unset` to prevent overwriting the values, that were previously possibly bound via by index binding. This however, is not consistent with cpp-driver. The cpp-driver overwrites the value in such case. To allocate new index, we simply get the current size of `name_to_bound` map size. Consider following example, where user declared 2 parameters (thus bound_values.len() == 2): - by_name("foo", 5) <- bound_values[0] = 5, name_to_bound_index["foo"] = 0 - by_index(1, 19) <- bound_values[1] = 19 - by_name("bar", 13) <- previously: returns an error, because we can't find an index where value is Unset. Now: bound_values[1] = 13, name_to_bound_index["bar"] = 1 I'm adding an integration test case for analogous scenario at the end of this PR.
Previously, we would store a quoted parameter name for simple queries. This is a bug. The quotes are only introduces to decide whether the name is case sensitive for prepared statements. To fix this, I extracted the common logic of unquoting to `CassStatement::bind_cql_value_by_name`. It will pass the unquoted parameter name to methods on corresponding statement kind.
In this commit, we also adjust one of the NamedParameterTests to this change. We are going to enable this test suite in the next commit.
In these tests, we use the same bind marker (:abc) to bind values to 3 different columns. We then validate the results. There are two test cases - one for prepared statements, and other one for unprepared statements.
658f1cf
to
658ebb0
Compare
v4.1: Thanks to @Lorak-mmk I discovered a small inconsistency between cpp-rust and cpp-driver in regards to interleaving by name and by index bindings. I fixed it (commit: |
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 think I'd feel more secure about these changes with at least a number of unit tests of the BoundStatement
. There are integration tests, that's true, but for some reason I tend to trust Rust unit tests targetting the specific area more.
I think it would be possible to implement unit tests for simple queries, if I extracted another struct containing binding payload (everything from However, I don't see how we could implement unit tests for prepared statements. Does rust driver allow to somehow mock Anyhow, I'll merge it as is. There are multiple places where Rust unit tests would be useful, but currently (AFAIK) we don't have a way to mock structures from rust-driver. |
Motivation
Before this PR, binding values by name to unprepared queries was buggy:
SimpleQuery::name_to_bound_index
) - only writing to it. In result, we were not really binding by name, but rather by position, in the same order ascass_statement_bind_*
calls appeared. Thebound_values
vector was directly passed toSession::query_*
calls.CassStatement::bind_cql_value
would returnCASS_OK
when size ofSimpleQuery::name_to_bound_index
map exceeded the declared size of parameters (CassStatement::bound_values.len()
)CassStatement::bind_cql_value
This PR solves this issue, and enables another integration test suite -
NamedParametersTests
.Changes
Apart from the fixes to
CassStatement::bind_cql_value
, I also introduced a custom implementation ofSerializeRow
for unprepared queries execution. I created aSimpleQueryRowSerializer
struct which holds necessary information to perform serialization. Now, with following context:bound_values
vector - directly taken fromCassStatement::bound_values
SimpleQuery::name_to_bound_index
) - if it's non-empty, it means that we bind by names, otherwise we preserve the original order ofbound_values
.RowSerializationContext
we are able to serialize values in correct order for unprepared queries.
Pre-review checklist
[ ] I have implemented Rust unit tests for the features/changes introduced..github/workflows/build.yml
ingtest_filter
..github/workflows/cassandra.yml
ingtest_filter
.