Skip to content
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

Add iterator support for DbObject with collection content #314

Closed
n8falke opened this issue Mar 21, 2024 · 7 comments
Closed

Add iterator support for DbObject with collection content #314

n8falke opened this issue Mar 21, 2024 · 7 comments
Labels
enhancement New feature or request patch available

Comments

@n8falke
Copy link

n8falke commented Mar 21, 2024

Allowing the usage of DbObject directly in example for-loops, map() or set()-constructor without aslist() to list conversion would simplify usage of from queries returned collections.

Example implementation:

class DbObject:
    ...
    def __iter__(self):
        """
        Return generator iterating over each of the collection’s elements in
        index order.
        """
        self._ensure_is_collection()
        ix = self._impl.get_first_index()
        while ix is not None:
            yield(self._impl.get_element_by_index(ix))
            ix = self._impl.get_next_index(ix)

Example usage with PL/SQL:

...
conn = oracledb.connect(...)
out_type = con.gettype("SYS.DBMS_SQL.VARCHAR2_TABLE")
cur = con.cursor()
out_var = cur.var(out_type, 10)
cur.execute("""
    DECLARE
        tbl SYS.DBMS_SQL.VARCHAR2_TABLE;
    BEGIN
        tbl(0) := 'red';
        tbl(1) := 'blue';
        tbl(2) := 'green';
        :out := tbl;
    END;""", out=out_var )
colors = set(out_var.getvalue())
print(colors)
cur.close()

Example with SELECT:

Prepare DB:

CREATE OR REPLACE TYPE STR_TABLE_T AS TABLE OF VARCHAR2(4000);

Python source:

...
cur.execute("SELECT STR_TABLE_T('first', 'second', 'third') FROM dual")
row = cur.fetchone()
for res in row[0]:
    print(res)
...

With table data a use case could be:

SELECT name, CAST(COLLECT(value) AS STR_TABLE_T) AS entries
  FROM name_value_tab
 GROUP BY name
@n8falke n8falke added the enhancement New feature or request label Mar 21, 2024
@anthony-tuininga
Copy link
Member

Thanks for your clear description of what you would like to see. It seems quite reasonable to me!

@anthony-tuininga
Copy link
Member

I made the suggested change and added some tests. The aslist() method now simply uses the generator instead of duplicating the code! If you are able to build from source you can verify that it works for you, too.

@n8falke
Copy link
Author

n8falke commented Mar 25, 2024

Thank you for the very fast reply and change.

Yes, it works perfect with for, *-unpacking, collection-constructors, map(...).

You are right, the proposed function was nearly a copy of aslist() and your solution is much cleaner code.

@n8falke
Copy link
Author

n8falke commented Mar 25, 2024

Not important and probably the wrong place to ask: Do you perhaps know how I can change the returned type to int/decimal from DbObject with "TABLE OF NUMBER"?

@anthony-tuininga
Copy link
Member

There is no way to do so, currently. The driver looks at the metadata and returns either int or float depending on whether the metadata says only integers are allowed or not. If you want the ability to return decimals you will need to log another enhancement request.

@n8falke
Copy link
Author

n8falke commented Mar 28, 2024

Thank you for that hint. Controlling the type by definition works for me.

Took me while to understand the mechanism:

Column or collection defined with type Data-value Python resulting type
NUMBER or TABLE OF NUMBER 42 int
NUMBER or TABLE OF NUMBER 123.4 float
NUMBER(9) or TABLE OF NUMBER(9) 42 int
NUMBER(15,4) or TABLE OF NUMBER(15,4) 42 float
NUMBER(15,4) or TABLE OF NUMBER(15,4) 123.4 float
for all NULL NoneType

@anthony-tuininga
Copy link
Member

This was included in version 2.2.0 which was just released.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request patch available
Projects
None yet
Development

No branches or pull requests

2 participants