Skip to content

AxonOps — AI-Native Control Plane for Open Source Data Platforms

Cassandra CQL Reference

This documentation provides production-grade CQL (Cassandra Query Language) reference for Apache Cassandra, covering statement syntax, behavioral contracts, failure semantics, and version-specific differences. Each statement includes guaranteed behaviors, undefined behaviors, and error handling guidance derived from source code analysis and production experience.

Cassandra Query Language (CQL) is the interface for interacting with Apache Cassandra. CQL syntax resembles SQL but operates under different semantics due to Cassandra's distributed architecture.


This CQL reference complements the Apache Cassandra official documentation by providing:

AspectCoverage
Behavioral ContractsWhat each statement guarantees vs. what is undefined behavior
Failure SemanticsError types, recovery strategies, and retry guidance
Version DifferencesBehavior changes between Cassandra 4.x and 5.x
Operational ContextProduction implications and performance considerations
Source ReferencesJIRA tickets and CEPs for implementation details

For exact grammar definitions and exhaustive syntax variants, refer to the Apache documentation.


SectionDescription
DDL CommandsSchema management: keyspaces, tables, indexes, types, functions
DML CommandsData operations: SELECT, INSERT, UPDATE, DELETE, BATCH
Data TypesNative types, collections, UDTs, vectors
FunctionsScalar functions, aggregates, UDFs
IndexingSecondary indexes, SAI, materialized views

This documentation uses syntax notation conventions adopted from PostgreSQL Documentation and consistent with the Apache Cassandra CQL specification.

ElementMeaning
KEYWORDSQL keyword (uppercase, literal)
identifierPlaceholder for user-supplied name or value (shown in italics)
[ ]Optional element
{ }Required choice—select one of the alternatives
|Separates alternatives within { } or [ ]
[, ...]Preceding element may repeat (comma-separated)
INSERT INTO *table_name* [ ( *column_name* [, ...] ) ]
VALUES ( *value* [, ...] )
[ IF NOT EXISTS ]
[ USING TTL *seconds* ]

Reading this syntax:

  • INSERT INTO and table_name are required
  • Column list ( *column_name* [, ...] ) is optional
  • VALUES (...) clause is required
  • IF NOT EXISTS clause is optional
  • USING TTL clause is optional

Placeholder terms follow SQL grammar conventions from the ISO/IEC 9075 standard:

TermDescription
keyspace_nameIdentifier for a keyspace
table_nameIdentifier for a table
column_nameIdentifier for a column
termA value: literal, bind marker (?), or function call
relationA condition expression (e.g., column = value)
operatorComparison operator (=, <, >, <=, >=, IN, CONTAINS)

CQL VersionCassandra VersionKey Features
CQL 3.01.2+Collections, compound primary keys
CQL 3.43.0+Materialized views, JSON support, UDFs
CQL 3.4.54.0+Virtual tables, audit logging, duration type
CQL 3.4.64.1+CONTAINS KEY for maps, improved aggregations
CQL 3.4.75.0+Vectors, SAI, unified compaction

CQL operators are evaluated in the following precedence order (highest to lowest):

PrecedenceOperatorDescriptionAssociativity
1()Parentheses-
2.Field access (UDT)Left-to-right
3[]Index/key access (collections)Left-to-right
4- (unary)NegationRight-to-left
5*, /, %Multiplication, division, moduloLeft-to-right
6+, -Addition, subtractionLeft-to-right
7=, !=, <, >, <=, >=ComparisonLeft-to-right
8IN, CONTAINS, CONTAINS KEYMembership-
9ANDLogical ANDLeft-to-right

No OR Operator

CQL does not support the OR operator. All WHERE conditions are implicitly ANDed. To achieve OR semantics, execute multiple queries and union results in the application.


CQL errors fall into distinct categories that indicate when and why an error occurred:

Detected during parsing. The statement is malformed.

Error CodeDescriptionExample
SyntaxExceptionInvalid CQL syntaxSELEC * FROM users

Characteristics:

  • Detected before execution
  • No side effects
  • Statement never reaches coordinator

Detected after parsing but before execution. The statement is syntactically valid but meaningless.

Error CodeDescriptionExample
InvalidRequestExceptionInvalid query semanticsSELECT * FROM nonexistent_table
UnauthorizedExceptionPermission deniedUser lacks SELECT permission
ConfigurationExceptionInvalid configurationInvalid replication factor

Characteristics:

  • Detected before execution
  • No data modifications
  • Schema validation failures

Detected during execution. The statement is valid but cannot complete.

Error CodeDescriptionRecovery
UnavailableExceptionInsufficient replicas availableRetry or reduce CL
WriteTimeoutExceptionWrite did not complete in timeVerify and retry
ReadTimeoutExceptionRead did not complete in timeRetry
ReadFailureExceptionRead failed on replica(s)Check replica health
WriteFailureExceptionWrite failed on replica(s)Check replica health
TruncateExceptionTruncate operation failedRetry
FunctionFailureExceptionUDF execution failedFix function

Characteristics:

  • Partial execution may have occurred
  • State may be undefined (especially for timeouts)
  • Retry may succeed or cause duplicates

Detected during execution. Data violates constraints.

Error CodeDescriptionExample
CASWriteUnknownResultExceptionLWT result unknownTimeout during Paxos

CQL performs implicit type coercion in specific cases:

Source TypeTarget TypeAllowed
intbigint✅ Widening
bigintint❌ Narrowing (explicit cast required)
floatdouble✅ Widening
textvarchar✅ Equivalent
asciitext✅ Widening
timestampbigint❌ Use toUnixTimestamp()
uuidtext❌ Use toString()

CQL syntax resembles SQL but operates differently due to Cassandra's distributed architecture.

AspectSQL (RDBMS)CQL (Cassandra)
Query flexibilityAny columnMust include partition key
JOINsSupportedNot supported
Schema changesMay lock tableInstant (metadata only)
WHERE clauseAny conditionsRestricted to key columns
ORDER BYAny columnClustering columns only
GROUP BYAny columnsPartition + clustering keys
SubqueriesSupportedNot supported
TransactionsACIDLWT (Paxos-based)
OFFSETSupportedNot supported

CQL requires efficient query patterns:

-- Requires partition key
SELECT * FROM users WHERE user_id = ?;
-- Range queries require partition key + clustering column
SELECT * FROM events WHERE tenant_id = ? AND event_time > ?;
-- Without partition key, requires ALLOW FILTERING (avoid in production)
SELECT * FROM users WHERE email = ? ALLOW FILTERING;

Every query executes in a distributed environment:

  1. Client connects to any node (becomes coordinator)
  2. Coordinator hashes partition key to locate replica nodes
  3. Replicas contacted based on consistency level
  4. Results merged and returned to client
Client → Coordinator → Replica Nodes → Response
└── hash(partition_key) → node selection

The primary key determines data distribution and query capabilities:

PRIMARY KEY ((partition_key), clustering_col1, clustering_col2)
└──────┬──────┘ └────────────┬────────────────┘
Data distribution Sort order within partition
ComponentDescription
Partition keyDetermines which node stores the data
Clustering columnsDefine sort order within partition
-- Simple: single partition key
CREATE TABLE users (user_id UUID PRIMARY KEY, ...);
-- Compound: partition key + clustering
CREATE TABLE messages (
user_id UUID,
sent_at TIMESTAMP,
PRIMARY KEY ((user_id), sent_at)
) WITH CLUSTERING ORDER BY (sent_at DESC);
-- Composite: multiple partition key columns
CREATE TABLE events (
tenant_id TEXT,
date DATE,
event_time TIMESTAMP,
PRIMARY KEY ((tenant_id, date), event_time)
);

Query PatternEfficiency
Partition key equalityExcellent
Partition + clustering rangeExcellent
Partition + IN (< 10 values)Good
Secondary indexPoor
ALLOW FILTERINGAvoid

TypeDescription
UUIDRandom unique identifier
TIMEUUIDTime-based UUID
TEXTUTF-8 string
INT / BIGINT32-bit / 64-bit integer
TIMESTAMPDate/time
BOOLEANTrue/false
LIST<T>Ordered collection
SET<T>Unique values
MAP<K,V>Key-value pairs

See Data Types for complete reference.


FunctionDescription
uuid()Generate random UUID
now()Current time as TIMEUUID
toTimestamp()Convert to timestamp
token()Partition key hash value
TTL()Remaining time-to-live
WRITETIME()Write timestamp

See Functions for complete reference.


DoAvoid
Include partition key in queriesALLOW FILTERING in production
Design one table per query patternUnbounded partitions
Use prepared statementsLarge IN clauses (> 20 values)
Use TTL for expiring dataSecondary indexes on high-cardinality
Keep partitions < 100MBCollections with > 100 elements