Skip to content

Commit

Permalink
Add support for binding parameters by index
Browse files Browse the repository at this point in the history
Signed-off-by: Salil Chandra <[email protected]>
  • Loading branch information
chands10 committed Dec 18, 2024
1 parent 518dd75 commit 2149a58
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 6 deletions.
13 changes: 10 additions & 3 deletions comdb2/_ccdb2.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -402,14 +402,21 @@ cdef class Handle(object):
try:
if parameters is not None:
for key, val in parameters.items():
ckey = _string_as_bytes(key)
bind_by_index = isinstance(key, int)
ckey = _string_as_bytes(key) if not bind_by_index else key
cval = _ParameterValue(val, key)
param_guards.append(ckey)
param_guards.append(cval)
if cval.list_size == -1:
rc = lib.cdb2_bind_param(self.hndl, <char*>ckey,
cval.type, cval.data, cval.size)
if bind_by_index:
rc = lib.cdb2_bind_index(self.hndl, ckey,
cval.type, cval.data, cval.size)
else:
rc = lib.cdb2_bind_param(self.hndl, <char*>ckey,
cval.type, cval.data, cval.size)
else:
if bind_by_index:
raise ValueError("Cannot bind an array by index")
# Bind Array if cval is an array
rc = lib.cdb2_bind_array(self.hndl, <char*>ckey, cval.type, cval.data, cval.list_size, cval.size)
_errchk(rc, self.hndl)
Expand Down
1 change: 1 addition & 0 deletions comdb2/_cdb2api.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ cdef extern from "cdb2api.h" nogil:
void* cdb2_column_value(cdb2_hndl_tp* hndl, int col) except +
const char* cdb2_errstr(cdb2_hndl_tp* hndl) except +
int cdb2_bind_param(cdb2_hndl_tp *hndl, const char *name, int type, const void *varaddr, int length) except +
int cdb2_bind_index(cdb2_hndl_tp *hndl, int index, int type, const void *varaddr, int length) except +
int cdb2_bind_array(cdb2_hndl_tp *hndl, const char *name, cdb2_coltype, const void *varaddr, size_t count, size_t typelen) except +
int cdb2_clearbindings(cdb2_hndl_tp *hndl) except +
int cdb2_clear_ack(cdb2_hndl_tp *hndl) except +
22 changes: 20 additions & 2 deletions comdb2/cdb2.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,13 @@
examples we make use of the `list` constructor to turn the iterable returned
by `Handle.execute` into a list of result rows.
You can also bind by index (starting from 1) instead of by name with placeholders specified using ``?``
in sequence. Note that binding an array by index is not supported. For example:
>>> query = "select 25 between ? and ?"
>>> print(list(hndl.execute(query, {1: 20, 2: 42})))
[[1]]
Types
-----
Expand Down Expand Up @@ -148,6 +155,7 @@
"ColumnType",
"ConnectionFlags",
"Value",
"IndexParameterValue",
"ParameterValue",
]

Expand All @@ -160,14 +168,17 @@
datetime.datetime,
DatetimeUs,
]
ParameterValue = Union[
IndexParameterValue = Union[
None,
int,
float,
bytes,
str,
datetime.datetime,
DatetimeUs,
]
ParameterValue = Union[
IndexParameterValue,
List[int],
List[float],
List[bytes],
Expand Down Expand Up @@ -359,7 +370,7 @@ def row_factory(
def execute(
self,
sql: str | bytes,
parameters: Mapping[str, ParameterValue] | None = None,
parameters: Mapping[str, ParameterValue] | Mapping[int, IndexParameterValue] | None = None,
*,
column_types: Sequence[ColumnType] | None = None,
) -> Handle:
Expand All @@ -383,6 +394,7 @@ def execute(
sql (str): The SQL string to execute.
parameters (Mapping[str, Any]): An optional mapping from parameter
names to the values to be bound for them.
(Mapping[int, Any]): Can also map from parameter index starting with 1 (if not array)
column_types (Sequence[int]): An optional sequence of types (values
of the `ColumnType` enumeration) which the columns of the
result set will be coerced to.
Expand All @@ -403,6 +415,12 @@ def execute(
... print(row)
[1, 2]
[2, 4]
>>> for row in hndl.execute("select 1, 2 UNION ALL select ?, ?",
... {1: 2, 2: 4}):
... print(row)
[1, 2]
[2, 4]
"""
if parameters is None:
parameters = {}
Expand Down
17 changes: 16 additions & 1 deletion tests/test_cdb2.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,12 @@ def test_binding_parameters():
hndl.execute("insert into simple(key, val) values(@k, @v)", dict(k=3, v=4))
assert hndl.get_effects()[0] == 1

hndl.execute("insert into simple(key, val) values(?, ?)", {1: 5, 2: 6})
hndl.execute("insert into simple(key, val) values(?, ?)", {2: 8, 1: 7})
assert hndl.get_effects()[0] == 1

rows = list(hndl.execute("select key, val from simple order by key"))
assert rows == [[1, 2], [3, 4]]
assert rows == [[1, 2], [3, 4], [5, 6], [7, 8]]


def test_commit_failures():
Expand Down Expand Up @@ -304,6 +308,17 @@ def test_parameter_name_in_binding_errors_noexception():
)


def test_binding_array_by_index():
hndl = cdb2.Handle("mattdb", "dev")

with pytest.raises(Exception) as exc:
hndl.execute("select * from carray(?)", {1: [1, 2, 3]})

assert exc.value.args[0] == (
"Cannot bind an array by index"
)


def test_specifying_column_types():
# GIVEN
hndl = cdb2.Handle("mattdb", "dev")
Expand Down

0 comments on commit 2149a58

Please sign in to comment.