Lindorm CQL (Cassandra Query Language) uses Data Definition Language (DDL) statements to manage keyspaces, tables, and indexes. This page covers the syntax and examples for each statement.
Statements on this page: CREATE KEYSPACE | ALTER KEYSPACE | USE | DROP KEYSPACE | CREATE TABLE | ALTER TABLE | DROP TABLE | TRUNCATE | CREATE INDEX | DROP INDEX | CREATE SEARCH INDEX | DROP SEARCH INDEX | REBUILD SEARCH INDEX | ALTER SEARCH INDEX
Overview
Lindorm CQL stores data in tables. Each table belongs to a keyspace, which groups related tables together. Keyspaces support options such as replication policy, but Lindorm CQL uses fixed default values for these settings—you cannot customize them.
Lindorm CQL supports two index types:
Secondary indexes: index one or more columns for targeted queries.
Search indexes: built on a search engine; support multi-dimensional queries, column-based sorting, and fuzzy matching.
Key concepts
Keyspace and table names
Both keyspace and table names follow the same naming rules:
Contain only letters (a–z, A–Z), digits (0–9), and underscores (
_).Cannot be blank.
Maximum length: 48 characters. This limit prevents file names that include keyspace or table names from exceeding file system limits.
Case-insensitive by default. For example,
myTableandmytablerefer to the same object. Enclose a name in double quotation marks (") to make it case-sensitive. For example,"myTable"and"mytable"refer to different objects.A table name can be qualified with its keyspace name. For example,
ks.ordersrefers to theorderstable in thekskeyspace.
Syntax notation
The syntax blocks on this page use standard BNF notation:
| Symbol | Meaning |
|---|---|
UPPERCASE | Literal keyword |
lowercase | Variable or placeholder |
[ ] | Optional element |
( ) | Grouping |
| | Or (choose one) |
* | Repeatable zero or more times |
::= | Is defined as |
Lindorm CQL vs. standard Cassandra CQL
Lindorm CQL is compatible with Cassandra CQL but has these differences:
No custom replication settings: Lindorm CQL does not support custom replication policies or replica counts. Default values (two replicas,
durable_writes = true) always apply.Data placement: In standard Cassandra CQL, the partition key alone determines which node stores a row. In Lindorm CQL, the combination of the partition key and clustering columns determines the node. Rows that share the same partition key are not guaranteed to be on the same node.
No column deletion:
ALTER TABLE ... DROPis not supported.No `STATIC` columns: the
STATICcolumn modifier is not supported.
CREATE KEYSPACE
Creates a keyspace.
Syntax
CREATE KEYSPACE [ IF NOT EXISTS ] keyspace_name WITH optionsParameters
keyspace_name: The name of the keyspace. Example:testks.options: One or both of the following:replication: A map. Specifies the replication strategy. Lindorm CQL always uses two replicas; this setting cannot be changed.durable_writes: A boolean. Specifies whether writes are durable. Alwaystrue; this setting cannot be changed.
In Lindorm, keyspaces function as logical namespaces. Replication and durable_writes settings are accepted for compatibility with standard CQL clients but have no effect—Lindorm CQL always applies its defaults.Example
CREATE KEYSPACE testks WITH replication = {'class': 'SimpleStrategy', 'replication_factor': 1};ALTER KEYSPACE
Modifies keyspace options.
Syntax
ALTER KEYSPACE keyspace_name WITH optionsParameters
Same options as CREATE KEYSPACE. Because keyspace-level options are fixed defaults in Lindorm CQL, this statement is accepted for compatibility but has no practical effect.
Example
ALTER KEYSPACE testks WITH replication = {'class': 'SimpleStrategy', 'replication_factor': 1};USE
Sets the active keyspace for the current session. Objects such as tables, user-defined types (UDTs), and functions are scoped to a keyspace.
Syntax
USE keyspace_nameParameters
keyspace_name: The keyspace to activate. Example:testks.
Example
USE testks;DROP KEYSPACE
Deletes a keyspace and all its contents permanently.
Syntax
DROP KEYSPACE [ IF EXISTS ] keyspace_nameDropping a keyspace immediately and permanently deletes it along with all its tables, UDTs, functions, and data. This action cannot be undone.
IF EXISTS: Suppresses the error if the keyspace does not exist. Without this clause, dropping a non-existent keyspace returns an error.Only the root user can drop keyspaces.
Parameters
keyspace_name: The keyspace to delete. Example:testks.
Example
DROP KEYSPACE testks;CREATE TABLE
Creates a table.
Syntax
CREATE TABLE [ IF NOT EXISTS ] table_name
'('
column_definition
( ',' column_definition )*
[ ',' PRIMARY KEY '(' primary_key ')' ]
')' [ WITH table_options ]
column_definition ::= column_name cql_type [ PRIMARY KEY ]
primary_key ::= partition_key [ ',' clustering_columns ]
partition_key ::= column_name
| '(' column_name ( ',' column_name )* ')'
clustering_columns ::= column_name ( ',' column_name )*
table_options ::= CLUSTERING ORDER BY '(' clustering_order ')' [ AND options ]
| options
clustering_order ::= column_name (ASC | DESC) ( ',' column_name (ASC | DESC) )*Description
Every table must define exactly one primary key. The primary key has two parts:
Partition key: The first element of the primary key. A single column, or multiple columns enclosed in parentheses to form a composite partition key. Every table has at least one partition key column.
Clustering columns: The remaining columns in the primary key, listed after the partition key. They define how rows are ordered within a partition. Clustering columns are optional.
Primary key examples:
| Definition | Partition key | Clustering columns |
|---|---|---|
PRIMARY KEY (a) | a | None |
PRIMARY KEY (a, b, c) | a | b, c |
PRIMARY KEY ((a, b), c) | a, b (composite) | c |
In Lindorm CQL, the combination of the partition key and clustering columns determines which node stores a row. This differs from standard Cassandra CQL, where the partition key alone determines the node. As a result, rows that share the same partition key values are not guaranteed to reside on the same node.
For example, given this table and data:
CREATE TABLE personinfo (
a int,
b int,
c int,
d int,
PRIMARY KEY ((a, b), c, d)
);SELECT * FROM personinfo;
a | b | c | d
---+---+---+---
0 | 0 | 0 | 0 -- partition: (a=0, b=0)
0 | 0 | 1 | 1 -- partition: (a=0, b=0)
0 | 1 | 2 | 2 -- partition: (a=0, b=1)
0 | 1 | 3 | 3 -- partition: (a=0, b=1)
1 | 1 | 4 | 4 -- partition: (a=1, b=1)Rows 1 and 2 share the same partition key (a=0, b=0) and are guaranteed to be in the same partition in standard Cassandra CQL. In Lindorm CQL, this guarantee does not apply.
Examples
-- Create a table with name as the primary key
CREATE TABLE tb (name text PRIMARY KEY, age int);
-- Set the default time-to-live (TTL) to 1,000 seconds
CREATE TABLE ttltb (name text PRIMARY KEY, age int) WITH default_time_to_live = 1000;
-- Use LZ4 compression (default is Snappy)
CREATE TABLE cptb (name text PRIMARY KEY, age int) WITH compression = {'class': 'LZ4Compressor'};
-- Set the hot-cold boundary to 10 seconds
CREATE TABLE hct (name text PRIMARY KEY, age int) WITH extensions = {'COLD_BOUNDARY': '10'};Supported table options
| Option | Type | Default | Description |
|---|---|---|---|
default_time_to_live | int | 0 (no expiry) | Default time-to-live for table data, in seconds. |
compression | map | Snappy | Compression algorithm for SSTables. Supported: LZ4, ZSTD, Snappy. See Compression. |
extensions | map | — | Lindorm-specific settings for storage policy, hot-cold separation, consistency, and mutability. See Extensions. |
Compression
Specify the compression algorithm using the compression option. The default algorithm is Snappy.
-- LZ4 compression
CREATE TABLE personinfo (
id int,
name text,
address text,
PRIMARY KEY (id, name)
) WITH compression = {'class': 'LZ4Compressor'};
-- ZSTD compression
CREATE TABLE personinfo (
id int,
name text,
address text,
PRIMARY KEY (id, name)
) WITH compression = {'class': 'ZstdCompressor'};
-- Snappy compression
CREATE TABLE personinfo (
id int,
name text,
address text,
PRIMARY KEY (id, name)
) WITH compression = {'class': 'SnappyCompressor'};Change the compression algorithm at any time using ALTER TABLE.Extensions
The extensions option configures Lindorm-specific table properties.
`STORAGE_POLICY`
Controls the storage tier for the table.
COLD: Store data in cold storage.DEFAULT: Store data in hot storage (default).
-- Create a cold-storage table
CREATE TABLE personinfo (name text PRIMARY KEY, age int)
WITH extensions = {'STORAGE_POLICY': 'COLD'};
-- Switch to hot storage
ALTER TABLE personinfo WITH extensions = {'STORAGE_POLICY': 'DEFAULT'};`COLD_BOUNDARY`
Enables hot-cold separation. Data older than the boundary (in seconds) moves to cold storage automatically.
Do not set STORAGE_POLICY to COLD when using COLD_BOUNDARY. If you previously set it, clear the STORAGE_POLICY setting before enabling hot-cold separation. For details, see Capacity storage.
-- Set a 1-day hot-cold boundary (86,400 seconds)
CREATE TABLE personinfo (name text PRIMARY KEY, age int)
WITH extensions = {'COLD_BOUNDARY': '86400'};
-- Change the boundary to 1,000 seconds
ALTER TABLE personinfo WITH extensions = {'COLD_BOUNDARY': '1000'};
-- Disable hot-cold separation
ALTER TABLE personinfo WITH extensions = {'COLD_BOUNDARY': ''};`CONSISTENCY_TYPE`
Sets the consistency level for tables deployed across multiple zones. Valid values: eventual, timestamp, basic, strong.
-- Create a table with strong consistency
CREATE TABLE personinfo (name text PRIMARY KEY, age int)
WITH extensions = {'CONSISTENCY_TYPE': 'strong'};
-- Change to eventual consistency
ALTER TABLE personinfo WITH extensions = {'CONSISTENCY_TYPE': 'eventual'};`MUTABILITY`
Controls row update behavior. Set this option before creating secondary indexes or search indexes.
| Value | Requires | Description |
|---|---|---|
IMMUTABLE | — | Rows cannot be updated after write. |
IMMUTABLE_ROWS | CONSISTENCY_TYPE=strong | Row-level immutability. |
MUTABLE_LATEST | CONSISTENCY_TYPE=strong | Only the latest version of each row is retained. |
MUTABLE_ALL | CONSISTENCY_TYPE=strong | All versions of each row are retained (default). |
-- Set mutability to IMMUTABLE
CREATE TABLE personinfo (name text PRIMARY KEY, age int)
WITH extensions = {'MUTABILITY': 'IMMUTABLE'};
-- Change mutability to MUTABLE_LATEST
ALTER TABLE personinfo WITH extensions = {'MUTABILITY': 'MUTABLE_LATEST'};Unsupported table options
The following standard Cassandra CQL options are not supported in Lindorm CQL:
| Option | Type | Cassandra default |
|---|---|---|
comment | string | (none) |
speculative_retry | string | 99PERCENTILE |
cdc | boolean | false |
gc_grace_seconds | int | 86400 |
bloom_filter_fp_chance | float | 0.00075 |
compaction | map | STCS |
caching | map | — |
memtable_flush_period_in_ms | int | 0 |
read_repair | string | BLOCKING |
ALTER TABLE
Modifies a table's columns or options.
Syntax
ALTER TABLE table_name alter_table_instruction
alter_table_instruction ::= ADD column_name cql_type ( ',' column_name cql_type )*
| WITH optionsDescription
Add columns: Use
ADDto add one or more columns. New columns cannot be part of the primary key, because primary keys cannot be changed after table creation.Modify options: Use
WITHto changedefault_time_to_live,compression, orextensions. TheCLUSTERING ORDERoption cannot be modified after table creation.Delete columns: Not supported in Lindorm CQL.
Example
CREATE TABLE personinfo (name text PRIMARY KEY, age int);
ALTER TABLE personinfo ADD address text;DROP TABLE
Deletes a table and all its data permanently.
Syntax
DROP TABLE [ IF EXISTS ] table_nameDropping a table immediately and permanently deletes it and all its data. This action cannot be undone.
IF EXISTS: Suppresses the error if the table does not exist. Without this clause, dropping a non-existent table returns an error.Only the root user can drop tables.
Parameters
table_name: The table to delete. Example:personinfo.
Example
DROP TABLE personinfo;TRUNCATE
Removes all rows from a table without deleting the table itself.
Syntax
TRUNCATE [ TABLE ] table_nameTRUNCATE permanently deletes all table data. The table schema is preserved. This action cannot be undone.
Only the root user can truncate tables.
Parameters
table_name: The table to truncate. Example:personinfo.
Example
TRUNCATE TABLE personinfo;CREATE INDEX
Creates a secondary index on one or more columns of a table.
Syntax
CREATE [ CUSTOM ] INDEX [ IF NOT EXISTS ] [ index_name ]
ON table_name '(' index_identifier ')'
[ USING string [ WITH OPTIONS = map_literal ] ]
index_identifier ::= column_name
| '(' column_name ')'Description
CREATE INDEX builds a secondary index on a column, enabling queries on that column. If the column already contains data, indexing happens asynchronously in the background. New data written to the column is indexed automatically.
Standard
CREATE INDEXsupports indexing a single column.To index multiple columns, use
CREATE CUSTOM INDEXwith the Lindorm secondary index class.IF NOT EXISTS: Suppresses the error if the index already exists.
Examples
-- Index a single column with an explicit index name
CREATE INDEX myindex ON personinfo (c2);
-- Index a single column without specifying an index name
CREATE INDEX ON personinfo (c2);
-- Index multiple columns using a custom index
CREATE CUSTOM INDEX myindex ON personinfo (c1, c2)
USING 'com.alibaba.lindorm.cserver.schema.index.LindormSecondaryIndex';DROP INDEX
Deletes a secondary index.
Syntax
DROP INDEX [ IF EXISTS ] index_nameIF EXISTS: Suppresses the error if the index does not exist. Without this clause, dropping a non-existent index returns an error.Optionally qualify the index name with a keyspace:
keyspace_name.index_name.
Example
DROP INDEX myindex;CREATE SEARCH INDEX
Creates a full-text search index on one or more columns of a table.
Syntax
CREATE SEARCH INDEX [ IF NOT EXISTS ] index_name ON [keyspace_name.]table_name
[ WITH COLUMNS (column1, ..., columnn) ]
| [ WITH COLUMNS (*) ]Description
Search indexes enable multi-dimensional queries, column-based sorting with ORDER BY, and fuzzy matching.
Before creating a search index, enable full-text search and Lindorm Tunnel Service (LTS). For setup instructions, see Overview.
For tables deployed across multiple zones, set CONSISTENCY_TYPE and MUTABILITY in the table's extensions before creating the index. These settings are optional for single-zone deployments.
WITH COLUMNS (column1, ..., columnn): Index the specified columns, separated by commas.WITH COLUMNS (*): Index all columns.
Example
CREATE SEARCH INDEX schidx ON personinfo WITH COLUMNS (c2, c3);DROP SEARCH INDEX
Deletes a full-text search index.
Syntax
DROP SEARCH INDEX [IF EXISTS] ON [keyspace_name.]table_name;Example
DROP SEARCH INDEX ON testks.personinfo;REBUILD SEARCH INDEX
Activates a search index and indexes historical data.
Syntax
REBUILD SEARCH INDEX [ASYNC] [IF EXISTS] ON [keyspace_name.]table_name;Description
After CREATE SEARCH INDEX, the index status is INACTIVE. Run REBUILD SEARCH INDEX to activate the index and index any existing data. Because indexing historical data can take time, use ASYNC to run the rebuild in the background.
Examples
-- Rebuild synchronously
REBUILD SEARCH INDEX ON personinfo;
-- Rebuild asynchronously
REBUILD SEARCH INDEX ASYNC ON personinfo;ALTER SEARCH INDEX
Adds or removes columns from a search index.
Syntax
ALTER SEARCH INDEX SCHEMA [IF EXISTS] ON [keyspace_name.]table_name
( ADD FIELD column_name
| DROP FIELD column_name );After modifying a search index, run
REBUILD SEARCH INDEXto reactivate it.Columns added with
ADD FIELDor removed withDROP FIELDmust exist in the source table.
Examples
-- Add a column to the search index
ALTER SEARCH INDEX SCHEMA ON personinfo ADD (c3);
-- Remove a column from the search index
ALTER SEARCH INDEX SCHEMA ON personinfo DROP (c2);