Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 7 additions & 8 deletions cassandra/query.py
Original file line number Diff line number Diff line change
Expand Up @@ -486,23 +486,24 @@ def bind(self, values):
* short sequences will be extended to match bind parameters with UNSET_VALUE
* names may be omitted from a dict with UNSET_VALUE implied.

.. versionchanged:: 3.0.0

method will not throw if extra keys are present in bound dict (PYTHON-178)
"""
if values is None:
values = ()
proto_version = self.prepared_statement.protocol_version
col_meta = self.prepared_statement.column_metadata
col_meta_len = len(col_meta)
value_len = len(values)

# special case for binding dicts
if isinstance(values, dict):
unbound_values = values.copy()
values_dict = values
values = []

# sort values accordingly
for col in col_meta:
try:
values.append(unbound_values.pop(col.name))
values.append(values_dict[col.name])
except KeyError:
if proto_version >= 4:
values.append(UNSET_VALUE)
Expand All @@ -511,10 +512,8 @@ def bind(self, values):
'Column name `%s` not found in bound dict.' %
(col.name))

value_len = len(values)

if unbound_values:
raise ValueError("Unexpected arguments provided to bind(): %s" % unbound_values.keys())
value_len = len(values)
col_meta_len = len(col_meta)

if value_len > col_meta_len:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't this this check is valid anymore because the content of values is bounded by the col_meta.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is valid if incoming values is not a dict

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, yeah

raise ValueError(
Expand Down
10 changes: 5 additions & 5 deletions tests/integration/standard/test_prepared_statements.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ def _run_too_many_bind_values(self, session):
self.assertIsInstance(prepared, PreparedStatement)
self.assertRaises(ValueError, prepared.bind, (1, 2))

def test_too_many_bind_values_dicts(self):
def test_imprecise_bind_values_dicts(self):
"""
Ensure an error is thrown when attempting to bind the wrong values
with dict bindings
Expand All @@ -189,16 +189,16 @@ def test_too_many_bind_values_dicts(self):

self.assertIsInstance(prepared, PreparedStatement)

# too many values
self.assertRaises(ValueError, prepared.bind, {'k': 1, 'v': 2, 'v2': 3})
# too many values is ok - others are ignored
prepared.bind({'k': 1, 'v': 2, 'v2': 3})

# right number, but one does not belong
if PROTOCOL_VERSION < 4:
# pre v4, the driver bails with key error when 'v' is found missing
self.assertRaises(KeyError, prepared.bind, {'k': 1, 'v2': 3})
else:
# post v4, the driver uses UNSET_VALUE for 'v' and bails when 'v2' is unbound
self.assertRaises(ValueError, prepared.bind, {'k': 1, 'v2': 3})
# post v4, the driver uses UNSET_VALUE for 'v' and 'v2' is ignored
prepared.bind({'k': 1, 'v2': 3})

# also catch too few variables with dicts
self.assertIsInstance(prepared, PreparedStatement)
Expand Down
6 changes: 4 additions & 2 deletions tests/unit/test_parameter_binding.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
from cassandra.util import OrderedDict

from six.moves import xrange
import six


class ParamBindingTest(unittest.TestCase):
Expand Down Expand Up @@ -147,8 +148,9 @@ def test_dict_missing_routing_key(self):
def test_missing_value(self):
self.assertRaises(KeyError, self.bound.bind, {'rk0': 0, 'rk1': 0, 'ck0': 0})

def test_dict_extra_value(self):
self.assertRaises(ValueError, self.bound.bind, {'rk0': 0, 'rk1': 0, 'ck0': 0, 'v0': 0, 'should_not_be_here': 123})
def test_extra_value(self):
self.bound.bind({'rk0': 0, 'rk1': 0, 'ck0': 0, 'v0': 0, 'should_not_be_here': 123}) # okay to have extra keys in dict
self.assertEqual(self.bound.values, [six.b('\x00') * 4] * 4) # four encoded zeros
self.assertRaises(ValueError, self.bound.bind, (0, 0, 0, 0, 123))

def test_values_none(self):
Expand Down