From 0ee8895b27c2aa18260c73ec5c1941e48fbeaf75 Mon Sep 17 00:00:00 2001 From: Robert Stupp Date: Fri, 27 Nov 2015 15:24:51 +0100 Subject: [PATCH] Show CQL help in cqlsh in web browser patch by Robert Stupp; reviewed by Paulo Motta for CASSANDRA-7225 --- CHANGES.txt | 1 + bin/cqlsh.py | 61 +- build.xml | 7 +- conf/cqlshrc.sample | 17 + debian/rules | 3 +- pylib/cqlshlib/helptopics.py | 1070 +++------------------------------- 6 files changed, 181 insertions(+), 978 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index ce82bd0ca2..af1a1869a7 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,5 @@ 2.2.4 + * Show CQL help in cqlsh in web browser (CASSANDRA-7225) * Serialize on disk the proper SSTable compression ratio (CASSANDRA-10775) * Reject index queries while the index is building (CASSANDRA-8505) * CQL.textile syntax incorrectly includes optional keyspace for aggregate SFUNC and FINALFUNC (CASSANDRA-10747) diff --git a/bin/cqlsh.py b/bin/cqlsh.py index 28054bac2e..e7dc1212dc 100644 --- a/bin/cqlsh.py +++ b/bin/cqlsh.py @@ -45,6 +45,7 @@ import sys import time import traceback import warnings +import webbrowser from contextlib import contextmanager from functools import partial from glob import glob @@ -71,6 +72,31 @@ CQL_LIB_PREFIX = 'cassandra-driver-internal-only-' CASSANDRA_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), '..') +if os.path.exists(CASSANDRA_PATH + '/doc/cql3/CQL.html'): + # default location of local CQL.html + CASSANDRA_CQL_HTML = 'file://' + CASSANDRA_PATH + '/doc/cql3/CQL.html' +elif os.path.exists('/usr/share/doc/cassandra/CQL.html'): + # fallback to package file + CASSANDRA_CQL_HTML = 'file:///usr/share/doc/cassandra/CQL.html' +else: + # fallback to online version + CASSANDRA_CQL_HTML = 'https://cassandra.apache.org/doc/cql3/CQL-2.2.html' + +# On Linux, the Python webbrowser module uses the 'xdg-open' executable +# to open a file/URL. But that only works, if the current session has been +# opened from _within_ a desktop environment. I.e. 'xdg-open' will fail, +# if the session's been opened via ssh to a remote box. +# +# Use 'python' to get some information about the detected browsers. +# >>> import webbrowser +# >>> webbrowser._tryorder +# >>> webbrowser._browser +# +if webbrowser._tryorder[0] == 'xdg-open' and os.environ.get('XDG_DATA_DIRS', '') == '': + # only on Linux (some OS with xdg-open) + webbrowser._tryorder.remove('xdg-open') + webbrowser._tryorder.append('xdg-open') + # use bundled libs for python-cql and thrift, if available. if there # is a ../lib dir, use bundled libs there preferentially. ZIPLIB_DIRS = [os.path.join(CASSANDRA_PATH, 'lib')] @@ -164,6 +190,9 @@ parser.add_option("-C", "--color", action='store_true', dest='color', help='Always use color output') parser.add_option("--no-color", action='store_false', dest='color', help='Never use color output') +parser.add_option("--browser", dest='browser', help="""The browser to use to display CQL help, where BROWSER can be: + - one of the supported browsers in https://docs.python.org/2/library/webbrowser.html. + - browser path followed by %s, example: /usr/bin/google-chrome-stable %s""") parser.add_option('--ssl', action='store_true', help='Use SSL', default=False) parser.add_option("-u", "--username", help="Authenticate as user.") parser.add_option("-p", "--password", help="Authenticate using password.") @@ -630,7 +659,7 @@ class Shell(cmd.Cmd): def __init__(self, hostname, port, color=False, username=None, password=None, encoding=None, stdin=None, tty=True, - completekey=DEFAULT_COMPLETEKEY, use_conn=None, + completekey=DEFAULT_COMPLETEKEY, browser=None, use_conn=None, cqlver=DEFAULT_CQLVER, keyspace=None, tracing_enabled=False, expand_enabled=False, display_nanotime_format=DEFAULT_NANOTIME_FORMAT, @@ -674,6 +703,9 @@ class Shell(cmd.Cmd): else: self.session = self.conn.connect() + if browser == "": + browser = None + self.browser = browser self.color = color self.display_nanotime_format = display_nanotime_format @@ -2178,10 +2210,33 @@ class Shell(cmd.Cmd): doc = getattr(self, 'do_' + t.lower()).__doc__ self.stdout.write(doc + "\n") elif t.lower() in cqldocs.get_help_topics(): - cqldocs.print_help_topic(t) + urlpart = cqldocs.get_help_topic(t) + if urlpart is not None: + url = "%s#%s" % (CASSANDRA_CQL_HTML, urlpart) + if self.browser is not None: + webbrowser.get(self.browser).open_new_tab(url) + else: + webbrowser.open_new_tab(url) else: self.printerr("*** No help on %s" % (t,)) + def do_unicode(self, parsed): + """ + Textual input/output + + When control characters, or other characters which can't be encoded + in your current locale, are found in values of 'text' or 'ascii' + types, it will be shown as a backslash escape. If color is enabled, + any such backslash escapes will be shown in a different color from + the surrounding text. + + Unicode code points in your data will be output intact, if the + encoding for your locale is capable of decoding them. If you prefer + that non-ascii characters be shown with Python-style "\\uABCD" + escape sequences, invoke cqlsh with an ASCII locale (for example, + by setting the $LANG environment variable to "C"). + """ + def do_paging(self, parsed): """ PAGING [cqlsh] @@ -2524,6 +2579,7 @@ def read_options(cmdlineargs, environment): optvalues.username = option_with_default(configs.get, 'authentication', 'username') optvalues.password = option_with_default(rawconfigs.get, 'authentication', 'password') optvalues.keyspace = option_with_default(configs.get, 'authentication', 'keyspace') + optvalues.browser = option_with_default(configs.get, 'ui', 'browser', None) optvalues.completekey = option_with_default(configs.get, 'ui', 'completekey', DEFAULT_COMPLETEKEY) optvalues.color = option_with_default(configs.getboolean, 'ui', 'color') @@ -2664,6 +2720,7 @@ def main(options, hostname, port): stdin=stdin, tty=options.tty, completekey=options.completekey, + browser=options.browser, cqlver=options.cqlversion, keyspace=options.keyspace, display_timestamp_format=options.time_format, diff --git a/build.xml b/build.xml index fe30964897..6110bb057b 100644 --- a/build.xml +++ b/build.xml @@ -776,7 +776,7 @@ depends="maven-ant-tasks-retrieve-build,build-project" description="Compile Cassandra classes"/> - @@ -1013,6 +1013,11 @@ + + + + + diff --git a/conf/cqlshrc.sample b/conf/cqlshrc.sample index 6558ad2d8e..302d25f029 100644 --- a/conf/cqlshrc.sample +++ b/conf/cqlshrc.sample @@ -25,6 +25,23 @@ password = !!bang!!$ color = on completekey = tab +; To use another than the system default browser for cqlsh HELP to open +; the CQL doc HTML, use the 'browser' preference. +; If the field value is empty or not specified, cqlsh will use the +; default browser (specifying 'browser = default' does not work). +; +; Supported browsers are those supported by the Python webbrowser module. +; (https://docs.python.org/2/library/webbrowser.html). +; +; Hint: to use Google Chome, use +; 'browser = open -a /Applications/Google\ Chrome.app %s' on Mac OS X and +; 'browser = /usr/bin/google-chrome-stable %s' on Linux and +; 'browser = C:/Program Files (x86)/Google/Chrome/Application/chrome.exe %s' on Windows. +; +; This setting can be overridden with the --browser command line option. +; +;browser = + [cql] version = 3.1.5 diff --git a/debian/rules b/debian/rules index d0d22a9663..fedb32eae3 100755 --- a/debian/rules +++ b/debian/rules @@ -28,6 +28,7 @@ build-stamp: patch-stamp dh_testdir printf "version=%s" $(VERSION) > build.properties + $(ANT) generate-cql-html $(ANT) jar cd pylib && python setup.py install --no-compile --install-layout deb \ --root $(CURDIR)/debian/cassandra @@ -62,7 +63,7 @@ binary-indep: build install dh_testroot dh_installchangelogs dh_installinit -u'start 50 2 3 4 5 . stop 50 0 1 6 .' - dh_installdocs README.asc CHANGES.txt NEWS.txt + dh_installdocs README.asc CHANGES.txt NEWS.txt doc/cql3/CQL.css doc/cql3/CQL.html dh_installexamples tools/*.yaml dh_bash-completion dh_compress diff --git a/pylib/cqlshlib/helptopics.py b/pylib/cqlshlib/helptopics.py index 8e296e14a9..c2eebe365a 100644 --- a/pylib/cqlshlib/helptopics.py +++ b/pylib/cqlshlib/helptopics.py @@ -17,1017 +17,139 @@ from .cql3handling import simple_cql_types -class CQLHelpTopics(object): +class CQL3HelpTopics(object): def get_help_topics(self): return [t[5:] for t in dir(self) if t.startswith('help_')] - def print_help_topic(self, topic): - getattr(self, 'help_' + topic.lower())() + def get_help_topic(self, topic): + return getattr(self, 'help_' + topic.lower())() def help_types(self): - print "\n CQL types recognized by this version of cqlsh:\n" - for t in simple_cql_types: - print ' ' + t - print """ - For information on the various recognizable input formats for these - types, or on controlling the formatting of cqlsh query output, see - one of the following topics: + return 'types' - HELP TIMESTAMP_INPUT - HELP DATE_INPUT - HELP TIME_INPUT - HELP BLOB_INPUT - HELP UUID_INPUT - HELP BOOLEAN_INPUT - HELP INT_INPUT + def help_timestamp(self): + return 'usingtimestamps' - HELP TEXT_OUTPUT - HELP TIMESTAMP_OUTPUT - """ + def help_date(self): + return 'usingdates' - def help_timestamp_input(self): - print """ - Timestamp input + def help_time(self): + return 'usingtime' - CQL supports any of the following ISO 8601 formats for timestamp - specification: + def help_blob(self): + return 'constants' - yyyy-mm-dd HH:mm - yyyy-mm-dd HH:mm:ss - yyyy-mm-dd HH:mmZ - yyyy-mm-dd HH:mm:ssZ - yyyy-mm-dd'T'HH:mm - yyyy-mm-dd'T'HH:mmZ - yyyy-mm-dd'T'HH:mm:ss - yyyy-mm-dd'T'HH:mm:ssZ - yyyy-mm-dd - yyyy-mm-ddZ + def help_uuid(self): + return 'constants' - The Z in these formats refers to an RFC-822 4-digit time zone, - expressing the time zone's difference from UTC. For example, a - timestamp in Pacific Standard Time might be given thus: + def help_boolean(self): + return 'constants' - 2012-01-20 16:14:12-0800 + def help_int(self): + return 'constants' - If no time zone is supplied, the current time zone for the Cassandra - server node will be used. - """ + def help_counter(self): + return 'counters' - def help_date_input(self): - print """ - Date input - - CQL supports the following format for date specification: - - yyyy-mm-dd - """ - - def help_time_input(self): - print """ - Time input - - CQL supports the following format for time specification: - - HH:MM:SS - HH:MM:SS.mmm - HH:MM:SS.mmmuuu - HH:MM:SS.mmmuuunnn - """ - - def help_blob_input(self): - print """ - Blob input - - CQL blob data must be specified in a string literal as hexidecimal - data. Example: to store the ASCII values for the characters in the - string "CQL", use '43514c'. - """ - - def help_uuid_input(self): - print """ - UUID input - - UUIDs may be specified in CQL using 32 hexidecimal characters, - split up using dashes in the standard UUID format: - - XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX - """ - - def help_boolean_input(self): - print """ - Boolean input - - CQL accepts the strings 'true' and 'false' (case insensitive) - as input for boolean types. - """ - - def help_int_input(self): - print """ - Integer input - - CQL accepts the following integer types: - tinyint - 1-byte signed integer - smallint - 2-byte signed integer - int - 4-byte signed integer - bigint - 8-byte signed integer - """ - - def help_timestamp_output(self): - print """ - Timestamp output - - Cqlsh will display timestamps in the following format by default: - - yyyy-mm-dd HH:mm:ssZ - - which is a format acceptable as CQL timestamp input as well. - The output format can be changed by setting 'time_format' property - in the [ui] section of .cqlshrc file. - """ - - def help_text_output(self): - print """ - Textual output - - When control characters, or other characters which can't be encoded - in your current locale, are found in values of 'text' or 'ascii' - types, it will be shown as a backslash escape. If color is enabled, - any such backslash escapes will be shown in a different color from - the surrounding text. - - Unicode code points in your data will be output intact, if the - encoding for your locale is capable of decoding them. If you prefer - that non-ascii characters be shown with Python-style "\\uABCD" - escape sequences, invoke cqlsh with an ASCII locale (for example, - by setting the $LANG environment variable to "C"). - """ - help_ascii_output = help_text_output - - def help_create_index(self): - print """ - CREATE INDEX [] ON ( ); - - A CREATE INDEX statement is used to create a new, automatic secondary - index on the given CQL table, for the named column. A name for the - index itself can be specified before the ON keyword, if desired. A - single column name must be specified inside the parentheses. It is not - necessary for the column to exist on any current rows (Cassandra is - schema-optional), but the column must already have a type (specified - during the CREATE TABLE, or added afterwards with ALTER TABLE). - """ - - def help_drop(self): - print """ - There are different variants of DROP. For more information, see - one of the following: - - HELP DROP_KEYSPACE; - HELP DROP_TABLE; - HELP DROP_INDEX; - HELP DROP_FUNCTION; - HELP DROP_AGGREGATE; - """ - - def help_drop_keyspace(self): - print """ - DROP KEYSPACE ; - - A DROP KEYSPACE statement results in the immediate, irreversible - removal of a keyspace, including all column families in it, and all - data contained in those column families. - """ - - def help_drop_table(self): - print """ - DROP TABLE ; - - A DROP TABLE statement results in the immediate, irreversible - removal of a CQL table and the underlying column family, including all - data contained in it. - """ - help_drop_columnfamily = help_drop_table - - def help_drop_index(self): - print """ - DROP INDEX ; - - A DROP INDEX statement is used to drop an existing secondary index. - """ - - def help_drop_function(self): - print """ - DROP FUNCTION ( IF EXISTS )? - ( '.' )? - ( '(' ( ',' )* ')' )? - - DROP FUNCTION statement removes a function created using CREATE FUNCTION. - You must specify the argument types (signature) of the function to drop if there - are multiple functions with the same name but a different signature - (overloaded functions). - - DROP FUNCTION with the optional IF EXISTS keywords drops a function if it exists. - """ - - def help_drop_aggregate(self): - print """ - DROP AGGREGATE ( IF EXISTS )? - ( '.' )? - ( '(' ( ',' )* ')' )? - - The DROP AGGREGATE statement removes an aggregate created using CREATE AGGREGATE. - You must specify the argument types of the aggregate to drop if there are multiple - aggregates with the same name but a different signature (overloaded aggregates). - - DROP AGGREGATE with the optional IF EXISTS keywords drops an aggregate if it exists, - and does nothing if a function with the signature does not exist. - - Signatures for user-defined aggregates follow the same rules as for - user-defined functions. - """ - - def help_truncate(self): - print """ - TRUNCATE ; - - TRUNCATE accepts a single argument for the table name, and permanently - removes all data from it. - """ - - def help_create(self): - print """ - There are different variants of CREATE. For more information, see - one of the following: - - HELP CREATE_KEYSPACE; - HELP CREATE_TABLE; - HELP CREATE_INDEX; - HELP CREATE_FUNCTION; - HELP CREATE_AGGREGATE; - """ + def help_text(self): + return 'constants' + help_ascii = help_text def help_use(self): - print """ - USE ; - - Tells cqlsh and the connected Cassandra instance that you will be - working in the given keyspace. All subsequent operations on tables - or indexes will be in the context of this keyspace, unless otherwise - specified, until another USE command is issued or the connection - terminates. - - As always, when a keyspace name does not work as a normal identifier or - number, it can be quoted using double quotes. - """ - - def help_create_aggregate(self): - print """ - CREATE ( OR REPLACE )? AGGREGATE ( IF NOT EXISTS )? - ( '.' )? - '(' ( ',' )* ')' - SFUNC ( '.' )? - STYPE - ( FINALFUNC ( '.' )? )? - ( INITCOND )? - - CREATE AGGREGATE creates or replaces a user-defined aggregate. - - CREATE AGGREGATE with the optional OR REPLACE keywords either creates an aggregate - or replaces an existing one with the same signature. A CREATE AGGREGATE without - OR REPLACE fails if an aggregate with the same signature already exists. - - CREATE AGGREGATE with the optional IF NOT EXISTS keywords either creates an aggregate - if it does not already exist. - - OR REPLACE and IF NOT EXIST cannot be used together. - - Aggregates belong to a keyspace. If no keyspace is specified in , the - current keyspace is used (i.e. the keyspace specified using the USE statement). It is - not possible to create a user-defined aggregate in one of the system keyspaces. - - Signatures for user-defined aggregates follow the same rules as for - user-defined functions. - - STYPE defines the type of the state value and must be specified. - - The optional INITCOND defines the initial state value for the aggregate. It defaults - to null. A non-null INITCOND must be specified for state functions that are declared - with RETURNS NULL ON NULL INPUT. - - SFUNC references an existing function to be used as the state modifying function. The - type of first argument of the state function must match STYPE. The remaining argument - types of the state function must match the argument types of the aggregate function. - State is not updated for state functions declared with RETURNS NULL ON NULL INPUT and - called with null. - - The optional FINALFUNC is called just before the aggregate result is returned. It must - take only one argument with type STYPE. The return type of the FINALFUNC may be a - different type. A final function declared with RETURNS NULL ON NULL INPUT means that - the aggregate's return value will be null, if the last state is null. - - If no FINALFUNC is defined, the overall return type of the aggregate function is STYPE. - If a FINALFUNC is defined, it is the return type of that function. - """ - - def help_create_function(self): - print """ - CREATE ( OR REPLACE )? FUNCTION ( IF NOT EXISTS )? - ( '.' )? - '(' ( ',' )* ')' - ( CALLED | RETURNS NULL ) ON NULL INPUT - RETURNS - LANGUAGE - AS - - CREATE FUNCTION creates or replaces a user-defined function. - - Signatures are used to distinguish individual functions. The signature consists of: - - The fully qualified function name - i.e keyspace plus function-name - The concatenated list of all argument types - - Note that keyspace names, function names and argument types are subject to the default - naming conventions and case-sensitivity rules. - - CREATE FUNCTION with the optional OR REPLACE keywords either creates a function or - replaces an existing one with the same signature. A CREATE FUNCTION without OR REPLACE - fails if a function with the same signature already exists. - - Behavior on invocation with null values must be defined for each function. There are - two options: - - RETURNS NULL ON NULL INPUT declares that the function will always return null if any - of the input arguments is null. CALLED ON NULL INPUT declares that the function will - always be executed. - - If the optional IF NOT EXISTS keywords are used, the function will only be created if - another function with the same signature does not exist. - - OR REPLACE and IF NOT EXIST cannot be used together. - - Functions belong to a keyspace. If no keyspace is specified in , the - current keyspace is used (i.e. the keyspace specified using the USE statement). - It is not possible to create a user-defined function in one of the system keyspaces. - """ - - def help_create_table(self): - print """ - CREATE TABLE ( PRIMARY KEY [, - [, ...]] ) - [WITH = [AND = [...]]]; - - CREATE TABLE statements create a new CQL table under the current - keyspace. Valid table names are strings of alphanumeric characters and - underscores, which begin with a letter. - - Each table requires a primary key, which will correspond to the - underlying columnfamily key and key validator. It's important to - note that the key type you use must be compatible with the partitioner - in use. For example, OrderPreservingPartitioner and - CollatingOrderPreservingPartitioner both require UTF-8 keys. - - In cql3 mode, a table can have multiple columns composing the primary - key (see HELP COMPOUND_PRIMARY_KEYS). - - For more information, see one of the following: - - HELP CREATE_TABLE_TYPES; - HELP CREATE_TABLE_OPTIONS; - """ - help_create_columnfamily = help_create_table - - def help_compound_primary_keys(self): - print """ - CREATE TABLE ( , type, type, - [, ...]], PRIMARY KEY (, , ); - - CREATE TABLE allows a primary key composed of multiple columns. When this is the case, specify - the columns that take part in the compound key after all columns have been specified. - - , PRIMARY KEY( , , ... ) - - The partitioning key itself can be a compound key, in which case the first element of the PRIMARY KEY - phrase should be parenthesized, as - - PRIMARY KEY ((, ), ) - """ - - def help_create_table_types(self): - print """ - CREATE TABLE: Specifying column types - - CREATE ... (KEY PRIMARY KEY, - othercol ) ... - - It is possible to assign columns a type during table creation. Columns - configured with a type are validated accordingly when a write occurs, - and intelligent CQL drivers and interfaces will be able to decode the - column values correctly when receiving them. Column types are specified - as a parenthesized, comma-separated list of column term and type pairs. - See HELP TYPES; for the list of recognized types. - """ - help_create_columnfamily_types = help_create_table_types - - def help_create_table_options(self): - print """ - CREATE TABLE: Specifying columnfamily options - - CREATE TABLE blah (...) - WITH optionname = val AND otheroption = val2; - - A number of optional keyword arguments can be supplied to control the - configuration of a new CQL table, such as the size of the associated - row and key caches for the underlying Cassandra columnfamily. Consult - your CQL reference for the complete list of options and possible - values. - """ - help_create_columnfamily_options = help_create_table_options - - def help_alter_alter(self): - print """ - ALTER TABLE: altering existing typed columns - - ALTER TABLE addamsFamily ALTER lastKnownLocation TYPE uuid; - - ALTER TABLE ... ALTER changes the expected storage type for a column. - The column must already have a type in the column family metadata. The - column may or may not already exist in current rows-- but be aware that - no validation of existing data is done. The bytes stored in values for - that column will remain unchanged, and if existing data is not - deserializable according to the new type, this may cause your CQL - driver or interface to report errors. - """ - - def help_alter_add(self): - print """ - ALTER TABLE: adding a typed column - - ALTER TABLE addamsFamily ADD gravesite varchar; - - The ALTER TABLE ... ADD variant adds a typed column to a column - family. The column must not already have a type in the column family - metadata. See the warnings on HELP ALTER_ALTER regarding the lack of - validation of existing data; they apply here as well. - """ - - def help_alter_drop(self): - print """ - ALTER TABLE: dropping a typed column - - ALTER TABLE addamsFamily DROP gender; - - An ALTER TABLE ... DROP statement removes the type of a column - from the column family metadata. Note that this does _not_ remove the - column from current rows; it just removes the metadata saying that the - bytes stored under that column are expected to be deserializable - according to a certain type. - """ - - def help_alter_with(self): - print """ - ALTER TABLE: changing column family properties - - ALTER TABLE addamsFamily WITH comment = 'Glad to be here!' - AND read_repair_chance = 0.2; - - An ALTER TABLE ... WITH statement makes adjustments to the - table properties, as defined when the table was created (see - HELP CREATE_TABLE_OPTIONS and your Cassandra documentation for - information about the supported parameter names and values). - """ - - def help_delete_columns(self): - print """ - DELETE: specifying columns - - DELETE col1, col2, col3 FROM ... - - Following the DELETE keyword is an optional comma-delimited list of - column name terms. When no column names are given, the remove applies - to the entire row(s) matched by the WHERE clause. - - When column names do not parse as valid CQL identifiers, they can be - quoted in single quotes (CQL 2) or double quotes (CQL 3). - """ - - def help_delete_where(self): - print """ - DELETE: specifying rows - - DELETE ... WHERE keycol = 'some_key_value'; - DELETE ... WHERE keycol1 = 'val1' AND keycol2 = 'val2'; - DELETE ... WHERE keycol IN (key1, key2); - - The WHERE clause is used to determine to which row(s) a DELETE - applies. The first form allows the specification of a precise row - by specifying a particular primary key value (if the primary key has - multiple columns, values for each must be given). The second form - allows a list of key values to be specified using the IN operator - and a parenthesized list of comma-delimited key values. - """ - - def help_update_set(self): - print """ - UPDATE: Specifying Columns and Row - - UPDATE ... SET name1 = value1, name2 = value2 - WHERE = keyname; - UPDATE ... SET name1 = value1, name2 = value2 - WHERE IN ('', '', ...) - - Rows are created or updated by supplying column names and values in - term assignment format. Multiple columns can be set by separating the - name/value pairs using commas. - """ - - def help_update_counters(self): - print """ - UPDATE: Updating Counter Columns - - UPDATE ... SET name1 = name1 + ... - UPDATE ... SET name1 = name1 - ... - - Counter columns can be incremented or decremented by an arbitrary - numeric value though the assignment of an expression that adds or - subtracts the value. - """ - - def help_update_where(self): - print """ - UPDATE: Selecting rows to update - - UPDATE ... WHERE = ; - UPDATE ... WHERE IN (, , ...); - UPDATE ... WHERE = AND = ; - - Each update statement requires a precise set of keys to be specified - using a WHERE clause. - - If the table's primary key consists of multiple columns, an explicit - value must be given for each for the UPDATE statement to make sense. - """ - - def help_select_table(self): - print """ - SELECT: Specifying Table - - SELECT ... FROM [.] ... - - The FROM clause is used to specify the CQL table applicable to a SELECT - query. The keyspace in which the table exists can optionally be - specified along with the table name, separated by a dot (.). This will - not change the current keyspace of the session (see HELP USE). - """ - help_select_columnfamily = help_select_table - - def help_select_where(self): - print """ - SELECT: Filtering rows - - SELECT ... WHERE = keyname AND name1 = value1 - SELECT ... WHERE >= startkey and =< endkey AND name1 = value1 - SELECT ... WHERE IN ('', '', '', ...) - - The WHERE clause provides for filtering the rows that appear in - results. The clause can filter on a key name, or range of keys, and in - the case of indexed columns, on column values. Key filters are - specified using the KEY keyword or key alias name, a relational - operator (one of =, >, >=, <, and <=), and a term value. When terms - appear on both sides of a relational operator it is assumed the filter - applies to an indexed column. With column index filters, the term on - the left of the operator is the name, the term on the right is the - value to filter _on_. - - Note: The greater-than and less-than operators (> and <) result in key - ranges that are inclusive of the terms. There is no supported notion of - "strictly" greater-than or less-than; these operators are merely - supported as aliases to >= and <=. - """ - - def help_select_limit(self): - print """ - SELECT: Limiting results - - SELECT ... WHERE [LIMIT n] ... - - Limiting the number of rows returned can be achieved by adding the - LIMIT option to a SELECT expression. LIMIT defaults to 10,000 when left - unset. - """ - - -class CQL3HelpTopics(CQLHelpTopics): - - def help_create_keyspace(self): - print """ - CREATE KEYSPACE - WITH replication = {'class':'' [,'