Merge pull request #175 from datastax/PYTHON-114

Add docs section for UDTs
This commit is contained in:
aholmberg
2014-08-06 08:36:43 -05:00
3 changed files with 96 additions and 0 deletions

View File

@@ -30,6 +30,9 @@ Contents
:doc:`query_paging`
Notes on paging large query results.
:doc:`user_defined_types`
Working with Cassandra 2.1's user-defined types.
:doc:`security`
An overview of the security features of the driver.
@@ -58,6 +61,7 @@ If you would like to contribute, please feel free to open a pull request.
performance
query_paging
security
user_defined_types
Indices and Tables
==================

View File

@@ -63,6 +63,8 @@ If no class is registered for a user-defined type, query results
will use a ``namedtuple`` class and data may only be inserted
though prepared statements.
See :ref:`udts` for more details.
Customizing Encoders for Non-prepared Statements
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Starting with version 2.1 of the driver, it is possible to customize

View File

@@ -0,0 +1,90 @@
.. _udts:
User Defined Types
==================
Cassandra 2.1 introduced user-defined types (UDTs). You can create a
new type through ``CREATE TYPE`` statements in CQL::
CREATE TYPE address (street text, zip int);
Version 2.1 of the python driver adds support for user-defined types.
Registering a Class to Map to a UDT
-----------------------------------
You can tell the python driver to return columns of a specific UDT as
instances of a class by registering them with your :class:`~.Cluster`
instance through :meth:`.Cluster.register_user_type`:
.. code-block:: python
cluster = Cluster(protocol_version=3)
session = cluster.connect()
session.set_keyspace('mykeyspace')
session.execute("CREATE TYPE address (street text, zipcode int)")
session.execute("CREATE TABLE users (id int PRIMARY KEY, location address)")
# create a class to map to the "address" UDT
class Address(object):
def __init__(self, street, zipcode):
self.street = street
self.zipcode = zipcode
cluster.register_user_type('mykeyspace', 'address', Address)
# insert a row using an instance of Address
session.execute("INSERT INTO users (id, location) VALUES (%s, %s)",
(0, Address("123 Main St.", 78723)))
# results will include Address instances
results = session.execute("SELECT * FROM users")
row = results[0]
print row.id, row.location.street, row.location.zipcode
Using UDTs Without Registering Them
-----------------------------------
Although it is recommended to register your types with
:meth:`.Cluster.register_user_type`, the driver gives you some options
for working with unregistered UDTS.
When you use prepared statements, the driver knows what data types to
expect for each placeholder. This allows you to pass any object you
want for a UDT, as long as it has attributes that match the field names
for the UDT:
.. code-block:: python
cluster = Cluster(protocol_version=3)
session = cluster.connect()
session.set_keyspace('mykeyspace')
session.execute("CREATE TYPE address (street text, zipcode int)")
session.execute("CREATE TABLE users (id int PRIMARY KEY, location address)")
class Foo(object):
def __init__(self, street, zipcode, otherstuff):
self.street = street
self.zipcode = zipcode
self.otherstuff = otherstuff
insert_statement = session.prepare("INSERT INTO users (id, location) VALUES (?, ?)")
# since we're using a prepared statement, we don't *have* to register
# a class to map to the UDT to insert data. The object just needs to have
# "street" and "zipcode" attributes (which Foo does):
session.execute(insert_statement, [0, Foo("123 Main St.", 78723, "some other stuff")]
# when we query data, UDT columns that don't have a class registered
# will be returned as namedtuples:
results = session.execute("SELECT * FROM users")
first_row = results[0]
address = first_row.address
print address # prints "Address(street='123 Main St.', zipcode=78723)"
street = address.street
zipcode = address.street
As shown in the code example, inserting data for UDT columns without registering
a class works fine for prepared statements. However, **you must register a
class to insert UDT columns with unprepared statements**. You can still query
UDT columns without registered classes using unprepared statements, they will
simply return ``namedtuple`` instances (just like prepared statements do).