@ -399,7 +399,7 @@ link:#createKeyspaceStmt[`CREATE KEYSPACE`] statement.
_Syntax:_
[source,bnf]
::= DROP KEYSPACE ( IF EXISTS )?
::= DROP KEYSPACE [ IF EXISTS ]
_Sample:_
@ -1088,10 +1088,10 @@ _Syntax:_
[source,bnf]
----
::= ALTER TYPE (IF EXISTS)?
::= ALTER TYPE [ IF EXISTS ]
::= ADD (IF NOT EXISTS)?
| RENAME (IF EXISTS)? TO ( AND TO )*
::= ADD [ IF NOT EXISTS ]
| RENAME [ IF EXISTS ] TO ( AND TO )*
----
_Sample:_
@ -1112,7 +1112,7 @@ type of existing fields. If the type does not exist, the statement will return a
_Syntax:_
[source,bnf]
::= DROP TYPE ( IF EXISTS )?
::= DROP TYPE [ IF EXISTS ]
The `DROP TYPE` statement results in the immediate, irreversible removal
of a type. Attempting to drop a type that is still in use by another
@ -1809,632 +1809,7 @@ doing'', you can force the execution of this query by using
SELECT firstname, lastname FROM users WHERE birth_year = 1981 AND
country = 'FR' ALLOW FILTERING;
[[databaseRoles]]
=== Database Roles
[[createRoleStmt]]
==== CREATE ROLE
_Syntax:_
[source,bnf]
include::cassandra:example$BNF/create_role_statement.bnf[]
_Sample:_
[source,sql]
include::cassandra:example$CQL/create_role.cql[]
By default roles do not possess `LOGIN` privileges or `SUPERUSER`
status.
link:#permissions[Permissions] on database resources are granted to
roles; types of resources include keyspaces, tables, functions and roles
themselves. Roles may be granted to other roles to create hierarchical
permissions structures; in these hierarchies, permissions and
`SUPERUSER` status are inherited, but the `LOGIN` privilege is not.
If a role has the `LOGIN` privilege, clients may identify as that role
when connecting. For the duration of that connection, the client will
acquire any roles and privileges granted to that role.
Only a client with the `CREATE` permission on the database roles
resource may issue `CREATE ROLE` requests (see the
link:#permissions[relevant section] below), unless the client is a
`SUPERUSER`. Role management in Cassandra is pluggable and custom
implementations may support only a subset of the listed options.
Role names should be quoted if they contain non-alphanumeric characters.
[[createRolePwd]]
===== Setting credentials for internal authentication
Use the `WITH PASSWORD` clause to set a password for internal
authentication, enclosing the password in single quotation marks. +
If internal authentication has not been set up or the role does not have
`LOGIN` privileges, the `WITH PASSWORD` clause is not necessary.
[[createRoleConditional]]
===== Creating a role conditionally
Attempting to create an existing role results in an invalid query
condition unless the `IF NOT EXISTS` option is used. If the option is
used and the role exists, the statement is a no-op.
[source,sql]
include::cassandra:example$CQL/create_role_ifnotexists.cql[]
[[alterRoleStmt]]
==== ALTER ROLE
_Syntax:_
[source,bnf]
include::cassandra:example$BNF/alter_role_statement.bnf[]
_Sample:_
[source,sql]
include::cassandra:example$CQL/alter_role.cql[]
If the role does not exist, the statement will return an error, unless `IF EXISTS` is used in which case the operation is a no-op.
Conditions on executing `ALTER ROLE` statements:
* A client must have `SUPERUSER` status to alter the `SUPERUSER` status
of another role
* A client cannot alter the `SUPERUSER` status of any role it currently
holds
* A client can only modify certain properties of the role with which it
identified at login (e.g. `PASSWORD`)
* To modify properties of a role, the client must be granted `ALTER`
link:#permissions[permission] on that role
[[dropRoleStmt]]
==== DROP ROLE
_Syntax:_
[source,bnf]
include::cassandra:example$BNF/drop_role_statement.bnf[]
_Sample:_
[source,sql]
----
DROP ROLE alice;
DROP ROLE IF EXISTS bob;
----
`DROP ROLE` requires the client to have `DROP`
link:#permissions[permission] on the role in question. In addition,
client may not `DROP` the role with which it identified at login.
Finally, only a client with `SUPERUSER` status may `DROP` another
`SUPERUSER` role. +
Attempting to drop a role which does not exist results in an invalid
query condition unless the `IF EXISTS` option is used. If the option is
used and the role does not exist the statement is a no-op.
[[grantRoleStmt]]
==== GRANT ROLE
_Syntax:_
[source,bnf]
include::cassandra:example$BNF/grant_role_statement.bnf[]
_Sample:_
[source,sql]
include::cassandra:example$CQL/grant_role.cql[]
This statement grants the `report_writer` role to `alice`. Any
permissions granted to `report_writer` are also acquired by `alice`. +
Roles are modelled as a directed acyclic graph, so circular grants are
not permitted. The following examples result in error conditions:
[source,sql]
----
GRANT role_a TO role_b;
GRANT role_b TO role_a;
----
[source,sql]
----
GRANT role_a TO role_b;
GRANT role_b TO role_c;
GRANT role_c TO role_a;
----
[[revokeRoleStmt]]
==== REVOKE ROLE
_Syntax:_
[source,bnf]
include::cassandra:example$BNF/revoke_role_statement.bnf[]
_Sample:_
[source,sql]
include::cassandra:example$CQL/revoke_role.cql[]
This statement revokes the `report_writer` role from `alice`. Any
permissions that `alice` has acquired via the `report_writer` role are
also revoked.
[[listRolesStmt]]
===== LIST ROLES
_Syntax:_
[source,bnf]
include::cassandra:example$BNF/list_roles_statement.bnf[]
_Sample:_
[source,sql]
include::cassandra:example$CQL/list_roles.cql[]
Return all known roles in the system, this requires `DESCRIBE`
permission on the database roles resource.
[source,sql]
include::cassandra:example$CQL/list_roles_of.cql[]
Enumerate all roles granted to `alice`, including those transitively
acquired.
[source,sql]
include::cassandra:example$CQL/list_roles_nonrecursive.cql[]
List all roles directly granted to `bob`.
[[createUserStmt]]
==== CREATE USER
Prior to the introduction of roles in Cassandra 2.2, authentication and
authorization were based around the concept of a `USER`. For backward
compatibility, the legacy syntax has been preserved with `USER` centric
statements becoming synonyms for the `ROLE` based equivalents.
_Syntax:_
[source,bnf]
include::cassandra:example$BNF/create_user_statement.bnf[]
_Sample:_
[source,sql]
include::cassandra:example$CQL/create_user.cql[]
`CREATE USER` is equivalent to `CREATE ROLE` where the `LOGIN` option is
`true`. So, the following pairs of statements are equivalent:
[source,sql]
----
include::cassandra:example$CQL/create_user_role.cql[]
----
[[alterUserStmt]]
==== ALTER USER
_Syntax:_
[source,bnf]
include::cassandra:example$BNF/alter_user_statement.bnf[]
_Sample:_
[source,sql]
include::cassandra:example$CQL/alter_user.cql[]
If the user does not exist, the statement will return an error, unless `IF EXISTS` is used in which case the operation is a no-op.
[[dropUserStmt]]
==== DROP USER
_Syntax:_
[source,bnf]
include::cassandra:example$BNF/drop_user_statement.bnf[]
_Sample:_
[source,sql]
----
DROP USER alice;
DROP USER IF EXISTS bob;
----
[[listUsersStmt]]
==== LIST USERS
_Syntax:_
[source,bnf]
include::cassandra:example$BNF/list_users_statement.bnf[]
_Sample:_
[source,sql]
LIST USERS;
This statement is equivalent to
[source,sql]
LIST ROLES;
but only roles with the `LOGIN` privilege are included in the output.
[[databaseIdentity]]
=== Database Identities
[[AddIdentityStmt]]
==== ADD IDENTITY
_Syntax:_
[source,bnf]
::= ADD IDENTITY ( IF NOT EXISTS )? TO ROLE ?
_Sample:_
[source,sql]
ADD IDENTITY 'id1' TO ROLE 'role1';
Only a user with privileges to add roles can add identities
Role names & Identity names should be quoted if they contain non-alphanumeric characters.
[[addIdentityConditional]]
===== Adding an identity conditionally
Attempting to add an existing identity results in an invalid query
condition unless the `IF NOT EXISTS` option is used. If the option is
used and the identity exists, the statement is a no-op.
[source,sql]
ADD IDENTITY IF NOT EXISTS 'id1' TO ROLE 'role1';
[[dropIdentityStmt]]
==== DROP IDENTITY
_Syntax:_
[source,bnf]
::= DROP IDENTITY ( IF EXISTS )?
_Sample:_
[source,sql]
----
DROP IDENTITY 'testIdentity';
DROP IDENTITY IF EXISTS 'testIdentity';
----
Only a user with privileges to drop roles can remove identities
Attempting to drop an Identity which does not exist results in an invalid
query condition unless the `IF EXISTS` option is used. If the option is
used and the identity does not exist the statement is a no-op.
[[dataControl]]
=== Data Control
==== Permissions
Permissions on resources are granted to roles; there are several
types of resources in Cassandra and each type is modelled
hierarchically:
* The hierarchy of Data resources, Keyspaces and Tables has the
structure `ALL KEYSPACES` -> `KEYSPACE` -> `TABLE`
* Function resources have the structure `ALL FUNCTIONS` -> `KEYSPACE` ->
`FUNCTION`
* Resources representing roles have the structure `ALL ROLES` -> `ROLE`
* Resources representing JMX ObjectNames, which map to sets of
MBeans/MXBeans, have the structure `ALL MBEANS` -> `MBEAN`
Permissions can be granted at any level of these hierarchies, and they
flow downwards. So granting a permission on a resource higher up the
chain automatically grants that same permission on all resources lower
down. For example, granting `SELECT` on a `KEYSPACE` automatically
grants it on all `TABLES` in that `KEYSPACE`. Likewise, granting a
permission on `ALL FUNCTIONS` grants it on every defined function,
regardless of which keyspace it is scoped in. It is also possible to
grant permissions on all functions scoped to a particular keyspace.
Modifications to permissions are visible to existing client sessions;
that is, connections need not be re-established following permissions
changes.
The full set of available permissions is:
* `CREATE`
* `ALTER`
* `DROP`
* `SELECT`
* `MODIFY`
* `AUTHORIZE`
* `DESCRIBE`
* `EXECUTE`
* `UNMASK`
* `SELECT_MASKED`
Not all permissions are applicable to every type of resource. For
instance, `EXECUTE` is only relevant in the context of functions or
mbeans; granting `EXECUTE` on a resource representing a table is
nonsensical. Attempting to `GRANT` a permission on resource to which it
cannot be applied results in an error response. The following
illustrates which permissions can be granted on which types of resource,
and which statements are enabled by that permission.
[cols=",,,,,",options="header",]
|===
|permission |resource |operations | | |
|`CREATE` |`ALL KEYSPACES` |`CREATE KEYSPACE` <br> `CREATE TABLE` in any
keyspace | | |
|`CREATE` |`KEYSPACE` |`CREATE TABLE` in specified keyspace | | |
|`CREATE` |`ALL FUNCTIONS` |`CREATE FUNCTION` in any keyspace <br>
`CREATE AGGREGATE` in any keyspace | | |
|`CREATE` |`ALL FUNCTIONS IN KEYSPACE` |`CREATE FUNCTION` in keyspace
<br> `CREATE AGGREGATE` in keyspace | | |
|`CREATE` |`ALL ROLES` |`CREATE ROLE` | | |
|`ALTER` |`ALL KEYSPACES` |`ALTER KEYSPACE` <br> `ALTER TABLE` in any
keyspace | | |
|`ALTER` |`KEYSPACE` |`ALTER KEYSPACE` <br> `ALTER TABLE` in keyspace |
| |
|`ALTER` |`TABLE` |`ALTER TABLE` | | |
|`ALTER` |`ALL FUNCTIONS` |`CREATE FUNCTION` replacing any existing <br>
`CREATE AGGREGATE` replacing any existing | | |
|`ALTER` |`ALL FUNCTIONS IN KEYSPACE` |`CREATE FUNCTION` replacing
existing in keyspace <br> `CREATE AGGREGATE` replacing any existing in
keyspace | | |
|`ALTER` |`FUNCTION` |`CREATE FUNCTION` replacing existing <br>
`CREATE AGGREGATE` replacing existing | | |
|`ALTER` |`ALL ROLES` |`ALTER ROLE` on any role | | |
|`ALTER` |`ROLE` |`ALTER ROLE` | | |
|`DROP` |`ALL KEYSPACES` |`DROP KEYSPACE` <br> `DROP TABLE` in any
keyspace | | |
|`DROP` |`KEYSPACE` |`DROP TABLE` in specified keyspace | | |
|`DROP` |`TABLE` |`DROP TABLE` | | |
|`DROP` |`ALL FUNCTIONS` |`DROP FUNCTION` in any keyspace <br>
`DROP AGGREGATE` in any existing | | |
|`DROP` |`ALL FUNCTIONS IN KEYSPACE` |`DROP FUNCTION` in keyspace <br>
`DROP AGGREGATE` in existing | | |
|`DROP` |`FUNCTION` |`DROP FUNCTION` | | |
|`DROP` |`ALL ROLES` |`DROP ROLE` on any role | | |
|`DROP` |`ROLE` |`DROP ROLE` | | |
|`SELECT` |`ALL KEYSPACES` |`SELECT` on any table | | |
|`SELECT` |`KEYSPACE` |`SELECT` on any table in keyspace | | |
|`SELECT` |`TABLE` |`SELECT` on specified table | | |
|`SELECT` |`ALL MBEANS` |Call getter methods on any mbean | | |
|`SELECT` |`MBEANS` |Call getter methods on any mbean matching a
wildcard pattern | | |
|`SELECT` |`MBEAN` |Call getter methods on named mbean | | |
|`MODIFY` |`ALL KEYSPACES` |`INSERT` on any table <br> `UPDATE` on any
table <br> `DELETE` on any table <br> `TRUNCATE` on any table | | |
|`MODIFY` |`KEYSPACE` |`INSERT` on any table in keyspace <br> `UPDATE`
on any table in keyspace <br> `DELETE` on any table in keyspace <br>
`TRUNCATE` on any table in keyspace |`MODIFY` |`TABLE` |`INSERT` <br>
`UPDATE` <br> `DELETE` <br> `TRUNCATE`
|`MODIFY` |`ALL MBEANS` |Call setter methods on any mbean | | |
|`MODIFY` |`MBEANS` |Call setter methods on any mbean matching a
wildcard pattern | | |
|`MODIFY` |`MBEAN` |Call setter methods on named mbean | | |
|`AUTHORIZE` |`ALL KEYSPACES` |`GRANT PERMISSION` on any table <br>
`REVOKE PERMISSION` on any table | | |
|`AUTHORIZE` |`KEYSPACE` |`GRANT PERMISSION` on table in keyspace <br>
`REVOKE PERMISSION` on table in keyspace | | |
|`AUTHORIZE` |`TABLE` |`GRANT PERMISSION` <br> `REVOKE PERMISSION` | | |
|`AUTHORIZE` |`ALL FUNCTIONS` |`GRANT PERMISSION` on any function <br>
`REVOKE PERMISSION` on any function | | |
|`AUTHORIZE` |`ALL FUNCTIONS IN KEYSPACE` |`GRANT PERMISSION` in
keyspace <br> `REVOKE PERMISSION` in keyspace | | |
|`AUTHORIZE` |`ALL FUNCTIONS IN KEYSPACE` |`GRANT PERMISSION` in
keyspace <br> `REVOKE PERMISSION` in keyspace | | |
|`AUTHORIZE` |`FUNCTION` |`GRANT PERMISSION` <br> `REVOKE PERMISSION` |
| |
|`AUTHORIZE` |`ALL MBEANS` |`GRANT PERMISSION` on any mbean <br>
`REVOKE PERMISSION` on any mbean | | |
|`AUTHORIZE` |`MBEANS` |`GRANT PERMISSION` on any mbean matching a
wildcard pattern <br> `REVOKE PERMISSION` on any mbean matching a
wildcard pattern | | |
|`AUTHORIZE` |`MBEAN` |`GRANT PERMISSION` on named mbean <br>
`REVOKE PERMISSION` on named mbean | | |
|`AUTHORIZE` |`ALL ROLES` |`GRANT ROLE` grant any role <br>
`REVOKE ROLE` revoke any role | | |
|`AUTHORIZE` |`ROLES` |`GRANT ROLE` grant role <br> `REVOKE ROLE` revoke
role | | |
|`DESCRIBE` |`ALL ROLES` |`LIST ROLES` all roles or only roles granted
to another, specified role | | |
|`DESCRIBE` |@ALL MBEANS |Retrieve metadata about any mbean from the
platform’ s MBeanServer | | |
|`DESCRIBE` |@MBEANS |Retrieve metadata about any mbean matching a
wildcard patter from the platform’ s MBeanServer | | |
|`DESCRIBE` |@MBEAN |Retrieve metadata about a named mbean from the
platform’ s MBeanServer | | |
|`EXECUTE` |`ALL FUNCTIONS` |`SELECT`, `INSERT`, `UPDATE` using any
function <br> use of any function in `CREATE AGGREGATE` | | |
|`EXECUTE` |`ALL FUNCTIONS IN KEYSPACE` |`SELECT`, `INSERT`, `UPDATE`
using any function in keyspace <br> use of any function in keyspace in
`CREATE AGGREGATE` | | |
|`EXECUTE` |`FUNCTION` |`SELECT`, `INSERT`, `UPDATE` using function <br>
use of function in `CREATE AGGREGATE` | | |
|`EXECUTE` |`ALL MBEANS` |Execute operations on any mbean | | |
|`EXECUTE` |`MBEANS` |Execute operations on any mbean matching a
wildcard pattern | | |
|`EXECUTE` |`MBEAN` |Execute operations on named mbean | | |
|`UNMASK` |`ALL KEYSPACES` |See the clear contents of masked columns on any table | | |
|`UNMASK` |`KEYSPACE` |See the clear contents of masked columns on any table in keyspace | | |
|`UNMASK` |`TABLE` |See the clear contents of masked columns on the specified table | | |
|`SELECT_MASKED` | `ALL KEYSPACES` | `SELECT` restricting masked columns on any table | | |
|`SELECT_MASKED` | `KEYSPACE` | `SELECT` restricting masked columns on any table in specified keyspace | | |
|`SELECT_MASKED` | `TABLE` | `SELECT` restricting masked columns on the specified table | | |
|===
[[grantPermissionsStmt]]
==== GRANT PERMISSION
_Syntax:_
[source,bnf]
include::cassandra:example$BNF/grant_permission_statement.bnf[]
_Sample:_
[source,sql]
include::cassandra:example$CQL/grant_perm.cql[]
This gives any user with the role `data_reader` permission to execute
`SELECT` statements on any table across all keyspaces
[source,sql]
GRANT MODIFY ON KEYSPACE keyspace1 TO data_writer;
This give any user with the role `data_writer` permission to perform
`UPDATE`, `INSERT`, `UPDATE`, `DELETE` and `TRUNCATE` queries on all
tables in the `keyspace1` keyspace
[source,sql]
GRANT DROP ON keyspace1.table1 TO schema_owner;
This gives any user with the `schema_owner` role permissions to `DROP`
`keyspace1.table1`.
[source,sql]
include::cassandra:example$CQL/grant_execute.cql[]
This grants any user with the `report_writer` role permission to execute
`SELECT`, `INSERT` and `UPDATE` queries which use the function
`keyspace1.user_function( int )`
[source,sql]
include::cassandra:example$CQL/grant_describe.cql[]
This grants any user with the `role_admin` role permission to view any
and all roles in the system with a `LIST ROLES` statement
[[grantAll]]
===== GRANT ALL
When the `GRANT ALL` form is used, the appropriate set of permissions is
determined automatically based on the target resource.
[[autoGrantPermissions]]
===== Automatic Granting
When a resource is created, via a `CREATE KEYSPACE`, `CREATE TABLE`,
`CREATE FUNCTION`, `CREATE AGGREGATE` or `CREATE ROLE` statement, the
creator (the role the database user who issues the statement is
identified as), is automatically granted all applicable permissions on
the new resource.
[[revokePermissionsStmt]]
==== REVOKE PERMISSION
_Syntax:_
[source,bnf]
include::cassandra:example$BNF/revoke_permission_statement.bnf[]
_Sample:_
[source,sql]
include::cassandra:example$CQL/revoke_perm.cql[]
[[listPermissionsStmt]]
===== LIST PERMISSIONS
_Syntax:_
[source,bnf]
include::cassandra:example$BNF/list_permissions_statement.bnf[]
_Sample:_
[source,sql]
include::cassandra:example$CQL/list_perm.cql[]
Show all permissions granted to `alice`, including those acquired
transitively from any other roles.
[source,sql]
include::cassandra:example$CQL/list_all_perm.cql[]
Show all permissions on `keyspace1.table1` granted to `bob`, including
those acquired transitively from any other roles. This also includes any
permissions higher up the resource hierarchy which can be applied to
`keyspace1.table1`. For example, should `bob` have `ALTER` permission on
`keyspace1`, that would be included in the results of this query. Adding
the `NORECURSIVE` switch restricts the results to only those permissions
which were directly granted to `bob` or one of `bob`’ s roles.
[source,sql]
include::cassandra:example$CQL/list_select_perm.cql[]
Show any permissions granted to `carlos` or any of `carlos`’ s roles,
limited to `SELECT` permissions on any resource.
include::security.adoc[]
[[types]]
=== Data Types
@ -3604,227 +2979,4 @@ names as their name.
|`macaddr`
|===
=== Changes
The following describes the changes in each version of CQL.
==== 3.4.3
* Support for `GROUP BY`. See link:#selectGroupBy[`<group-by>`] (see
https://issues.apache.org/jira/browse/CASSANDRA-10707)[CASSANDRA-10707].
==== 3.4.2
* Support for selecting elements and slices of a collection
(https://issues.apache.org/jira/browse/CASSANDRA-7396)[CASSANDRA-7396].
==== 3.4.2
* link:#updateOptions[`INSERT/UPDATE options`] for tables having a
default_time_to_live specifying a TTL of 0 will remove the TTL from the
inserted or updated values
* link:#alterTableStmt[`ALTER TABLE`] `ADD` and `DROP` now allow multiple
columns to be added/removed
* New link:#selectLimit[`PER PARTITION LIMIT`] option (see
https://issues.apache.org/jira/browse/CASSANDRA-7017)[CASSANDRA-7017].
* link:#udfs[User-defined functions] can now instantiate `UDTValue` and
`TupleValue` instances via the new `UDFContext` interface (see
https://issues.apache.org/jira/browse/CASSANDRA-10818)[CASSANDRA-10818].
* ``User-defined types''#createTypeStmt may now be stored in a
non-frozen form, allowing individual fields to be updated and deleted in
link:#updateStmt[`UPDATE` statements] and link:#deleteStmt[`DELETE`
statements], respectively.
(https://issues.apache.org/jira/browse/CASSANDRA-7423)[CASSANDRA-7423]
==== 3.4.1
* Adds `CAST` functions. See link:#castFun[`Cast`].
==== 3.4.0
* Support for link:#createMVStmt[materialized views]
* link:#deleteStmt[`DELETE`] support for inequality expressions and `IN`
restrictions on any primary key columns
* link:#updateStmt[`UPDATE`] support for `IN` restrictions on any
primary key columns
==== 3.3.1
* The syntax `TRUNCATE TABLE X` is now accepted as an alias for
`TRUNCATE X`
==== 3.3.0
* Adds new link:#aggregates[aggregates]
* User-defined functions are now supported through
link:#createFunctionStmt[`CREATE FUNCTION`] and
link:#dropFunctionStmt[`DROP FUNCTION`].
* User-defined aggregates are now supported through
link:#createAggregateStmt[`CREATE AGGREGATE`] and
link:#dropAggregateStmt[`DROP AGGREGATE`].
* Allows double-dollar enclosed strings literals as an alternative to
single-quote enclosed strings.
* Introduces Roles to supersede user based authentication and access
control
* link:#usingdates[`Date`] and link:usingtime[`Time`] data types have
been added
* link:#json[`JSON`] support has been added
* `Tinyint` and `Smallint` data types have been added
* Adds new time conversion functions and deprecate `dateOf` and
`unixTimestampOf`. See link:#timeFun[`Time conversion functions`]
==== 3.2.0
* User-defined types are now supported through
link:#createTypeStmt[`CREATE TYPE`], link:#alterTypeStmt[`ALTER TYPE`],
and link:#dropTypeStmt[`DROP TYPE`]
* link:#createIndexStmt[`CREATE INDEX`] now supports indexing collection
columns, including indexing the keys of map collections through the
`keys()` function
* Indexes on collections may be queried using the new `CONTAINS` and
`CONTAINS KEY` operators
* Tuple types were added to hold fixed-length sets of typed positional
fields (see the section on link:#types[types] )
* link:#dropIndexStmt[`DROP INDEX`] now supports optionally specifying a
keyspace
==== 3.1.7
* `SELECT` statements now support selecting multiple rows in a single
partition using an `IN` clause on combinations of clustering columns.
See link:#selectWhere[SELECT WHERE] clauses.
* `IF NOT EXISTS` and `IF EXISTS` syntax is now supported by
`CREATE USER` and `DROP USER` statements, respectively.
==== 3.1.6
* A new link:#uuidFun[`uuid` method] has been added.
* Support for `DELETE ... IF EXISTS` syntax.
==== 3.1.5
* It is now possible to group clustering columns in a relatiion, see
link:#selectWhere[SELECT WHERE] clauses.
* Added support for `STATIC` columns, see link:#createTableStatic[static
in CREATE TABLE].
==== 3.1.4
* `CREATE INDEX` now allows specifying options when creating CUSTOM
indexes (see link:#createIndexStmt[CREATE INDEX reference] ).
==== 3.1.3
* Millisecond precision formats have been added to the timestamp parser
(see link:#usingtimestamps[working with dates] ).
==== 3.1.2
* `NaN` and `Infinity` has been added as valid float constants. They are
now reserved keywords. In the unlikely case you we're using them as a
column identifier (or keyspace/table one), you will now need to double
quote them (see link:#identifiers[quote identifiers] ).
==== 3.1.1
* `SELECT` statement now allows listing the partition keys (using the
`DISTINCT` modifier). See
https://issues.apache.org/jira/browse/CASSANDRA-4536[CASSANDRA-4536].
* The syntax `c IN ?` is now supported in `WHERE` clauses. In that case,
the value expected for the bind variable will be a list of whatever type
`c` is.
* It is now possible to use named bind variables (using `:name` instead
of `?`).
==== 3.1.0
* link:#alterTableStmt[ALTER TABLE] `DROP` option has been re-enabled for
CQL3 tables and has new semantics now: the space formerly used by
dropped columns will now be eventually reclaimed (post-compaction). You
should not read previously dropped columns unless you use timestamps
with microsecond precision (see
https://issues.apache.org/jira/browse/CASSANDRA-3919[CASSANDRA-3919] for
more details).
* `SELECT` statement now supports aliases in select clause. Aliases in
WHERE and ORDER BY clauses are not supported. See the
link:#selectStmt[section on select] for details.
* `CREATE` statements for `KEYSPACE`, `TABLE` and `INDEX` now supports
an `IF NOT EXISTS` condition. Similarly, `DROP` statements support a
`IF EXISTS` condition.
* `INSERT` statements optionally supports a `IF NOT EXISTS` condition
and `UPDATE` supports `IF` conditions.
==== 3.0.5
* `SELECT`, `UPDATE`, and `DELETE` statements now allow empty `IN`
relations (see
https://issues.apache.org/jira/browse/CASSANDRA-5626)[CASSANDRA-5626].
==== 3.0.4
* Updated the syntax for custom link:#createIndexStmt[secondary
indexes].
* Non-equal condition on the partition key are now never supported, even
for ordering partitioner as this was not correct (the order was *not*
the one of the type of the partition key). Instead, the `token` method
should always be used for range queries on the partition key (see
link:#selectWhere[WHERE clauses] ).
==== 3.0.3
* Support for custom link:#createIndexStmt[secondary indexes] has been
added.
==== 3.0.2
* Type validation for the link:#constants[constants] has been fixed. For
instance, the implementation used to allow `'2'` as a valid value for an
`int` column (interpreting it has the equivalent of `2`), or `42` as a
valid `blob` value (in which case `42` was interpreted as a hexadecimal
representation of the blob). This is no longer the case, type validation
of constants is now stricter. See the link:#types[data types] section
for details on which constant is allowed for which type.
* The type validation fixed of the previous point has lead to the
introduction of link:#constants[blobs constants] to allow inputing
blobs. Do note that while inputing blobs as strings constant is still
supported by this version (to allow smoother transition to blob
constant), it is now deprecated (in particular the link:#types[data
types] section does not list strings constants as valid blobs) and will
be removed by a future version. If you were using strings as blobs, you
should thus update your client code ASAP to switch blob constants.
* A number of functions to convert native types to blobs have also been
introduced. Furthermore, the token function is now also allowed in select
clauses. See the link:#functions[section on functions] for details.
==== 3.0.1
* link:#usingtimestamps[Date strings] (and timestamps) are no longer
accepted as valid `timeuuid` values. Doing so was a bug in the sense
that date string are not valid `timeuuid`, and it was thus resulting in
https://issues.apache.org/jira/browse/CASSANDRA-4936[confusing
behaviors]. However, the following new methods have been added to help
working with `timeuuid`: `now`, `minTimeuuid`, `maxTimeuuid` , `dateOf`
and `unixTimestampOf`. See the link:#timeuuidFun[section dedicated to
these methods] for more detail.
* ``Float constants''#constants now support the exponent notation. In
other words, `4.2E10` is now a valid floating point value.
=== Versioning
Versioning of the CQL language adheres to the http://semver.org[Semantic
Versioning] guidelines. Versions take the form X.Y.Z where X, Y, and Z
are integer values representing major, minor, and patch level
respectively. There is no correlation between Cassandra release versions
and the CQL language version.
[cols=",",options="header",]
|===
|version |description
|Major |The major version _must_ be bumped when backward incompatible
changes are introduced. This should rarely occur.
|Minor |Minor version increments occur when new, but backward
compatible, functionality is introduced.
|Patch |The patch version is incremented when bugs are fixed.
|===
include::changes.adoc[]