You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by ty...@apache.org on 2016/08/23 19:25:18 UTC
svn commit: r1757419 [3/29] - in /cassandra/site/src/doc: ./ 3.10/
3.10/_images/ 3.10/_sources/ 3.10/_sources/architecture/
3.10/_sources/configuration/ 3.10/_sources/cql/
3.10/_sources/data_modeling/ 3.10/_sources/development/ 3.10/_sources/faq/
3.10/...
Added: cassandra/site/src/doc/3.10/_sources/cql/changes.txt
URL: http://svn.apache.org/viewvc/cassandra/site/src/doc/3.10/_sources/cql/changes.txt?rev=1757419&view=auto
==============================================================================
--- cassandra/site/src/doc/3.10/_sources/cql/changes.txt (added)
+++ cassandra/site/src/doc/3.10/_sources/cql/changes.txt Tue Aug 23 19:25:17 2016
@@ -0,0 +1,197 @@
+.. Licensed to the Apache Software Foundation (ASF) under one
+.. or more contributor license agreements. See the NOTICE file
+.. distributed with this work for additional information
+.. regarding copyright ownership. The ASF licenses this file
+.. to you under the Apache License, Version 2.0 (the
+.. "License"); you may not use this file except in compliance
+.. with the License. You may obtain a copy of the License at
+..
+.. http://www.apache.org/licenses/LICENSE-2.0
+..
+.. Unless required by applicable law or agreed to in writing, software
+.. distributed under the License is distributed on an "AS IS" BASIS,
+.. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+.. See the License for the specific language governing permissions and
+.. limitations under the License.
+
+.. highlight:: cql
+
+Changes
+-------
+
+The following describes the changes in each version of CQL.
+
+3.4.3
+^^^^^
+
+- Support for ``GROUP BY`` (:jira:`10707`).
+- Adds a ``DEFAULT UNSET`` option for ``INSERT JSON`` to ignore omitted columns (:jira:`11424`).
+- Allows ``null`` as a legal value for TTL on insert and update. It will be treated as equivalent to
+inserting a 0 (:jira:`12216`).
+
+3.4.2
+^^^^^
+
+- If a table has a non zero ``default_time_to_live``, then explicitly specifying a TTL of 0 in an ``INSERT`` or
+ ``UPDATE`` statement will result in the new writes not having any expiration (that is, an explicit TTL of 0 cancels
+ the ``default_time_to_live``). This wasn't the case before and the ``default_time_to_live`` was applied even though a
+ TTL had been explicitly set.
+- ``ALTER TABLE`` ``ADD`` and ``DROP`` now allow multiple columns to be added/removed.
+- New ``PER PARTITION LIMIT`` option for ``SELECT`` statements (see `CASSANDRA-7017
+ <https://issues.apache.org/jira/browse/CASSANDRA-7017)>`__.
+- :ref:`User-defined functions <cql-functions>` can now instantiate ``UDTValue`` and ``TupleValue`` instances via the
+ new ``UDFContext`` interface (see `CASSANDRA-10818 <https://issues.apache.org/jira/browse/CASSANDRA-10818)>`__.
+- :ref:`User-defined types <udts>` may now be stored in a non-frozen form, allowing individual fields to be updated and
+ deleted in ``UPDATE`` statements and ``DELETE`` statements, respectively. (`CASSANDRA-7423
+ <https://issues.apache.org/jira/browse/CASSANDRA-7423)>`__).
+
+3.4.1
+^^^^^
+
+- Adds ``CAST`` functions.
+
+3.4.0
+^^^^^
+
+- Support for :ref:`materialized views <materialized-views>`.
+- ``DELETE`` support for inequality expressions and ``IN`` restrictions on any primary key columns.
+- ``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
+^^^^^
+
+- :ref:`User-defined functions and aggregates <cql-functions>` are now supported.
+- Allows double-dollar enclosed strings literals as an alternative to single-quote enclosed strings.
+- Introduces Roles to supersede user based authentication and access control
+- New ``date``, ``time``, ``tinyint`` and ``smallint`` :ref:`data types <data-types>` have been added.
+- :ref:`JSON support <cql-json>` has been added
+- Adds new time conversion functions and deprecate ``dateOf`` and ``unixTimestampOf``.
+
+3.2.0
+^^^^^
+
+- :ref:`User-defined types <udts>` supported.
+- ``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
+- :ref:`Tuple types <tuples>` were added to hold fixed-length sets of typed positional fields.
+- ``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.
+- ``IF NOT EXISTS`` and ``IF EXISTS`` syntax is now supported by ``CREATE USER`` and ``DROP USER`` statements,
+ respectively.
+
+3.1.6
+^^^^^
+
+- A new ``uuid()`` method has been added.
+- Support for ``DELETE ... IF EXISTS`` syntax.
+
+3.1.5
+^^^^^
+
+- It is now possible to group clustering columns in a relation, see :ref:`WHERE <where-clause>` clauses.
+- Added support for :ref:`static columns <static-columns>`.
+
+3.1.4
+^^^^^
+
+- ``CREATE INDEX`` now allows specifying options when creating CUSTOM indexes.
+
+3.1.3
+^^^^^
+
+- Millisecond precision formats have been added to the :ref:`timestamp <timestamps>` parser.
+
+3.1.2
+^^^^^
+
+- ``NaN`` and ``Infinity`` has been added as valid float constants. They are now reserved keywords. In the unlikely case
+ you we using them as a column identifier (or keyspace/table one), you will now need to double quote them.
+
+3.1.1
+^^^^^
+
+- ``SELECT`` statement now allows listing the partition keys (using the ``DISTINCT`` modifier). See `CASSANDRA-4536
+ <https://issues.apache.org/jira/browse/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
+^^^^^
+
+- ``ALTER TABLE`` ``DROP`` option added.
+- ``SELECT`` statement now supports aliases in select clause. Aliases in WHERE and ORDER BY clauses are not supported.
+- ``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 `CASSANDRA-5626
+ <https://issues.apache.org/jira/browse/CASSANDRA-5626)>`__.
+
+3.0.4
+^^^^^
+
+- Updated the syntax for custom :ref:`secondary indexes <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 :ref:`WHERE clauses <where-clause>`).
+
+3.0.3
+^^^^^
+
+- Support for custom :ref:`secondary indexes <secondary-indexes>` has been added.
+
+3.0.2
+^^^^^
+
+- Type validation for the :ref:`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 an hexadecimal representation of the blob). This is no longer
+ the case, type validation of constants is now more strict. See the :ref:`data 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 blobs constants to allow the input of
+ blobs. Do note that while the input of blobs as strings constant is still supported by this version (to allow smoother
+ transition to blob constant), it is now deprecated 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 :ref:`section on functions <cql-functions>` for details.
+
+3.0.1
+^^^^^
+
+- 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 `confusing behaviors
+ <https://issues.apache.org/jira/browse/CASSANDRA-4936>`__. However, the following new methods have been added to help
+ working with ``timeuuid``: ``now``, ``minTimeuuid``, ``maxTimeuuid`` ,
+ ``dateOf`` and ``unixTimestampOf``.
+- Float 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 `Semantic Versioning <http://semver.org>`__ 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.
+
+========= =============================================================================================================
+ 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.
+========= =============================================================================================================
Added: cassandra/site/src/doc/3.10/_sources/cql/ddl.txt
URL: http://svn.apache.org/viewvc/cassandra/site/src/doc/3.10/_sources/cql/ddl.txt?rev=1757419&view=auto
==============================================================================
--- cassandra/site/src/doc/3.10/_sources/cql/ddl.txt (added)
+++ cassandra/site/src/doc/3.10/_sources/cql/ddl.txt Tue Aug 23 19:25:17 2016
@@ -0,0 +1,677 @@
+.. Licensed to the Apache Software Foundation (ASF) under one
+.. or more contributor license agreements. See the NOTICE file
+.. distributed with this work for additional information
+.. regarding copyright ownership. The ASF licenses this file
+.. to you under the Apache License, Version 2.0 (the
+.. "License"); you may not use this file except in compliance
+.. with the License. You may obtain a copy of the License at
+..
+.. http://www.apache.org/licenses/LICENSE-2.0
+..
+.. Unless required by applicable law or agreed to in writing, software
+.. distributed under the License is distributed on an "AS IS" BASIS,
+.. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+.. See the License for the specific language governing permissions and
+.. limitations under the License.
+
+.. highlight:: cql
+
+.. _data-definition:
+
+Data Definition
+---------------
+
+CQL stores data in *tables*, whose schema defines the layout of said data in the table, and those tables are grouped in
+*keyspaces*. A keyspace defines a number of options that applies to all the tables it contains, most prominently of
+which is the :ref:`replication strategy <replication-strategy>` used by the keyspace. It is generally encouraged to use
+one keyspace by *application*, and thus many cluster may define only one keyspace.
+
+This section describes the statements used to create, modify, and remove those keyspace and tables.
+
+Common definitions
+^^^^^^^^^^^^^^^^^^
+
+The names of the keyspaces and tables are defined by the following grammar:
+
+.. productionlist::
+ keyspace_name: `name`
+ table_name: [ `keyspace_name` '.' ] `name`
+ name: `unquoted_name` | `quoted_name`
+ unquoted_name: re('[a-zA-Z_0-9]{1, 48}')
+ quoted_name: '"' `unquoted_name` '"'
+
+Both keyspace and table name should be comprised of only alphanumeric characters, cannot be empty and are limited in
+size to 48 characters (that limit exists mostly to avoid filenames (which may include the keyspace and table name) to go
+over the limits of certain file systems). By default, keyspace and table names are case insensitive (``myTable`` is
+equivalent to ``mytable``) but case sensitivity can be forced by using double-quotes (``"myTable"`` is different from
+``mytable``).
+
+Further, a table is always part of a keyspace and a table name can be provided fully-qualified by the keyspace it is
+part of. If is is not fully-qualified, the table is assumed to be in the *current* keyspace (see :ref:`USE statement
+<use-statement>`).
+
+Further, the valid names for columns is simply defined as:
+
+.. productionlist::
+ column_name: `identifier`
+
+We also define the notion of statement options for use in the following section:
+
+.. productionlist::
+ options: `option` ( AND `option` )*
+ option: `identifier` '=' ( `identifier` | `constant` | `map_literal` )
+
+.. _create-keyspace-statement:
+
+CREATE KEYSPACE
+^^^^^^^^^^^^^^^
+
+A keyspace is created using a ``CREATE KEYSPACE`` statement:
+
+.. productionlist::
+ create_keyspace_statement: CREATE KEYSPACE [ IF NOT EXISTS ] `keyspace_name` WITH `options`
+
+For instance::
+
+ CREATE KEYSPACE Excelsior
+ WITH replication = {'class': 'SimpleStrategy', 'replication_factor' : 3};
+
+ CREATE KEYSPACE Excalibur
+ WITH replication = {'class': 'NetworkTopologyStrategy', 'DC1' : 1, 'DC2' : 3}
+ AND durable_writes = false;
+
+
+The supported ``options`` are:
+
+=================== ========== =========== ========= ===================================================================
+name kind mandatory default description
+=================== ========== =========== ========= ===================================================================
+``replication`` *map* yes The replication strategy and options to use for the keyspace (see
+ details below).
+``durable_writes`` *simple* no true Whether to use the commit log for updates on this keyspace
+ (disable this option at your own risk!).
+=================== ========== =========== ========= ===================================================================
+
+The ``replication`` property is mandatory and must at least contains the ``'class'`` sub-option which defines the
+:ref:`replication strategy <replication-strategy>` class to use. The rest of the sub-options depends on what replication
+strategy is used. By default, Cassandra support the following ``'class'``:
+
+- ``'SimpleStrategy'``: A simple strategy that defines a replication factor for the whole cluster. The only sub-options
+ supported is ``'replication_factor'`` to define that replication factor and is mandatory.
+- ``'NetworkTopologyStrategy'``: A replication strategy that allows to set the replication factor independently for
+ each data-center. The rest of the sub-options are key-value pairs where a key is a data-center name and its value is
+ the associated replication factor.
+
+Attempting to create a keyspace that already exists will return an error unless the ``IF NOT EXISTS`` option is used. If
+it is used, the statement will be a no-op if the keyspace already exists.
+
+.. _use-statement:
+
+USE
+^^^
+
+The ``USE`` statement allows to change the *current* keyspace (for the *connection* on which it is executed). A number
+of objects in CQL are bound to a keyspace (tables, user-defined types, functions, ...) and the current keyspace is the
+default keyspace used when those objects are referred without a fully-qualified name (that is, without being prefixed a
+keyspace name). A ``USE`` statement simply takes the keyspace to use as current as argument:
+
+.. productionlist::
+ use_statement: USE `keyspace_name`
+
+.. _alter-keyspace-statement:
+
+ALTER KEYSPACE
+^^^^^^^^^^^^^^
+
+An ``ALTER KEYSPACE`` statement allows to modify the options of a keyspace:
+
+.. productionlist::
+ alter_keyspace_statement: ALTER KEYSPACE `keyspace_name` WITH `options`
+
+For instance::
+
+ ALTER KEYSPACE Excelsior
+ WITH replication = {'class': 'SimpleStrategy', 'replication_factor' : 4};
+
+The supported options are the same than for :ref:`creating a keyspace <create-keyspace-statement>`.
+
+.. _drop-keyspace-statement:
+
+DROP KEYSPACE
+^^^^^^^^^^^^^
+
+Dropping a keyspace can be done using the ``DROP KEYSPACE`` statement:
+
+.. productionlist::
+ drop_keyspace_statement: DROP KEYSPACE [ IF EXISTS ] `keyspace_name`
+
+For instance::
+
+ DROP KEYSPACE Excelsior;
+
+Dropping a keyspace results in the immediate, irreversible removal of that keyspace, including all the tables, UTD and
+functions in it, and all the data contained in those tables.
+
+If the keyspace does not exists, the statement will return an error, unless ``IF EXISTS`` is used in which case the
+operation is a no-op.
+
+.. _create-table-statement:
+
+CREATE TABLE
+^^^^^^^^^^^^
+
+Creating a new table uses the ``CREATE TABLE`` statement:
+
+.. productionlist::
+ create_table_statement: CREATE TABLE [ IF NOT EXISTS ] `table_name`
+ : '('
+ : `column_definition`
+ : ( ',' `column_definition` )*
+ : [ ',' PRIMARY KEY '(' `primary_key` ')' ]
+ : ')' [ WITH `table_options` ]
+ column_definition: `column_name` `cql_type` [ STATIC ] [ PRIMARY KEY]
+ primary_key: `partition_key` [ ',' `clustering_columns` ]
+ partition_key: `column_name`
+ : | '(' `column_name` ( ',' `column_name` )* ')'
+ clustering_columns: `column_name` ( ',' `column_name` )*
+ table_options: COMPACT STORAGE [ AND `table_options` ]
+ : | CLUSTERING ORDER BY '(' `clustering_order` ')' [ AND `table_options` ]
+ : | `options`
+ clustering_order: `column_name` (ASC | DESC) ( ',' `column_name` (ASC | DESC) )*
+
+For instance::
+
+ CREATE TABLE monkeySpecies (
+ species text PRIMARY KEY,
+ common_name text,
+ population varint,
+ average_size int
+ ) WITH comment='Important biological records'
+ AND read_repair_chance = 1.0;
+
+ CREATE TABLE timeline (
+ userid uuid,
+ posted_month int,
+ posted_time uuid,
+ body text,
+ posted_by text,
+ PRIMARY KEY (userid, posted_month, posted_time)
+ ) WITH compaction = { 'class' : 'LeveledCompactionStrategy' };
+
+ CREATE TABLE loads (
+ machine inet,
+ cpu int,
+ mtime timeuuid,
+ load float,
+ PRIMARY KEY ((machine, cpu), mtime)
+ ) WITH CLUSTERING ORDER BY (mtime DESC);
+
+A CQL table has a name and is composed of a set of *rows*. Creating a table amounts to defining which :ref:`columns
+<column-definition>` the rows will be composed, which of those columns compose the :ref:`primary key <primary-key>`, as
+well as optional :ref:`options <create-table-options>` for the table.
+
+Attempting to create an already existing table will return an error unless the ``IF NOT EXISTS`` directive is used. If
+it is used, the statement will be a no-op if the table already exists.
+
+
+.. _column-definition:
+
+Column definitions
+~~~~~~~~~~~~~~~~~~
+
+Every rows in a CQL table has a set of predefined columns defined at the time of the table creation (or added later
+using an :ref:`alter statement<alter-table-statement>`).
+
+A :token:`column_definition` is primarily comprised of the name of the column defined and it's :ref:`type <data-types>`,
+which restrict which values are accepted for that column. Additionally, a column definition can have the following
+modifiers:
+
+``STATIC``
+ it declares the column as being a :ref:`static column <static-columns>`.
+
+``PRIMARY KEY``
+ it declares the column as being the sole component of the :ref:`primary key <primary-key>` of the table.
+
+.. _static-columns:
+
+Static columns
+``````````````
+Some columns can be declared as ``STATIC`` in a table definition. A column that is static will be “shared” by all the
+rows belonging to the same partition (having the same :ref:`partition key <partition-key>`). For instance::
+
+ CREATE TABLE t (
+ pk int,
+ t int,
+ v text,
+ s text static,
+ PRIMARY KEY (pk, t)
+ );
+
+ INSERT INTO t (pk, t, v, s) VALUES (0, 0, 'val0', 'static0');
+ INSERT INTO t (pk, t, v, s) VALUES (0, 1, 'val1', 'static1');
+
+ SELECT * FROM t;
+ pk | t | v | s
+ ----+---+--------+-----------
+ 0 | 0 | 'val0' | 'static1'
+ 0 | 1 | 'val1' | 'static1'
+
+As can be seen, the ``s`` value is the same (``static1``) for both of the row in the partition (the partition key in
+that example being ``pk``, both rows are in that same partition): the 2nd insertion has overridden the value for ``s``.
+
+The use of static columns as the following restrictions:
+
+- tables with the ``COMPACT STORAGE`` option (see below) cannot use them.
+- a table without clustering columns cannot have static columns (in a table without clustering columns, every partition
+ has only one row, and so every column is inherently static).
+- only non ``PRIMARY KEY`` columns can be static.
+
+.. _primary-key:
+
+The Primary key
+~~~~~~~~~~~~~~~
+
+Within a table, a row is uniquely identified by its ``PRIMARY KEY``, and hence all table **must** define a PRIMARY KEY
+(and only one). A ``PRIMARY KEY`` definition is composed of one or more of the columns defined in the table.
+Syntactically, the primary key is defined the keywords ``PRIMARY KEY`` followed by comma-separated list of the column
+names composing it within parenthesis, but if the primary key has only one column, one can alternatively follow that
+column definition by the ``PRIMARY KEY`` keywords. The order of the columns in the primary key definition matter.
+
+A CQL primary key is composed of 2 parts:
+
+- the :ref:`partition key <partition-key>` part. It is the first component of the primary key definition. It can be a
+ single column or, using additional parenthesis, can be multiple columns. A table always have at least a partition key,
+ the smallest possible table definition is::
+
+ CREATE TABLE t (k text PRIMARY KEY);
+
+- the :ref:`clustering columns <clustering-columns>`. Those are the columns after the first component of the primary key
+ definition, and the order of those columns define the *clustering order*.
+
+Some example of primary key definition are:
+
+- ``PRIMARY KEY (a)``: ``a`` is the partition key and there is no clustering columns.
+- ``PRIMARY KEY (a, b, c)`` : ``a`` is the partition key and ``b`` and ``c`` are the clustering columns.
+- ``PRIMARY KEY ((a, b), c)`` : ``a`` and ``b`` compose the partition key (this is often called a *composite* partition
+ key) and ``c`` is the clustering column.
+
+
+.. _partition-key:
+
+The partition key
+`````````````````
+
+Within a table, CQL defines the notion of a *partition*. A partition is simply the set of rows that share the same value
+for their partition key. Note that if the partition key is composed of multiple columns, then rows belong to the same
+partition only they have the same values for all those partition key column. So for instance, given the following table
+definition and content::
+
+ CREATE TABLE t (
+ a int,
+ b int,
+ c int,
+ d int,
+ PRIMARY KEY ((a, b), c, d)
+ );
+
+ SELECT * FROM t;
+ a | b | c | d
+ ---+---+---+---
+ 0 | 0 | 0 | 0 // row 1
+ 0 | 0 | 1 | 1 // row 2
+ 0 | 1 | 2 | 2 // row 3
+ 0 | 1 | 3 | 3 // row 4
+ 1 | 1 | 4 | 4 // row 5
+
+``row 1`` and ``row 2`` are in the same partition, ``row 3`` and ``row 4`` are also in the same partition (but a
+different one) and ``row 5`` is in yet another partition.
+
+Note that a table always has a partition key, and that if the table has no :ref:`clustering columns
+<clustering-columns>`, then every partition of that table is only comprised of a single row (since the primary key
+uniquely identifies rows and the primary key is equal to the partition key if there is no clustering columns).
+
+The most important property of partition is that all the rows belonging to the same partition are guarantee to be stored
+on the same set of replica nodes. In other words, the partition key of a table defines which of the rows will be
+localized together in the Cluster, and it is thus important to choose your partition key wisely so that rows that needs
+to be fetch together are in the same partition (so that querying those rows together require contacting a minimum of
+nodes).
+
+Please note however that there is a flip-side to this guarantee: as all rows sharing a partition key are guaranteed to
+be stored on the same set of replica node, a partition key that groups too much data can create a hotspot.
+
+Another useful property of a partition is that when writing data, all the updates belonging to a single partition are
+done *atomically* and in *isolation*, which is not the case across partitions.
+
+The proper choice of the partition key and clustering columns for a table is probably one of the most important aspect
+of data modeling in Cassandra, and it largely impact which queries can be performed, and how efficiently they are.
+
+
+.. _clustering-columns:
+
+The clustering columns
+``````````````````````
+
+The clustering columns of a table defines the clustering order for the partition of that table. For a given
+:ref:`partition <partition-key>`, all the rows are physically ordered inside Cassandra by that clustering order. For
+instance, given::
+
+ CREATE TABLE t (
+ a int,
+ b int,
+ c int,
+ PRIMARY KEY (a, c, d)
+ );
+
+ SELECT * FROM t;
+ a | b | c
+ ---+---+---
+ 0 | 0 | 4 // row 1
+ 0 | 1 | 9 // row 2
+ 0 | 2 | 2 // row 3
+ 0 | 3 | 3 // row 4
+
+then the rows (which all belong to the same partition) are all stored internally in the order of the values of their
+``b`` column (the order they are displayed above). So where the partition key of the table allows to group rows on the
+same replica set, the clustering columns controls how those rows are stored on the replica. That sorting allows the
+retrieval of a range of rows within a partition (for instance, in the example above, ``SELECT * FROM t WHERE a = 0 AND b
+> 1 and b <= 3``) very efficient.
+
+
+.. _create-table-options:
+
+Table options
+~~~~~~~~~~~~~
+
+A CQL table has a number of options that can be set at creation (and, for most of them, :ref:`altered
+<alter-table-statement>` later). These options are specified after the ``WITH`` keyword.
+
+Amongst those options, two important ones cannot be changed after creation and influence which queries can be done
+against the table: the ``COMPACT STORAGE`` option and the ``CLUSTERING ORDER`` option. Those, as well as the other
+options of a table are described in the following sections.
+
+.. _compact-tables:
+
+Compact tables
+``````````````
+
+.. warning:: Since Cassandra 3.0, compact tables have the exact same layout internally than non compact ones (for the
+ same schema obviously), and declaring a table compact **only** creates artificial limitations on the table definition
+ and usage that are necessary to ensure backward compatibility with the deprecated Thrift API. And as ``COMPACT
+ STORAGE`` cannot, as of Cassandra |version|, be removed, it is strongly discouraged to create new table with the
+ ``COMPACT STORAGE`` option.
+
+A *compact* table is one defined with the ``COMPACT STORAGE`` option. This option is mainly targeted towards backward
+compatibility for definitions created before CQL version 3 (see `www.datastax.com/dev/blog/thrift-to-cql3
+<http://www.datastax.com/dev/blog/thrift-to-cql3>`__ for more details) and shouldn't be used for new tables. Declaring a
+table with this option creates limitations for the table which are largely arbitrary but necessary for backward
+compatibility with the (deprecated) Thrift API. Amongst those limitation:
+
+- a compact table cannot use collections nor static columns.
+- if a compact table has at least one clustering column, then it must have *exactly* one column outside of the primary
+ key ones. This imply you cannot add or remove columns after creation in particular.
+- a compact table is limited in the indexes it can create, and no materialized view can be created on it.
+
+.. _clustering-order:
+
+Reversing the clustering order
+``````````````````````````````
+
+The clustering order of a table is defined by the :ref:`clustering columns <clustering-columns>` of that table. By
+default, that ordering is based on natural order of those clustering order, but the ``CLUSTERING ORDER`` allows to
+change that clustering order to use the *reverse* natural order for some (potentially all) of the columns.
+
+The ``CLUSTERING ORDER`` option takes the comma-separated list of the clustering column, each with a ``ASC`` (for
+*ascendant*, e.g. the natural order) or ``DESC`` (for *descendant*, e.g. the reverse natural order). Note in particular
+that the default (if the ``CLUSTERING ORDER`` option is not used) is strictly equivalent to using the option with all
+clustering columns using the ``ASC`` modifier.
+
+Note that this option is basically a hint for the storage engine to change the order in which it stores the row but it
+has 3 visible consequences:
+
+# it limits which ``ORDER BY`` clause are allowed for :ref:`selects <select-statement>` on that table. You can only
+ order results by the clustering order or the reverse clustering order. Meaning that if a table has 2 clustering column
+ ``a`` and ``b`` and you defined ``WITH CLUSTERING ORDER (a DESC, b ASC)``, then in queries you will be allowed to use
+ ``ORDER BY (a DESC, b ASC)`` and (reverse clustering order) ``ORDER BY (a ASC, b DESC)`` but **not** ``ORDER BY (a
+ ASC, b ASC)`` (nor ``ORDER BY (a DESC, b DESC)``).
+# it also change the default order of results when queried (if no ``ORDER BY`` is provided). Results are always returned
+ in clustering order (within a partition).
+# it has a small performance impact on some queries as queries in reverse clustering order are slower than the one in
+ forward clustering order. In practice, this means that if you plan on querying mostly in the reverse natural order of
+ your columns (which is common with time series for instance where you often want data from the newest to the oldest),
+ it is an optimization to declare a descending clustering order.
+
+.. _create-table-general-options:
+
+Other table options
+```````````````````
+
+.. todo:: review (misses cdc if nothing else) and link to proper categories when appropriate (compaction for instance)
+
+A table supports the following options:
+
++--------------------------------+----------+-------------+-----------------------------------------------------------+
+| option | kind | default | description |
++================================+==========+=============+===========================================================+
+| ``comment`` | *simple* | none | A free-form, human-readable comment. |
++--------------------------------+----------+-------------+-----------------------------------------------------------+
+| ``read_repair_chance`` | *simple* | 0.1 | The probability with which to query extra nodes (e.g. |
+| | | | more nodes than required by the consistency level) for |
+| | | | the purpose of read repairs. |
++--------------------------------+----------+-------------+-----------------------------------------------------------+
+| ``dclocal_read_repair_chance`` | *simple* | 0 | The probability with which to query extra nodes (e.g. |
+| | | | more nodes than required by the consistency level) |
+| | | | belonging to the same data center than the read |
+| | | | coordinator for the purpose of read repairs. |
++--------------------------------+----------+-------------+-----------------------------------------------------------+
+| ``gc_grace_seconds`` | *simple* | 864000 | Time to wait before garbage collecting tombstones |
+| | | | (deletion markers). |
++--------------------------------+----------+-------------+-----------------------------------------------------------+
+| ``bloom_filter_fp_chance`` | *simple* | 0.00075 | The target probability of false positive of the sstable |
+| | | | bloom filters. Said bloom filters will be sized to provide|
+| | | | the provided probability (thus lowering this value impact |
+| | | | the size of bloom filters in-memory and on-disk) |
++--------------------------------+----------+-------------+-----------------------------------------------------------+
+| ``default_time_to_live`` | *simple* | 0 | The default expiration time (“TTL”) in seconds for a |
+| | | | table. |
++--------------------------------+----------+-------------+-----------------------------------------------------------+
+| ``compaction`` | *map* | *see below* | :ref:`Compaction options <cql-compaction-options>`. |
++--------------------------------+----------+-------------+-----------------------------------------------------------+
+| ``compression`` | *map* | *see below* | :ref:`Compression options <cql-compression-options>`. |
++--------------------------------+----------+-------------+-----------------------------------------------------------+
+| ``caching`` | *map* | *see below* | :ref:`Caching options <cql-caching-options>`. |
++--------------------------------+----------+-------------+-----------------------------------------------------------+
+
+.. _cql-compaction-options:
+
+Compaction options
+##################
+
+The ``compaction`` options must at least define the ``'class'`` sub-option, that defines the compaction strategy class
+to use. The default supported class are ``'SizeTieredCompactionStrategy'`` (:ref:`STCS <STCS>`),
+``'LeveledCompactionStrategy'`` (:ref:`LCS <LCS>`) and ``'TimeWindowCompactionStrategy'`` (:ref:`TWCS <TWCS>`) (the
+``'DateTieredCompactionStrategy'`` is also supported but is deprecated and ``'TimeWindowCompactionStrategy'`` should be
+preferred instead). Custom strategy can be provided by specifying the full class name as a :ref:`string constant
+<constants>`.
+
+All default strategies support a number of :ref:`common options <compaction-options>`, as well as options specific to
+the strategy chosen (see the section corresponding to your strategy for details: :ref:`STCS <stcs-options>`, :ref:`LCS
+<lcs-options>` and :ref:`TWCS <TWCS>`).
+
+.. _cql-compression-options:
+
+Compression options
+###################
+
+The ``compression`` options define if and how the sstables of the table are compressed. The following sub-options are
+available:
+
+========================= =============== =============================================================================
+ Option Default Description
+========================= =============== =============================================================================
+ ``class`` LZ4Compressor The compression algorithm to use. Default compressor are: LZ4Compressor,
+ SnappyCompressor and DeflateCompressor. Use ``'enabled' : false`` to disable
+ compression. Custom compressor can be provided by specifying the full class
+ name as a “string constant”:#constants.
+ ``enabled`` true Enable/disable sstable compression.
+ ``chunk_length_in_kb`` 64KB On disk SSTables are compressed by block (to allow random reads). This
+ defines the size (in KB) of said block. Bigger values may improve the
+ compression rate, but increases the minimum size of data to be read from disk
+ for a read
+ ``crc_check_chance`` 1.0 When compression is enabled, each compressed block includes a checksum of
+ that block for the purpose of detecting disk bitrot and avoiding the
+ propagation of corruption to other replica. This option defines the
+ probability with which those checksums are checked during read. By default
+ they are always checked. Set to 0 to disable checksum checking and to 0.5 for
+ instance to check them every other read |
+========================= =============== =============================================================================
+
+.. _cql-caching-options:
+
+Caching options
+###############
+
+The ``caching`` options allows to configure both the *key cache* and the *row cache* for the table. The following
+sub-options are available:
+
+======================== ========= ====================================================================================
+ Option Default Description
+======================== ========= ====================================================================================
+ ``keys`` ALL Whether to cache keys (“key cache”) for this table. Valid values are: ``ALL`` and
+ ``NONE``.
+ ``rows_per_partition`` NONE The amount of rows to cache per partition (“row cache”). If an integer ``n`` is
+ specified, the first ``n`` queried rows of a partition will be cached. Other
+ possible options are ``ALL``, to cache all rows of a queried partition, or ``NONE``
+ to disable row caching.
+======================== ========= ====================================================================================
+
+Other considerations:
+#####################
+
+- Adding new columns (see ``ALTER TABLE`` below) is a constant time operation. There is thus no need to try to
+ anticipate future usage when creating a table.
+
+.. _alter-table-statement:
+
+ALTER TABLE
+^^^^^^^^^^^
+
+Altering an existing table uses the ``ALTER TABLE`` statement:
+
+.. productionlist::
+ alter_table_statement: ALTER TABLE `table_name` `alter_table_instruction`
+ alter_table_instruction: ALTER `column_name` TYPE `cql_type`
+ : | ADD `column_name` `cql_type` ( ',' `column_name` `cql_type` )*
+ : | DROP `column_name` ( `column_name` )*
+ : | WITH `options`
+
+For instance::
+
+ ALTER TABLE addamsFamily ALTER lastKnownLocation TYPE uuid;
+
+ ALTER TABLE addamsFamily ADD gravesite varchar;
+
+ ALTER TABLE addamsFamily
+ WITH comment = 'A most excellent and useful table'
+ AND read_repair_chance = 0.2;
+
+The ``ALTER TABLE`` statement can:
+
+- Change the type of one of the column in the table (through the ``ALTER`` instruction). Note that the type of a column
+ cannot be changed arbitrarily. The change of type should be such that any value of the previous type should be a valid
+ value of the new type. Further, for :ref:`clustering columns <clustering-columns>` and columns on which a secondary
+ index is defined, the new type must sort values in the same way the previous type does. See the :ref:`type
+ compatibility table <alter-table-type-compatibility>` below for detail on which type changes are accepted.
+- Add new column(s) to the table (through the ``ADD`` instruction). Note that the primary key of a table cannot be
+ changed and thus newly added column will, by extension, never be part of the primary key. Also note that :ref:`compact
+ tables <compact-tables>` have restrictions regarding column addition. Note that this is constant (in the amount of
+ data the cluster contains) time operation.
+- Remove column(s) from the table. This drops both the column and all its content, but note that while the column
+ becomes immediately unavailable, its content is only removed lazily during compaction. Please also see the warnings
+ below. Due to lazy removal, the altering itself is a constant (in the amount of data removed or contained in the
+ cluster) time operation.
+- Change some of the table options (through the ``WITH`` instruction). The :ref:`supported options
+ <create-table-options>` are the same that when creating a table (outside of ``COMPACT STORAGE`` and ``CLUSTERING
+ ORDER`` that cannot be changed after creation). Note that setting any ``compaction`` sub-options has the effect of
+ erasing all previous ``compaction`` options, so you need to re-specify all the sub-options if you want to keep them.
+ The same note applies to the set of ``compression`` sub-options.
+
+.. warning:: Dropping a column assumes that the timestamps used for the value of this column are "real" timestamp in
+ microseconds. Using "real" timestamps in microseconds is the default is and is **strongly** recommended but as
+ Cassandra allows the client to provide any timestamp on any table it is theoretically possible to use another
+ convention. Please be aware that if you do so, dropping a column will not work correctly.
+
+.. warning:: Once a column is dropped, it is allowed to re-add a column with the same name than the dropped one
+ **unless** the type of the dropped column was a (non-frozen) column (due to an internal technical limitation).
+
+.. _alter-table-type-compatibility:
+
+CQL type compatibility:
+~~~~~~~~~~~~~~~~~~~~~~~
+
+CQL data types may be converted only as the following table.
+
++-------------------------------------------------------+--------------------+
+| Existing type | Can be altered to: |
++=======================================================+====================+
+| timestamp | bigint |
++-------------------------------------------------------+--------------------+
+| ascii, bigint, boolean, date, decimal, double, float, | blob |
+| inet, int, smallint, text, time, timestamp, timeuuid, | |
+| tinyint, uuid, varchar, varint | |
++-------------------------------------------------------+--------------------+
+| int | date |
++-------------------------------------------------------+--------------------+
+| ascii, varchar | text |
++-------------------------------------------------------+--------------------+
+| bigint | time |
++-------------------------------------------------------+--------------------+
+| bigint | timestamp |
++-------------------------------------------------------+--------------------+
+| timeuuid | uuid |
++-------------------------------------------------------+--------------------+
+| ascii, text | varchar |
++-------------------------------------------------------+--------------------+
+| bigint, int, timestamp | varint |
++-------------------------------------------------------+--------------------+
+
+Clustering columns have stricter requirements, only the following conversions are allowed:
+
++------------------------+----------------------+
+| Existing type | Can be altered to |
++========================+======================+
+| ascii, text, varchar | blob |
++------------------------+----------------------+
+| ascii, varchar | text |
++------------------------+----------------------+
+| ascii, text | varchar |
++------------------------+----------------------+
+
+.. _drop-table-statement:
+
+DROP TABLE
+^^^^^^^^^^
+
+Dropping a table uses the ``DROP TABLE`` statement:
+
+.. productionlist::
+ drop_table_statement: DROP TABLE [ IF EXISTS ] `table_name`
+
+Dropping a table results in the immediate, irreversible removal of the table, including all data it contains.
+
+If the table does not exist, the statement will return an error, unless ``IF EXISTS`` is used in which case the
+operation is a no-op.
+
+.. _truncate-statement:
+
+TRUNCATE
+^^^^^^^^
+
+A table can be truncated using the ``TRUNCATE`` statement:
+
+.. productionlist::
+ truncate_statement: TRUNCATE [ TABLE ] `table_name`
+
+Note that ``TRUNCATE TABLE foo`` is allowed for consistency with other DDL statements but tables are the only object
+that can be truncated currently and so the ``TABLE`` keyword can be omitted.
+
+Truncating a table permanently removes all existing data from the table, but without removing the table itself.
Added: cassandra/site/src/doc/3.10/_sources/cql/definitions.txt
URL: http://svn.apache.org/viewvc/cassandra/site/src/doc/3.10/_sources/cql/definitions.txt?rev=1757419&view=auto
==============================================================================
--- cassandra/site/src/doc/3.10/_sources/cql/definitions.txt (added)
+++ cassandra/site/src/doc/3.10/_sources/cql/definitions.txt Tue Aug 23 19:25:17 2016
@@ -0,0 +1,232 @@
+.. Licensed to the Apache Software Foundation (ASF) under one
+.. or more contributor license agreements. See the NOTICE file
+.. distributed with this work for additional information
+.. regarding copyright ownership. The ASF licenses this file
+.. to you under the Apache License, Version 2.0 (the
+.. "License"); you may not use this file except in compliance
+.. with the License. You may obtain a copy of the License at
+..
+.. http://www.apache.org/licenses/LICENSE-2.0
+..
+.. Unless required by applicable law or agreed to in writing, software
+.. distributed under the License is distributed on an "AS IS" BASIS,
+.. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+.. See the License for the specific language governing permissions and
+.. limitations under the License.
+
+.. _UUID: https://en.wikipedia.org/wiki/Universally_unique_identifier
+
+.. highlight:: cql
+
+Definitions
+-----------
+
+.. _conventions:
+
+Conventions
+^^^^^^^^^^^
+
+To aid in specifying the CQL syntax, we will use the following conventions in this document:
+
+- Language rules will be given in an informal `BNF variant
+ <http://en.wikipedia.org/wiki/Backus%E2%80%93Naur_Form#Variants>`_ notation. In particular, we'll use square brakets
+ (``[ item ]``) for optional items, ``*`` and ``+`` for repeated items (where ``+`` imply at least one).
+- The grammar will also use the following convention for convenience: non-terminal term will be lowercase (and link to
+ their definition) while terminal keywords will be provided "all caps". Note however that keywords are
+ :ref:`identifiers` and are thus case insensitive in practice. We will also define some early construction using
+ regexp, which we'll indicate with ``re(<some regular expression>)``.
+- The grammar is provided for documentation purposes and leave some minor details out. For instance, the comma on the
+ last column definition in a ``CREATE TABLE`` statement is optional but supported if present even though the grammar in
+ this document suggests otherwise. Also, not everything accepted by the grammar is necessarily valid CQL.
+- References to keywords or pieces of CQL code in running text will be shown in a ``fixed-width font``.
+
+
+.. _identifiers:
+
+Identifiers and keywords
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+The CQL language uses *identifiers* (or *names*) to identify tables, columns and other objects. An identifier is a token
+matching the regular expression ``[a-zA-Z][a-zA-Z0-9_]*``.
+
+A number of such identifiers, like ``SELECT`` or ``WITH``, are *keywords*. They have a fixed meaning for the language
+and most are reserved. The list of those keywords can be found in :ref:`appendix-A`.
+
+Identifiers and (unquoted) keywords are case insensitive. Thus ``SELECT`` is the same than ``select`` or ``sElEcT``, and
+``myId`` is the same than ``myid`` or ``MYID``. A convention often used (in particular by the samples of this
+documentation) is to use upper case for keywords and lower case for other identifiers.
+
+There is a second kind of identifiers called *quoted identifiers* defined by enclosing an arbitrary sequence of
+characters (non empty) in double-quotes(``"``). Quoted identifiers are never keywords. Thus ``"select"`` is not a
+reserved keyword and can be used to refer to a column (note that using this is particularly advised), while ``select``
+would raise a parsing error. Also, contrarily to unquoted identifiers and keywords, quoted identifiers are case
+sensitive (``"My Quoted Id"`` is *different* from ``"my quoted id"``). A fully lowercase quoted identifier that matches
+``[a-zA-Z][a-zA-Z0-9_]*`` is however *equivalent* to the unquoted identifier obtained by removing the double-quote (so
+``"myid"`` is equivalent to ``myid`` and to ``myId`` but different from ``"myId"``). Inside a quoted identifier, the
+double-quote character can be repeated to escape it, so ``"foo "" bar"`` is a valid identifier.
+
+.. note:: *quoted identifiers* allows to declare columns with arbitrary names, and those can sometime clash with
+ specific names used by the server. For instance, when using conditional update, the server will respond with a
+ result-set containing a special result named ``"[applied]"``. If you’ve declared a column with such a name, this
+ could potentially confuse some tools and should be avoided. In general, unquoted identifiers should be preferred but
+ if you use quoted identifiers, it is strongly advised to avoid any name enclosed by squared brackets (like
+ ``"[applied]"``) and any name that looks like a function call (like ``"f(x)"``).
+
+More formally, we have:
+
+.. productionlist::
+ identifier: `unquoted_identifier` | `quoted_identifier`
+ unquoted_identifier: re('[a-zA-Z][a-zA-Z0-9_]*')
+ quoted_identifier: '"' (any character where " can appear if doubled)+ '"'
+
+.. _constants:
+
+Constants
+^^^^^^^^^
+
+CQL defines the following kind of *constants*:
+
+.. productionlist::
+ constant: `string` | `integer` | `float` | `boolean` | `uuid` | `blob` | NULL
+ string: '\'' (any character where ' can appear if doubled)+ '\''
+ : '$$' (any character other than '$$') '$$'
+ integer: re('-?[0-9]+')
+ float: re('-?[0-9]+(\.[0-9]*)?([eE][+-]?[0-9+])?') | NAN | INFINITY
+ boolean: TRUE | FALSE
+ uuid: `hex`{8}-`hex`{4}-`hex`{4}-`hex`{4}-`hex`{12}
+ hex: re("[0-9a-fA-F]")
+ blob: '0' ('x' | 'X') `hex`+
+
+In other words:
+
+- A string constant is an arbitrary sequence of characters enclosed by single-quote(``'``). A single-quote
+ can be included by repeating it, e.g. ``'It''s raining today'``. Those are not to be confused with quoted
+ :ref:`identifiers` that use double-quotes. Alternatively, a string can be defined by enclosing the arbitrary sequence
+ of characters by two dollar characters, in which case single-quote can be use without escaping (``$$It's raining
+ today$$``). That latter form is often used when defining :ref:`user-defined functions <udfs>` to avoid having to
+ escape single-quote characters in function body (as they are more likely to occur than ``$$``).
+- Integer, float and boolean constant are defined as expected. Note however than float allows the special ``NaN`` and
+ ``Infinity`` constants.
+- CQL supports UUID_ constants.
+- Blobs content are provided in hexadecimal and prefixed by ``0x``.
+- The special ``NULL`` constant denotes the absence of value.
+
+For how these constants are typed, see the :ref:`data-types` section.
+
+Terms
+^^^^^
+
+CQL has the notion of a *term*, which denotes the kind of values that CQL support. Terms are defined by:
+
+.. productionlist::
+ term: `constant` | `literal` | `function_call` | `type_hint` | `bind_marker`
+ literal: `collection_literal` | `udt_literal` | `tuple_literal`
+ function_call: `identifier` '(' [ `term` (',' `term`)* ] ')'
+ type_hint: '(' `cql_type` `)` term
+ bind_marker: '?' | ':' `identifier`
+
+A term is thus one of:
+
+- A :ref:`constant <constants>`.
+- A literal for either :ref:`a collection <collections>`, :ref:`a user-defined type <udts>` or :ref:`a tuple <tuples>`
+ (see the linked sections for details).
+- A function call: see :ref:`the section on functions <cql-functions>` for details on which :ref:`native function
+ <native-functions>` exists and how to define your own :ref:`user-defined ones <udfs>`.
+- A *type hint*: see the :ref:`related section <type-hints>` for details.
+- A bind marker, which denotes a variable to be bound at execution time. See the section on :ref:`prepared-statements`
+ for details. A bind marker can be either anonymous (``?``) or named (``:some_name``). The latter form provides a more
+ convenient way to refer to the variable for binding it and should generally be preferred.
+
+
+Comments
+^^^^^^^^
+
+A comment in CQL is a line beginning by either double dashes (``--``) or double slash (``//``).
+
+Multi-line comments are also supported through enclosure within ``/*`` and ``*/`` (but nesting is not supported).
+
+::
+
+ -- This is a comment
+ // This is a comment too
+ /* This is
+ a multi-line comment */
+
+Statements
+^^^^^^^^^^
+
+CQL consists of statements that can be divided in the following categories:
+
+- :ref:`data-definition` statements, to define and change how the data is stored (keyspaces and tables).
+- :ref:`data-manipulation` statements, for selecting, inserting and deleting data.
+- :ref:`secondary-indexes` statements.
+- :ref:`materialized-views` statements.
+- :ref:`cql-roles` statements.
+- :ref:`cql-permissions` statements.
+- :ref:`User-Defined Functions <udfs>` statements.
+- :ref:`udts` statements.
+- :ref:`cql-triggers` statements.
+
+All the statements are listed below and are described in the rest of this documentation (see links above):
+
+.. productionlist::
+ cql_statement: `statement` [ ';' ]
+ statement: `ddl_statement`
+ : | `dml_statement`
+ : | `secondary_index_statement`
+ : | `materialized_view_statement`
+ : | `role_or_permission_statement`
+ : | `udf_statement`
+ : | `udt_statement`
+ : | `trigger_statement`
+ ddl_statement: `use_statement`
+ : | `create_keyspace_statement`
+ : | `alter_keyspace_statement`
+ : | `drop_keyspace_statement`
+ : | `create_table_statement`
+ : | `alter_table_statement`
+ : | `drop_table_statement`
+ : | `truncate_statement`
+ dml_statement: `select_statement`
+ : | `insert_statement`
+ : | `update_statement`
+ : | `delete_statement`
+ : | `batch_statement`
+ secondary_index_statement: `create_index_statement`
+ : | `drop_index_statement`
+ materialized_view_statement: `create_materialized_view_statement`
+ : | `drop_materialized_view_statement`
+ role_or_permission_statement: `create_role_statement`
+ : | `alter_role_statement`
+ : | `drop_role_statement`
+ : | `grant_role_statement`
+ : | `revoke_role_statement`
+ : | `list_roles_statement`
+ : | `grant_permission_statement`
+ : | `revoke_permission_statement`
+ : | `list_permissions_statement`
+ : | `create_user_statement`
+ : | `alter_user_statement`
+ : | `drop_user_statement`
+ : | `list_users_statement`
+ udf_statement: `create_function_statement`
+ : | `drop_function_statement`
+ : | `create_aggregate_statement`
+ : | `drop_aggregate_statement`
+ udt_statement: `create_type_statement`
+ : | `alter_type_statement`
+ : | `drop_type_statement`
+ trigger_statement: `create_trigger_statement`
+ : | `drop_trigger_statement`
+
+.. _prepared-statements:
+
+Prepared Statements
+^^^^^^^^^^^^^^^^^^^
+
+CQL supports *prepared statements*. Prepared statements are an optimization that allows to parse a query only once but
+execute it multiple times with different concrete values.
+
+Any statement that uses at least one bind marker (see :token:`bind_marker`) will need to be *prepared*. After which the statement
+can be *executed* by provided concrete values for each of its marker. The exact details of how a statement is prepared
+and then executed depends on the CQL driver used and you should refer to your driver documentation.
Added: cassandra/site/src/doc/3.10/_sources/cql/dml.txt
URL: http://svn.apache.org/viewvc/cassandra/site/src/doc/3.10/_sources/cql/dml.txt?rev=1757419&view=auto
==============================================================================
--- cassandra/site/src/doc/3.10/_sources/cql/dml.txt (added)
+++ cassandra/site/src/doc/3.10/_sources/cql/dml.txt Tue Aug 23 19:25:17 2016
@@ -0,0 +1,521 @@
+.. Licensed to the Apache Software Foundation (ASF) under one
+.. or more contributor license agreements. See the NOTICE file
+.. distributed with this work for additional information
+.. regarding copyright ownership. The ASF licenses this file
+.. to you under the Apache License, Version 2.0 (the
+.. "License"); you may not use this file except in compliance
+.. with the License. You may obtain a copy of the License at
+..
+.. http://www.apache.org/licenses/LICENSE-2.0
+..
+.. Unless required by applicable law or agreed to in writing, software
+.. distributed under the License is distributed on an "AS IS" BASIS,
+.. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+.. See the License for the specific language governing permissions and
+.. limitations under the License.
+
+.. highlight:: cql
+
+.. _data-manipulation:
+
+Data Manipulation
+-----------------
+
+This section describes the statements supported by CQL to insert, update, delete and query data.
+
+.. _select-statement:
+
+SELECT
+^^^^^^
+
+Querying data from data is done using a ``SELECT`` statement:
+
+.. productionlist::
+ select_statement: SELECT [ JSON | DISTINCT ] ( `select_clause` | '*' )
+ : FROM `table_name`
+ : [ WHERE `where_clause` ]
+ : [ GROUP BY `group_by_clause` ]
+ : [ ORDER BY `ordering_clause` ]
+ : [ PER PARTITION LIMIT (`integer` | `bind_marker`) ]
+ : [ LIMIT (`integer` | `bind_marker`) ]
+ : [ ALLOW FILTERING ]
+ select_clause: `selector` [ AS `identifier` ] ( ',' `selector` [ AS `identifier` ] )
+ selector: `column_name`
+ : | `term`
+ : | CAST '(' `selector` AS `cql_type` ')'
+ : | `function_name` '(' [ `selector` ( ',' `selector` )* ] ')'
+ : | COUNT '(' '*' ')'
+ where_clause: `relation` ( AND `relation` )*
+ relation: `column_name` `operator` `term`
+ : '(' `column_name` ( ',' `column_name` )* ')' `operator` `tuple_literal`
+ : TOKEN '(' `column_name` ( ',' `column_name` )* ')' `operator` `term`
+ operator: '=' | '<' | '>' | '<=' | '>=' | '!=' | IN | CONTAINS | CONTAINS KEY
+ group_by_clause: `column_name` ( ',' `column_name` )*
+ ordering_clause: `column_name` [ ASC | DESC ] ( ',' `column_name` [ ASC | DESC ] )*
+
+For instance::
+
+ SELECT name, occupation FROM users WHERE userid IN (199, 200, 207);
+ SELECT JSON name, occupation FROM users WHERE userid = 199;
+ SELECT name AS user_name, occupation AS user_occupation FROM users;
+
+ SELECT time, value
+ FROM events
+ WHERE event_type = 'myEvent'
+ AND time > '2011-02-03'
+ AND time <= '2012-01-01'
+
+ SELECT COUNT (*) AS user_count FROM users;
+
+The ``SELECT`` statements reads one or more columns for one or more rows in a table. It returns a result-set of the rows
+matching the request, where each row contains the values for the selection corresponding to the query. Additionally,
+:ref:`functions <cql-functions>` including :ref:`aggregation <aggregate-functions>` ones can be applied to the result.
+
+A ``SELECT`` statement contains at least a :ref:`selection clause <selection-clause>` and the name of the table on which
+the selection is on (note that CQL does **not** joins or sub-queries and thus a select statement only apply to a single
+table). In most case, a select will also have a :ref:`where clause <where-clause>` and it can optionally have additional
+clauses to :ref:`order <ordering-clause>` or :ref:`limit <limit-clause>` the results. Lastly, :ref:`queries that require
+filtering <allow-filtering>` can be allowed if the ``ALLOW FILTERING`` flag is provided.
+
+.. _selection-clause:
+
+Selection clause
+~~~~~~~~~~~~~~~~
+
+The :token:`select_clause` determines which columns needs to be queried and returned in the result-set, as well as any
+transformation to apply to this result before returning. It consists of a comma-separated list of *selectors* or,
+alternatively, of the wildcard character (``*``) to select all the columns defined in the table.
+
+Selectors
+`````````
+
+A :token:`selector` can be one of:
+
+- A column name of the table selected, to retrieve the values for that column.
+- A term, which is usually used nested inside other selectors like functions (if a term is selected directly, then the
+ corresponding column of the result-set will simply have the value of this term for every row returned).
+- A casting, which allows to convert a nested selector to a (compatible) type.
+- A function call, where the arguments are selector themselves. See the section on :ref:`functions <cql-functions>` for
+ more details.
+- The special call ``COUNT(*)`` to the :ref:`COUNT function <count-function>`, which counts all non-null results.
+
+Aliases
+```````
+
+Every *top-level* selector can also be aliased (using `AS`). If so, the name of the corresponding column in the result
+set will be that of the alias. For instance::
+
+ // Without alias
+ SELECT intAsBlob(4) FROM t;
+
+ // intAsBlob(4)
+ // --------------
+ // 0x00000004
+
+ // With alias
+ SELECT intAsBlob(4) AS four FROM t;
+
+ // four
+ // ------------
+ // 0x00000004
+
+.. note:: Currently, aliases aren't recognized anywhere else in the statement where they are used (not in the ``WHERE``
+ clause, not in the ``ORDER BY`` clause, ...). You must use the orignal column name instead.
+
+
+``WRITETIME`` and ``TTL`` function
+```````````````````````````````````
+
+Selection supports two special functions (that aren't allowed anywhere else): ``WRITETIME`` and ``TTL``. Both function
+take only one argument and that argument *must* be a column name (so for instance ``TTL(3)`` is invalid).
+
+Those functions allow to retrieve meta-information that are stored internally for each column, namely:
+
+- the timestamp of the value of the column for ``WRITETIME``.
+- the remaining time to live (in seconds) for the value of the column if it set to expire (and ``null`` otherwise).
+
+.. _where-clause:
+
+The ``WHERE`` clause
+~~~~~~~~~~~~~~~~~~~~
+
+The ``WHERE`` clause specifies which rows must be queried. It is composed of relations on the columns that are part of
+the ``PRIMARY KEY`` and/or have a `secondary index <#createIndexStmt>`__ defined on them.
+
+Not all relations are allowed in a query. For instance, non-equal relations (where ``IN`` is considered as an equal
+relation) on a partition key are not supported (but see the use of the ``TOKEN`` method below to do non-equal queries on
+the partition key). Moreover, for a given partition key, the clustering columns induce an ordering of rows and relations
+on them is restricted to the relations that allow to select a **contiguous** (for the ordering) set of rows. For
+instance, given::
+
+ CREATE TABLE posts (
+ userid text,
+ blog_title text,
+ posted_at timestamp,
+ entry_title text,
+ content text,
+ category int,
+ PRIMARY KEY (userid, blog_title, posted_at)
+ )
+
+The following query is allowed::
+
+ SELECT entry_title, content FROM posts
+ WHERE userid = 'john doe'
+ AND blog_title='John''s Blog'
+ AND posted_at >= '2012-01-01' AND posted_at < '2012-01-31'
+
+But the following one is not, as it does not select a contiguous set of rows (and we suppose no secondary indexes are
+set)::
+
+ // Needs a blog_title to be set to select ranges of posted_at
+ SELECT entry_title, content FROM posts
+ WHERE userid = 'john doe'
+ AND posted_at >= '2012-01-01' AND posted_at < '2012-01-31'
+
+When specifying relations, the ``TOKEN`` function can be used on the ``PARTITION KEY`` column to query. In that case,
+rows will be selected based on the token of their ``PARTITION_KEY`` rather than on the value. Note that the token of a
+key depends on the partitioner in use, and that in particular the RandomPartitioner won't yield a meaningful order. Also
+note that ordering partitioners always order token values by bytes (so even if the partition key is of type int,
+``token(-1) > token(0)`` in particular). Example::
+
+ SELECT * FROM posts
+ WHERE token(userid) > token('tom') AND token(userid) < token('bob')
+
+Moreover, the ``IN`` relation is only allowed on the last column of the partition key and on the last column of the full
+primary key.
+
+It is also possible to “group” ``CLUSTERING COLUMNS`` together in a relation using the tuple notation. For instance::
+
+ SELECT * FROM posts
+ WHERE userid = 'john doe'
+ AND (blog_title, posted_at) > ('John''s Blog', '2012-01-01')
+
+will request all rows that sorts after the one having “John's Blog” as ``blog_tile`` and '2012-01-01' for ``posted_at``
+in the clustering order. In particular, rows having a ``post_at <= '2012-01-01'`` will be returned as long as their
+``blog_title > 'John''s Blog'``, which would not be the case for::
+
+ SELECT * FROM posts
+ WHERE userid = 'john doe'
+ AND blog_title > 'John''s Blog'
+ AND posted_at > '2012-01-01'
+
+The tuple notation may also be used for ``IN`` clauses on clustering columns::
+
+ SELECT * FROM posts
+ WHERE userid = 'john doe'
+ AND (blog_title, posted_at) IN (('John''s Blog', '2012-01-01'), ('Extreme Chess', '2014-06-01'))
+
+The ``CONTAINS`` operator may only be used on collection columns (lists, sets, and maps). In the case of maps,
+``CONTAINS`` applies to the map values. The ``CONTAINS KEY`` operator may only be used on map columns and applies to the
+map keys.
+
+.. _group-by-clause:
+
+Grouping results
+~~~~~~~~~~~~~~~~
+
+The ``GROUP BY`` option allows to condense into a single row all selected rows that share the same values for a set
+of columns.
+
+Using the ``GROUP BY`` option, it is only possible to group rows at the partition key level or at a clustering column
+level. By consequence, the ``GROUP BY`` option only accept as arguments primary key column names in the primary key
+order. If a primary key column is restricted by an equality restriction it is not required to be present in the
+``GROUP BY`` clause.
+
+Aggregate functions will produce a separate value for each group. If no ``GROUP BY`` clause is specified,
+aggregates functions will produce a single value for all the rows.
+
+If a column is selected without an aggregate function, in a statement with a ``GROUP BY``, the first value encounter
+in each group will be returned.
+
+.. _ordering-clause:
+
+Ordering results
+~~~~~~~~~~~~~~~~
+
+The ``ORDER BY`` clause allows to select the order of the returned results. It takes as argument a list of column names
+along with the order for the column (``ASC`` for ascendant and ``DESC`` for descendant, omitting the order being
+equivalent to ``ASC``). Currently the possible orderings are limited by the :ref:`clustering order <clustering-order>`
+defined on the table:
+
+- if the table has been defined without any specific ``CLUSTERING ORDER``, then then allowed orderings are the order
+ induced by the clustering columns and the reverse of that one.
+- otherwise, the orderings allowed are the order of the ``CLUSTERING ORDER`` option and the reversed one.
+
+.. _limit-clause:
+
+Limiting results
+~~~~~~~~~~~~~~~~
+
+The ``LIMIT`` option to a ``SELECT`` statement limits the number of rows returned by a query, while the ``PER PARTITION
+LIMIT`` option limits the number of rows returned for a given partition by the query. Note that both type of limit can
+used in the same statement.
+
+.. _allow-filtering:
+
+Allowing filtering
+~~~~~~~~~~~~~~~~~~
+
+By default, CQL only allows select queries that don't involve “filtering” server side, i.e. queries where we know that
+all (live) record read will be returned (maybe partly) in the result set. The reasoning is that those “non filtering”
+queries have predictable performance in the sense that they will execute in a time that is proportional to the amount of
+data **returned** by the query (which can be controlled through ``LIMIT``).
+
+The ``ALLOW FILTERING`` option allows to explicitly allow (some) queries that require filtering. Please note that a
+query using ``ALLOW FILTERING`` may thus have unpredictable performance (for the definition above), i.e. even a query
+that selects a handful of records **may** exhibit performance that depends on the total amount of data stored in the
+cluster.
+
+For instance, considering the following table holding user profiles with their year of birth (with a secondary index on
+it) and country of residence::
+
+ CREATE TABLE users (
+ username text PRIMARY KEY,
+ firstname text,
+ lastname text,
+ birth_year int,
+ country text
+ )
+
+ CREATE INDEX ON users(birth_year);
+
+Then the following queries are valid::
+
+ SELECT * FROM users;
+ SELECT * FROM users WHERE birth_year = 1981;
+
+because in both case, Cassandra guarantees that these queries performance will be proportional to the amount of data
+returned. In particular, if no users are born in 1981, then the second query performance will not depend of the number
+of user profile stored in the database (not directly at least: due to secondary index implementation consideration, this
+query may still depend on the number of node in the cluster, which indirectly depends on the amount of data stored.
+Nevertheless, the number of nodes will always be multiple number of magnitude lower than the number of user profile
+stored). Of course, both query may return very large result set in practice, but the amount of data returned can always
+be controlled by adding a ``LIMIT``.
+
+However, the following query will be rejected::
+
+ SELECT * FROM users WHERE birth_year = 1981 AND country = 'FR';
+
+because Cassandra cannot guarantee that it won't have to scan large amount of data even if the result to those query is
+small. Typically, it will scan all the index entries for users born in 1981 even if only a handful are actually from
+France. However, if you “know what you are doing”, you can force the execution of this query by using ``ALLOW
+FILTERING`` and so the following query is valid::
+
+ SELECT * FROM users WHERE birth_year = 1981 AND country = 'FR' ALLOW FILTERING;
+
+.. _insert-statement:
+
+INSERT
+^^^^^^
+
+Inserting data for a row is done using an ``INSERT`` statement:
+
+.. productionlist::
+ insert_statement: INSERT INTO `table_name` ( `names_values` | `json_clause` )
+ : [ IF NOT EXISTS ]
+ : [ USING `update_parameter` ( AND `update_parameter` )* ]
+ names_values: `names` VALUES `tuple_literal`
+ json_clause: JSON `string` [ DEFAULT ( NULL | UNSET ) ]
+ names: '(' `column_name` ( ',' `column_name` )* ')'
+
+For instance::
+
+ INSERT INTO NerdMovies (movie, director, main_actor, year)
+ VALUES ('Serenity', 'Joss Whedon', 'Nathan Fillion', 2005)
+ USING TTL 86400;
+
+ INSERT INTO NerdMovies JSON '{"movie": "Serenity",
+ "director": "Joss Whedon",
+ "year": 2005}';
+
+The ``INSERT`` statement writes one or more columns for a given row in a table. Note that since a row is identified by
+its ``PRIMARY KEY``, at least the columns composing it must be specified. The list of columns to insert to must be
+supplied when using the ``VALUES`` syntax. When using the ``JSON`` syntax, they are optional. See the
+section on :ref:`JSON support <cql-json>` for more detail.
+
+Note that unlike in SQL, ``INSERT`` does not check the prior existence of the row by default: the row is created if none
+existed before, and updated otherwise. Furthermore, there is no mean to know which of creation or update happened.
+
+It is however possible to use the ``IF NOT EXISTS`` condition to only insert if the row does not exist prior to the
+insertion. But please note that using ``IF NOT EXISTS`` will incur a non negligible performance cost (internally, Paxos
+will be used) so this should be used sparingly.
+
+All updates for an ``INSERT`` are applied atomically and in isolation.
+
+Please refer to the :ref:`UPDATE <update-parameters>` section for informations on the :token:`update_parameter`.
+
+Also note that ``INSERT`` does not support counters, while ``UPDATE`` does.
+
+.. _update-statement:
+
+UPDATE
+^^^^^^
+
+Updating a row is done using an ``UPDATE`` statement:
+
+.. productionlist::
+ update_statement: UPDATE `table_name`
+ : [ USING `update_parameter` ( AND `update_parameter` )* ]
+ : SET `assignment` ( ',' `assignment` )*
+ : WHERE `where_clause`
+ : [ IF ( EXISTS | `condition` ( AND `condition` )*) ]
+ update_parameter: ( TIMESTAMP | TTL ) ( `integer` | `bind_marker` )
+ assignment: `simple_selection` '=' `term`
+ :| `column_name` '=' `column_name` ( '+' | '-' ) `term`
+ :| `column_name` '=' `list_literal` '+' `column_name`
+ simple_selection: `column_name`
+ :| `column_name` '[' `term` ']'
+ :| `column_name` '.' `field_name
+ condition: `simple_selection` `operator` `term`
+
+For instance::
+
+ UPDATE NerdMovies USING TTL 400
+ SET director = 'Joss Whedon',
+ main_actor = 'Nathan Fillion',
+ year = 2005
+ WHERE movie = 'Serenity';
+
+ UPDATE UserActions
+ SET total = total + 2
+ WHERE user = B70DE1D0-9908-4AE3-BE34-5573E5B09F14
+ AND action = 'click';
+
+The ``UPDATE`` statement writes one or more columns for a given row in a table. The :token:`where_clause` is used to
+select the row to update and must include all columns composing the ``PRIMARY KEY``. Non primary key columns are then
+set using the ``SET`` keyword.
+
+Note that unlike in SQL, ``UPDATE`` does not check the prior existence of the row by default (except through ``IF``, see
+below): the row is created if none existed before, and updated otherwise. Furthermore, there are no means to know
+whether a creation or update occurred.
+
+It is however possible to use the conditions on some columns through ``IF``, in which case the row will not be updated
+unless the conditions are met. But, please note that using ``IF`` conditions will incur a non-negligible performance
+cost (internally, Paxos will be used) so this should be used sparingly.
+
+In an ``UPDATE`` statement, all updates within the same partition key are applied atomically and in isolation.
+
+Regarding the :token:`assignment`:
+
+- ``c = c + 3`` is used to increment/decrement counters. The column name after the '=' sign **must** be the same than
+ the one before the '=' sign. Note that increment/decrement is only allowed on counters, and are the *only* update
+ operations allowed on counters. See the section on :ref:`counters <counters>` for details.
+- ``id = id + <some-collection>`` and ``id[value1] = value2`` are for collections, see the :ref:`relevant section
+ <collections>` for details.
+- ``id.field = 3`` is for setting the value of a field on a non-frozen user-defined types. see the :ref:`relevant section
+ <udts>` for details.
+
+.. _update-parameters:
+
+Update parameters
+~~~~~~~~~~~~~~~~~
+
+The ``UPDATE``, ``INSERT`` (and ``DELETE`` and ``BATCH`` for the ``TIMESTAMP``) statements support the following
+parameters:
+
+- ``TIMESTAMP``: sets the timestamp for the operation. If not specified, the coordinator will use the current time (in
+ microseconds) at the start of statement execution as the timestamp. This is usually a suitable default.
+- ``TTL``: specifies an optional Time To Live (in seconds) for the inserted values. If set, the inserted values are
+ automatically removed from the database after the specified time. Note that the TTL concerns the inserted values, not
+ the columns themselves. This means that any subsequent update of the column will also reset the TTL (to whatever TTL
+ is specified in that update). By default, values never expire. A TTL of 0 is equivalent to no TTL. If the table has a
+ default_time_to_live, a TTL of 0 will remove the TTL for the inserted or updated values. A TTL of ``null`` is equivalent
+ to inserting with a TTL of 0.
+
+.. _delete_statement:
+
+DELETE
+^^^^^^
+
+Deleting rows or parts of rows uses the ``DELETE`` statement:
+
+.. productionlist::
+ delete_statement: DELETE [ `simple_selection` ( ',' `simple_selection` ) ]
+ : FROM `table_name`
+ : [ USING `update_parameter` ( AND `update_parameter` )* ]
+ : WHERE `where_clause`
+ : [ IF ( EXISTS | `condition` ( AND `condition` )*) ]
+
+For instance::
+
+ DELETE FROM NerdMovies USING TIMESTAMP 1240003134
+ WHERE movie = 'Serenity';
+
+ DELETE phone FROM Users
+ WHERE userid IN (C73DE1D3-AF08-40F3-B124-3FF3E5109F22, B70DE1D0-9908-4AE3-BE34-5573E5B09F14);
+
+The ``DELETE`` statement deletes columns and rows. If column names are provided directly after the ``DELETE`` keyword,
+only those columns are deleted from the row indicated by the ``WHERE`` clause. Otherwise, whole rows are removed.
+
+The ``WHERE`` clause specifies which rows are to be deleted. Multiple rows may be deleted with one statement by using an
+``IN`` operator. A range of rows may be deleted using an inequality operator (such as ``>=``).
+
+``DELETE`` supports the ``TIMESTAMP`` option with the same semantics as in :ref:`updates <update-parameters>`.
+
+In a ``DELETE`` statement, all deletions within the same partition key are applied atomically and in isolation.
+
+A ``DELETE`` operation can be conditional through the use of an ``IF`` clause, similar to ``UPDATE`` and ``INSERT``
+statements. However, as with ``INSERT`` and ``UPDATE`` statements, this will incur a non-negligible performance cost
+(internally, Paxos will be used) and so should be used sparingly.
+
+.. _batch_statement:
+
+BATCH
+^^^^^
+
+Multiple ``INSERT``, ``UPDATE`` and ``DELETE`` can be executed in a single statement by grouping them through a
+``BATCH`` statement:
+
+.. productionlist::
+ batch_statement: BEGIN [ UNLOGGED | COUNTER ] BATCH
+ : [ USING `update_parameter` ( AND `update_parameter` )* ]
+ : `modification_statement` ( ';' `modification_statement` )*
+ : APPLY BATCH
+ modification_statement: `insert_statement` | `update_statement` | `delete_statement`
+
+For instance::
+
+ BEGIN BATCH
+ INSERT INTO users (userid, password, name) VALUES ('user2', 'ch@ngem3b', 'second user');
+ UPDATE users SET password = 'ps22dhds' WHERE userid = 'user3';
+ INSERT INTO users (userid, password) VALUES ('user4', 'ch@ngem3c');
+ DELETE name FROM users WHERE userid = 'user1';
+ APPLY BATCH;
+
+The ``BATCH`` statement group multiple modification statements (insertions/updates and deletions) into a single
+statement. It serves several purposes:
+
+- It saves network round-trips between the client and the server (and sometimes between the server coordinator and the
+ replicas) when batching multiple updates.
+- All updates in a ``BATCH`` belonging to a given partition key are performed in isolation.
+- By default, all operations in the batch are performed as *logged*, to ensure all mutations eventually complete (or
+ none will). See the notes on :ref:`UNLOGGED batches <unlogged-batches>` for more details.
+
+Note that:
+
+- ``BATCH`` statements may only contain ``UPDATE``, ``INSERT`` and ``DELETE`` statements (not other batches for instance).
+- Batches are *not* a full analogue for SQL transactions.
+- If a timestamp is not specified for each operation, then all operations will be applied with the same timestamp
+ (either one generated automatically, or the timestamp provided at the batch level). Due to Cassandra's conflict
+ resolution procedure in the case of `timestamp ties <http://wiki.apache.org/cassandra/FAQ#clocktie>`__, operations may
+ be applied in an order that is different from the order they are listed in the ``BATCH`` statement. To force a
+ particular operation ordering, you must specify per-operation timestamps.
+
+.. _unlogged-batches:
+
+``UNLOGGED`` batches
+~~~~~~~~~~~~~~~~~~~~
+
+By default, Cassandra uses a batch log to ensure all operations in a batch eventually complete or none will (note
+however that operations are only isolated within a single partition).
+
+There is a performance penalty for batch atomicity when a batch spans multiple partitions. If you do not want to incur
+this penalty, you can tell Cassandra to skip the batchlog with the ``UNLOGGED`` option. If the ``UNLOGGED`` option is
+used, a failed batch might leave the patch only partly applied.
+
+``COUNTER`` batches
+~~~~~~~~~~~~~~~~~~~
+
+Use the ``COUNTER`` option for batched counter updates. Unlike other
+updates in Cassandra, counter updates are not idempotent.