blue-yonder / turbodbc

Turbodbc is a Python module to access relational databases via the Open Database Connectivity (ODBC) interface. The module complies with the Python Database API Specification 2.0.
http://turbodbc.readthedocs.io/en/latest
MIT License
614 stars 86 forks source link

Using dot notation on returned rows #38

Open keitherskine opened 7 years ago

keitherskine commented 7 years ago

It would be handy if the cursor's fetch() functions returned something like named tuples so that the fields can be accessed using dot notation rather than having to refer to them by index.

cursor.execute("select first_name, last_name from person")
row = cursor.fetchone()
print('Hello {}'.format(row[0]))          # this currently works
print('Hello {}'.format(row.first_name))  # this is not yet possible
MathMagique commented 7 years ago

I agree that this would be a convenient addition. I am not sure how this would impact performance. Also, I would have to create new named tuple types for each result set; this could be bad for applications that do lots and lots of small queries. I'll have to think about this one.

keitherskine commented 7 years ago

Perhaps this could be a flag in the connect() function, for example:

conn = turbodbc.connect(dsn='...', row_type=turbodbc.TUPLE)  # rows would be returned as tuples
conn = turbodbc.connect(dsn='...', row_type=turbodbc.LIST)  # rows would be returned as lists
conn = turbodbc.connect(dsn='...', row_type=turbodbc.ORDERED_DICT)  # rows would be returned as OrderedDicts
conn = turbodbc.connect(dsn='...', row_type=turbodbc.NAMED_TUPLE)  # rows would be returned as NamedTuples

Then, any cursors generated from that connection would inherit the row type, but that too could be overridden:

conn = turbodbc.connect(dsn='...', row_type=turbodbc.LIST)
crsr1 = conn.cursor()  # rows from this cursor would be returned as lists
crsr2 = conn.cursor(row_type=turbodbc.ORDERED_DICT)  # rows from this cursor would be returned as OrderedDicts

Furthermore, perhaps the user could provide a class to the row type parameter that would do any custom transformation. The class would just have to have a constructor method, say make():

class MyClass():
    def make(seq):
        return list(seq)  # trivial example to always return a list

conn = turbodbc.connect(dsn='...', row_type=MyClass)