0
# CQL Types & Data
1
2
Comprehensive type system with encoding/decoding support for all Cassandra data types, collections, user-defined types, and utility functions. The type system handles conversion between Python objects and Cassandra's native binary format.
3
4
## Capabilities
5
6
### Base Type System
7
8
Foundation classes for the CQL type system with encoding and decoding capabilities.
9
10
```python { .api }
11
class _CassandraType:
12
"""Abstract base class for all CQL types."""
13
14
def serialize(self, value, protocol_version):
15
"""
16
Serialize a Python value to bytes for Cassandra.
17
18
Parameters:
19
- value: Python value to serialize
20
- protocol_version (int): Protocol version to use
21
22
Returns:
23
bytes: Serialized value
24
"""
25
26
def deserialize(self, byts, protocol_version):
27
"""
28
Deserialize bytes from Cassandra to a Python value.
29
30
Parameters:
31
- byts (bytes): Serialized data from Cassandra
32
- protocol_version (int): Protocol version used
33
34
Returns:
35
Python value corresponding to the CQL type
36
"""
37
38
class _UnrecognizedType(_CassandraType):
39
"""Represents an unrecognized CQL type."""
40
41
def __init__(self, name):
42
"""
43
Parameters:
44
- name (str): Name of the unrecognized type
45
"""
46
47
class _ParameterizedType(_CassandraType):
48
"""Base class for parameterized types like collections."""
49
50
def __init__(self, subtypes, names=None):
51
"""
52
Parameters:
53
- subtypes (list): List of parameter types
54
- names (list): Parameter names (for user-defined types)
55
"""
56
57
class EmptyValue:
58
"""Represents empty/null values in CQL."""
59
pass
60
```
61
62
### Primitive Types
63
64
Basic CQL data types for fundamental values.
65
66
```python { .api }
67
class BytesType(_CassandraType):
68
"""CQL blob type for binary data."""
69
70
class DecimalType(_CassandraType):
71
"""CQL decimal type for high-precision decimal numbers."""
72
73
class UUIDType(_CassandraType):
74
"""CQL uuid type for UUID values."""
75
76
class BooleanType(_CassandraType):
77
"""CQL boolean type."""
78
79
class ByteType(_CassandraType):
80
"""CQL tinyint type (8-bit signed integer)."""
81
82
class ShortType(_CassandraType):
83
"""CQL smallint type (16-bit signed integer)."""
84
85
class Int32Type(_CassandraType):
86
"""CQL int type (32-bit signed integer)."""
87
88
class LongType(_CassandraType):
89
"""CQL bigint type (64-bit signed integer)."""
90
91
class IntegerType(_CassandraType):
92
"""CQL varint type (variable-precision integer)."""
93
94
class FloatType(_CassandraType):
95
"""CQL float type (32-bit IEEE 754 floating point)."""
96
97
class DoubleType(_CassandraType):
98
"""CQL double type (64-bit IEEE 754 floating point)."""
99
100
class UTF8Type(_CassandraType):
101
"""CQL text type (UTF-8 encoded strings)."""
102
103
VarcharType = UTF8Type
104
"""Alias for UTF8Type (CQL varchar type)."""
105
106
class InetAddressType(_CassandraType):
107
"""CQL inet type for IP addresses."""
108
109
class AsciiType(_CassandraType):
110
"""CQL ascii type for ASCII-only strings."""
111
```
112
113
### Time-Related Types
114
115
Types for handling temporal data with proper timezone and precision support.
116
117
```python { .api }
118
class DateType(_CassandraType):
119
"""Base class for date-related types."""
120
121
class TimestampType(DateType):
122
"""CQL timestamp type (datetime with millisecond precision)."""
123
124
class SimpleDateType(DateType):
125
"""CQL date type (date without time component)."""
126
127
class TimeType(_CassandraType):
128
"""CQL time type (time of day with nanosecond precision)."""
129
130
class TimeUUIDType(UUIDType):
131
"""CQL timeuuid type (time-based UUID version 1)."""
132
```
133
134
### Collection Types
135
136
Types for handling CQL collections with proper nesting and type safety.
137
138
```python { .api }
139
class ListType(_ParameterizedType):
140
"""CQL list type (ordered collection)."""
141
142
def __init__(self, subtype, frozen=False):
143
"""
144
Parameters:
145
- subtype (_CassandraType): Type of list elements
146
- frozen (bool): Whether the collection is frozen
147
"""
148
149
class SetType(_ParameterizedType):
150
"""CQL set type (unordered collection of unique elements)."""
151
152
def __init__(self, subtype, frozen=False):
153
"""
154
Parameters:
155
- subtype (_CassandraType): Type of set elements
156
- frozen (bool): Whether the collection is frozen
157
"""
158
159
class MapType(_ParameterizedType):
160
"""CQL map type (key-value collection)."""
161
162
def __init__(self, key_type, value_type, frozen=False):
163
"""
164
Parameters:
165
- key_type (_CassandraType): Type of map keys
166
- value_type (_CassandraType): Type of map values
167
- frozen (bool): Whether the collection is frozen
168
"""
169
170
class TupleType(_ParameterizedType):
171
"""CQL tuple type (fixed-size collection of heterogeneous elements)."""
172
173
def __init__(self, subtypes):
174
"""
175
Parameters:
176
- subtypes (list): List of types for tuple elements
177
"""
178
```
179
180
### Complex Types
181
182
Advanced types for user-defined structures and legacy support.
183
184
```python { .api }
185
class UserType(_ParameterizedType):
186
"""CQL user-defined type (UDT)."""
187
188
def __init__(self, keyspace, typename, field_names, field_types):
189
"""
190
Parameters:
191
- keyspace (str): Keyspace containing the UDT
192
- typename (str): Name of the user-defined type
193
- field_names (list): Names of UDT fields
194
- field_types (list): Types of UDT fields
195
"""
196
197
@property
198
def keyspace(self):
199
"""str: Keyspace containing this UDT"""
200
201
@property
202
def typename(self):
203
"""str: Name of this UDT"""
204
205
@property
206
def field_names(self):
207
"""list: Names of fields in this UDT"""
208
209
@property
210
def field_types(self):
211
"""list: Types of fields in this UDT"""
212
213
class CompositeType(_CassandraType):
214
"""Legacy composite type (deprecated)."""
215
216
def __init__(self, subtypes):
217
"""
218
Parameters:
219
- subtypes (list): Component types
220
"""
221
222
class DynamicCompositeType(_CassandraType):
223
"""Legacy dynamic composite type (deprecated)."""
224
225
class CounterColumnType(_CassandraType):
226
"""CQL counter type for counter columns."""
227
228
class ReversedType(_CassandraType):
229
"""Wrapper type for reversed sort order."""
230
231
def __init__(self, subtype):
232
"""
233
Parameters:
234
- subtype (_CassandraType): The wrapped type
235
"""
236
237
class FrozenType(_CassandraType):
238
"""Wrapper type for frozen collections and UDTs."""
239
240
def __init__(self, subtype):
241
"""
242
Parameters:
243
- subtype (_CassandraType): The frozen type
244
"""
245
```
246
247
### Type Utilities
248
249
Utility functions for type lookup, parsing, and validation.
250
251
```python { .api }
252
def lookup_casstype(casstype_name):
253
"""
254
Look up a CQL type by name.
255
256
Parameters:
257
- casstype_name (str): Name of the CQL type
258
259
Returns:
260
_CassandraType: Type class for the given name
261
262
Raises:
263
- UnknownTypeException: If type name is not recognized
264
"""
265
266
def parse_casstype_args(typestring):
267
"""
268
Parse type arguments from a CQL type string.
269
270
Parameters:
271
- typestring (str): CQL type string (e.g., "map<text,int>")
272
273
Returns:
274
list: Parsed type arguments
275
"""
276
277
def is_counter_type(casstype):
278
"""
279
Check if a type is a counter type.
280
281
Parameters:
282
- casstype (_CassandraType): Type to check
283
284
Returns:
285
bool: True if the type is a counter type
286
"""
287
288
def cql_typename(casstype_name):
289
"""
290
Get the CQL name for a type.
291
292
Parameters:
293
- casstype_name (str): Internal type name
294
295
Returns:
296
str: CQL type name
297
"""
298
```
299
300
### Time and UUID Utilities
301
302
Utility functions for working with time-based data and UUIDs.
303
304
```python { .api }
305
def unix_time_from_uuid1(uuid_arg):
306
"""
307
Extract Unix timestamp from a time-based UUID (version 1).
308
309
Parameters:
310
- uuid_arg (UUID): Time-based UUID
311
312
Returns:
313
float: Unix timestamp in seconds
314
"""
315
316
def datetime_from_timestamp(timestamp):
317
"""
318
Convert a timestamp to a datetime object.
319
320
Parameters:
321
- timestamp (int or float): Unix timestamp
322
323
Returns:
324
datetime: Corresponding datetime object
325
"""
326
327
def datetime_from_uuid1(uuid_arg):
328
"""
329
Extract datetime from a time-based UUID (version 1).
330
331
Parameters:
332
- uuid_arg (UUID): Time-based UUID
333
334
Returns:
335
datetime: Datetime when the UUID was created
336
"""
337
338
def min_uuid_from_time(timestamp):
339
"""
340
Generate the minimum possible UUID for a given timestamp.
341
342
Parameters:
343
- timestamp (datetime or float): Time for UUID generation
344
345
Returns:
346
UUID: Minimum UUID for the given time
347
"""
348
349
def max_uuid_from_time(timestamp):
350
"""
351
Generate the maximum possible UUID for a given timestamp.
352
353
Parameters:
354
- timestamp (datetime or float): Time for UUID generation
355
356
Returns:
357
UUID: Maximum UUID for the given time
358
"""
359
360
def uuid_from_time(time_arg, node=None, clock_seq=None):
361
"""
362
Generate a time-based UUID (version 1).
363
364
Parameters:
365
- time_arg (datetime or float): Time for UUID generation
366
- node (int): MAC address (6 bytes) or None for random
367
- clock_seq (int): Clock sequence or None for random
368
369
Returns:
370
UUID: Generated time-based UUID
371
"""
372
```
373
374
## Usage Examples
375
376
### Working with Basic Types
377
378
```python
379
from cassandra.cqltypes import *
380
from decimal import Decimal
381
import uuid
382
from datetime import datetime, date, time
383
384
# Working with various primitive types
385
session.execute("""
386
CREATE TABLE type_examples (
387
id uuid PRIMARY KEY,
388
text_val text,
389
int_val int,
390
bigint_val bigint,
391
float_val float,
392
double_val double,
393
decimal_val decimal,
394
bool_val boolean,
395
blob_val blob,
396
inet_val inet,
397
timestamp_val timestamp,
398
date_val date,
399
time_val time,
400
timeuuid_val timeuuid
401
)
402
""")
403
404
# Insert data with various types
405
session.execute("""
406
INSERT INTO type_examples (
407
id, text_val, int_val, bigint_val, float_val, double_val,
408
decimal_val, bool_val, blob_val, inet_val, timestamp_val,
409
date_val, time_val, timeuuid_val
410
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
411
""", [
412
uuid.uuid4(),
413
'Hello, Cassandra!',
414
42,
415
9223372036854775807,
416
3.14159,
417
2.718281828459045,
418
Decimal('123.456'),
419
True,
420
b'binary data',
421
'192.168.1.1',
422
datetime.now(),
423
date.today(),
424
time(14, 30, 0),
425
uuid.uuid1() # Time-based UUID
426
])
427
```
428
429
### Working with Collections
430
431
```python
432
# Create table with collection types
433
session.execute("""
434
CREATE TABLE collection_examples (
435
id uuid PRIMARY KEY,
436
tags set<text>,
437
scores list<int>,
438
metadata map<text, text>,
439
coordinates tuple<double, double>
440
)
441
""")
442
443
# Insert collection data
444
session.execute("""
445
INSERT INTO collection_examples (id, tags, scores, metadata, coordinates)
446
VALUES (?, ?, ?, ?, ?)
447
""", [
448
uuid.uuid4(),
449
{'python', 'cassandra', 'database'}, # Set
450
[95, 87, 92, 88], # List
451
{'author': 'Alice', 'version': '1.0'}, # Map
452
(40.7128, -74.0060) # Tuple (NYC coordinates)
453
])
454
455
# Working with nested collections (requires frozen)
456
session.execute("""
457
CREATE TABLE nested_collections (
458
id uuid PRIMARY KEY,
459
matrix list<frozen<list<int>>>,
460
user_scores map<text, frozen<list<int>>>
461
)
462
""")
463
464
session.execute("""
465
INSERT INTO nested_collections (id, matrix, user_scores)
466
VALUES (?, ?, ?)
467
""", [
468
uuid.uuid4(),
469
[[1, 2, 3], [4, 5, 6], [7, 8, 9]], # List of lists
470
{
471
'alice': [95, 87, 92],
472
'bob': [88, 91, 85]
473
}
474
])
475
```
476
477
### Working with User-Defined Types
478
479
```python
480
# Create a user-defined type
481
session.execute("""
482
CREATE TYPE address (
483
street text,
484
city text,
485
state text,
486
zip_code text
487
)
488
""")
489
490
session.execute("""
491
CREATE TABLE users_with_address (
492
id uuid PRIMARY KEY,
493
name text,
494
home_address address,
495
work_address address
496
)
497
""")
498
499
# Insert data with UDT
500
from collections import namedtuple
501
502
# Create a named tuple that matches the UDT structure
503
Address = namedtuple('Address', ['street', 'city', 'state', 'zip_code'])
504
505
home = Address('123 Main St', 'Anytown', 'CA', '12345')
506
work = Address('456 Business Ave', 'Corporate City', 'NY', '67890')
507
508
session.execute("""
509
INSERT INTO users_with_address (id, name, home_address, work_address)
510
VALUES (?, ?, ?, ?)
511
""", [uuid.uuid4(), 'Alice Smith', home, work])
512
513
# Query and access UDT fields
514
result = session.execute("SELECT * FROM users_with_address")
515
for row in result:
516
print(f"User: {row.name}")
517
print(f"Home: {row.home_address.street}, {row.home_address.city}")
518
print(f"Work: {row.work_address.street}, {row.work_address.city}")
519
```
520
521
### Time and UUID Operations
522
523
```python
524
from cassandra.util import *
525
import uuid
526
from datetime import datetime, timedelta
527
528
# Generate time-based UUIDs
529
now = datetime.now()
530
uuid1_now = uuid_from_time(now)
531
uuid1_past = uuid_from_time(now - timedelta(hours=1))
532
533
print(f"UUID for now: {uuid1_now}")
534
print(f"UUID for 1 hour ago: {uuid1_past}")
535
536
# Extract time from UUID
537
extracted_time = datetime_from_uuid1(uuid1_now)
538
timestamp = unix_time_from_uuid1(uuid1_now)
539
540
print(f"Extracted datetime: {extracted_time}")
541
print(f"Unix timestamp: {timestamp}")
542
543
# Generate min/max UUIDs for time range queries
544
start_time = datetime.now() - timedelta(days=1)
545
end_time = datetime.now()
546
547
min_uuid = min_uuid_from_time(start_time)
548
max_uuid = max_uuid_from_time(end_time)
549
550
# Query using UUID time range
551
session.execute("""
552
SELECT * FROM time_series
553
WHERE id >= ? AND id <= ?
554
""", [min_uuid, max_uuid])
555
556
# Convert timestamps
557
timestamp = 1640995200 # Example timestamp
558
dt = datetime_from_timestamp(timestamp)
559
print(f"Timestamp {timestamp} -> {dt}")
560
```
561
562
### Type Introspection and Custom Handling
563
564
```python
565
from cassandra.cqltypes import lookup_casstype, parse_casstype_args
566
567
# Look up types by name
568
text_type = lookup_casstype('text')
569
int_type = lookup_casstype('int')
570
uuid_type = lookup_casstype('uuid')
571
572
print(f"Text type: {text_type}")
573
print(f"Int type: {int_type}")
574
print(f"UUID type: {uuid_type}")
575
576
# Parse complex type strings
577
map_args = parse_casstype_args('map<text,int>')
578
list_args = parse_casstype_args('list<uuid>')
579
tuple_args = parse_casstype_args('tuple<text,int,boolean>')
580
581
print(f"Map args: {map_args}")
582
print(f"List args: {list_args}")
583
print(f"Tuple args: {tuple_args}")
584
585
# Custom type handling in results
586
def custom_decimal_handler(value):
587
"""Convert Decimal to float for JSON serialization"""
588
if isinstance(value, Decimal):
589
return float(value)
590
return value
591
592
# Apply custom handling to query results
593
result = session.execute("SELECT decimal_column FROM my_table")
594
for row in result:
595
processed_value = custom_decimal_handler(row.decimal_column)
596
print(f"Processed decimal: {processed_value}")
597
```
598
599
### Working with Null and Empty Values
600
601
```python
602
from cassandra.cqltypes import EmptyValue
603
604
# Insert null/empty values
605
session.execute("""
606
INSERT INTO nullable_table (id, optional_text, optional_int)
607
VALUES (?, ?, ?)
608
""", [uuid.uuid4(), None, None]) # None becomes CQL null
609
610
# Insert using EmptyValue explicitly
611
session.execute("""
612
INSERT INTO nullable_table (id, optional_text, optional_int)
613
VALUES (?, ?, ?)
614
""", [uuid.uuid4(), EmptyValue(), EmptyValue()])
615
616
# Check for null values in results
617
result = session.execute("SELECT * FROM nullable_table")
618
for row in result:
619
if row.optional_text is None:
620
print("Text field is null")
621
if row.optional_int is None:
622
print("Int field is null")
623
```
624
625
### Type Validation and Conversion
626
627
```python
628
from cassandra.cqltypes import *
629
import uuid
630
from decimal import Decimal
631
632
def validate_and_convert_data(data, expected_types):
633
"""Validate and convert data according to expected CQL types"""
634
converted = {}
635
636
for field, value in data.items():
637
expected_type = expected_types[field]
638
639
if isinstance(expected_type, UTF8Type):
640
converted[field] = str(value) if value is not None else None
641
elif isinstance(expected_type, Int32Type):
642
converted[field] = int(value) if value is not None else None
643
elif isinstance(expected_type, UUIDType):
644
if isinstance(value, str):
645
converted[field] = uuid.UUID(value)
646
else:
647
converted[field] = value
648
elif isinstance(expected_type, DecimalType):
649
if isinstance(value, (int, float, str)):
650
converted[field] = Decimal(str(value))
651
else:
652
converted[field] = value
653
else:
654
converted[field] = value
655
656
return converted
657
658
# Example usage
659
schema = {
660
'id': UUIDType(),
661
'name': UTF8Type(),
662
'age': Int32Type(),
663
'balance': DecimalType()
664
}
665
666
raw_data = {
667
'id': 'f47ac10b-58cc-4372-a567-0e02b2c3d479',
668
'name': 'Alice',
669
'age': '30', # String that should be int
670
'balance': '123.45' # String that should be Decimal
671
}
672
673
validated_data = validate_and_convert_data(raw_data, schema)
674
print(f"Validated data: {validated_data}")
675
676
# Use validated data in query
677
session.execute("""
678
INSERT INTO users (id, name, age, balance) VALUES (?, ?, ?, ?)
679
""", [validated_data['id'], validated_data['name'],
680
validated_data['age'], validated_data['balance']])
681
```