Skip to content

Commit 61a7eae

Browse files
authored
Make SqlRow support [] operator (#478)
This is mainly an enhancement for easier access for columns in the row. Now, the `SqlRow` implements the `__getitem__` magic method. Implementation of the method simply performs a type check and calls `get_object_with_index` if the type of the passed parameter is an integer type. For any other type, it calls `get_object`. Hence, it will throw for any other type than `int` or `str`. Also, put a piece of information about this new way to the documentation & code samples.
1 parent b0da06a commit 61a7eae

File tree

4 files changed

+59
-3
lines changed

4 files changed

+59
-3
lines changed

docs/using_python_client_with_hazelcast_imdg.rst

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1567,6 +1567,8 @@ The following code prints names of the employees whose age is less than 30:
15671567
15681568
for row in result:
15691569
name = row.get_object("name")
1570+
# or, you can use the [] operator
1571+
# name = row["name"]
15701572
print(name)
15711573
15721574
@@ -1681,7 +1683,10 @@ it:
16811683
16821684
with client.sql.execute(select_query) as result:
16831685
for row in result:
1684-
print(row.get_object("name"))
1686+
name = row.get_object("name")
1687+
# or, you can use the [] operator
1688+
# name = row["name"]
1689+
print(name)
16851690
16861691
16871692
**"SELECT *" Queries**

examples/sql/sql_example.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,11 @@ def __repr__(self):
6767
# Get the object with the column index
6868
is_active = row.get_object_with_index(is_active_index)
6969

70+
# Rows can also be used similar to lists
71+
# with integer column indexes
72+
73+
# is_active = row[is_active_index]
74+
7075
print(name, age, is_active)
7176

7277
# Construct a statement object to control the properties of the query
@@ -86,13 +91,20 @@ def __repr__(self):
8691
key = row.get_object("__key")
8792
age = row.get_object("age")
8893

94+
# Rows can also be used similar to dictionaries
95+
# with string column names
96+
97+
# key = row["__key"]
98+
# age = row["age"]
99+
89100
print(key, age)
90101

91102
# Parameters can be passed directly in the basic execution syntax
92103
result = client.sql.execute("SELECT this FROM customers WHERE age > ? AND age < ?", 30, 40)
93104

94105
for row in result:
95-
customer = row.get_object("this")
106+
# Access columns with [] operator
107+
customer = row["this"]
96108
print(customer)
97109

98110
# Query can be closed explicitly

hazelcast/sql.py

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -463,7 +463,24 @@ def __repr__(self):
463463

464464

465465
class SqlRow(object):
466-
"""One of the rows of an SQL query result."""
466+
"""One of the rows of an SQL query result.
467+
468+
The columns of the rows can be retrieved using
469+
470+
- :func:`get_object` with column name.
471+
- :func:`get_object_with_index` with column index.
472+
473+
Apart from these methods, the row objects can also be treated as a ``dict``
474+
or ``list`` and columns can be retrieved using the ``[]`` operator.
475+
476+
If an integer value is passed to the ``[]`` operator, it will implicitly
477+
call the :func:`get_object_with_index` and return the result.
478+
479+
For any other type passed into the the ``[]`` operator, :func:`get_object`
480+
will be called. Note that, :func:`get_object` expects ``str`` values.
481+
Hence, the ``[]`` operator will raise error for any type other than integer
482+
and string.
483+
"""
467484

468485
__slots__ = ("_row_metadata", "_row", "_deserialize_fn")
469486

@@ -551,6 +568,12 @@ def metadata(self):
551568
"""SqlRowMetadata: The row metadata."""
552569
return self._row_metadata
553570

571+
def __getitem__(self, item):
572+
if isinstance(item, six.integer_types):
573+
return self.get_object_with_index(item)
574+
575+
return self.get_object(item)
576+
554577
def __repr__(self):
555578
return "[%s]" % ", ".join(
556579
"%s %s=%s"

tests/integration/backward_compatible/sql_test.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,22 @@ def test_lazy_deserialization(self):
572572
with self.assertRaises(HazelcastSqlError):
573573
row.get_object("this")
574574

575+
def test_rows_as_dict_or_list(self):
576+
skip_if_client_version_older_than(self, "5.0")
577+
578+
self._create_mapping("VARCHAR")
579+
entry_count = 20
580+
581+
def value_factory(v):
582+
return "value-%s" % v
583+
584+
self._populate_map(entry_count, value_factory)
585+
586+
expected = [(i, value_factory(i)) for i in range(entry_count)]
587+
with self.client.sql.execute('SELECT __key, this FROM "%s"' % self.map_name) as result:
588+
# Verify that both row[integer] and row[string] works
589+
six.assertCountEqual(self, expected, [(row[0], row["this"]) for row in result])
590+
575591

576592
@unittest.skipIf(
577593
compare_client_version("4.2") < 0, "Tests the features added in 4.2 version of the client"

0 commit comments

Comments
 (0)