/** * 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. */ package org.apache.cassandra.cli; import java.util.EnumMap; import org.antlr.runtime.tree.Tree; /** * @author Pavel A. Yaskevich */ public class CliUserHelp { /* * the <i>add column family</i> command requires a list of arguments, * this enum defines which arguments are valid. */ protected enum ColumnFamilyArgument { COLUMN_TYPE, COMPARATOR, SUBCOMPARATOR, COMMENT, ROWS_CACHED, ROW_CACHE_SAVE_PERIOD, KEYS_CACHED, KEY_CACHE_SAVE_PERIOD, READ_REPAIR_CHANCE, GC_GRACE, COLUMN_METADATA, MEMTABLE_OPERATIONS, MEMTABLE_THROUGHPUT, MEMTABLE_FLUSH_AFTER, DEFAULT_VALIDATION_CLASS, MIN_COMPACTION_THRESHOLD, MAX_COMPACTION_THRESHOLD, ROWKEY_SIZE, COLUMNFAMILY_SIZE, COLUMNFAMILY_TYPE, MYSQL_ENGINE, KC_DBCLASS, } protected EnumMap<ColumnFamilyArgument, String> argumentExplanations = new EnumMap<ColumnFamilyArgument, String>(ColumnFamilyArgument.class) {{ put(ColumnFamilyArgument.COLUMN_TYPE, "Super or Standard"); put(ColumnFamilyArgument.COMMENT, "Human-readable column family description. Any string is acceptable"); put(ColumnFamilyArgument.COMPARATOR, "The class used as a comparator when sorting column names.\n Valid options include: AsciiType, BytesType, LexicalUUIDType,\n LongType, IntegerType, TimeUUIDType, and UTF8Type"); put(ColumnFamilyArgument.SUBCOMPARATOR, "Comparator for sorting subcolumn names, for Super columns only"); put(ColumnFamilyArgument.MEMTABLE_OPERATIONS, "Flush memtables after this many operations (in millions)"); put(ColumnFamilyArgument.MEMTABLE_THROUGHPUT, "... or after this many MB have been written"); put(ColumnFamilyArgument.MEMTABLE_FLUSH_AFTER, "... or after this many minutes"); put(ColumnFamilyArgument.ROWS_CACHED, "Number or percentage of rows to cache"); put(ColumnFamilyArgument.ROW_CACHE_SAVE_PERIOD, "Period with which to persist the row cache, in seconds"); put(ColumnFamilyArgument.KEYS_CACHED, "Number or percentage of keys to cache"); put(ColumnFamilyArgument.KEY_CACHE_SAVE_PERIOD, "Period with which to persist the key cache, in seconds"); put(ColumnFamilyArgument.READ_REPAIR_CHANCE, "Probability (0.0-1.0) with which to perform read repairs on CL.ONE reads"); put(ColumnFamilyArgument.GC_GRACE, "Discard tombstones after this many seconds"); put(ColumnFamilyArgument.MIN_COMPACTION_THRESHOLD, "Avoid minor compactions of less than this number of sstable files"); put(ColumnFamilyArgument.MAX_COMPACTION_THRESHOLD, "Compact no more than this number of sstable files at once"); put(ColumnFamilyArgument.ROWKEY_SIZE, "Max Key Size (16-) With MyCassandra-MySQL"); put(ColumnFamilyArgument.COLUMNFAMILY_SIZE, "Max CF Size (1024-) With MyCassandra-MySQL"); put(ColumnFamilyArgument.COLUMNFAMILY_TYPE, "CF type (MySQL data type) With MyCassandra-MySQL"); put(ColumnFamilyArgument.MYSQL_ENGINE, "Storage Engine With MySQL"); put(ColumnFamilyArgument.KC_DBCLASS, "DB CLASS With KyotoCabinet"); }}; protected void printCmdHelp(Tree statement, CliSessionState state) { if (statement.getChildCount() > 0) { int helpType = statement.getChild(0).getType(); switch(helpType) { case CliParser.NODE_HELP: state.out.println("help <command>;\n"); state.out.println("Display the general help page with a list of available commands."); break; case CliParser.NODE_CONNECT: state.out.println("connect <hostname>/<port> (<username> '<password>')?;\n"); state.out.println("Connect to the specified host on the specified port (using specified username and password).\n"); state.out.println("example:"); state.out.println("connect localhost/9160;"); state.out.println("connect localhost/9160 user 'badpasswd';"); state.out.println("connect 127.0.0.1/9160 user 'badpasswd';"); break; case CliParser.NODE_USE_TABLE: state.out.println("use <keyspace>;"); state.out.println("use <keyspace> <username> '<password>';\n"); state.out.println("Switch to the specified keyspace. The optional username and password fields"); state.out.println("are needed when performing authentication.\n"); break; case CliParser.NODE_DESCRIBE_TABLE: state.out.println("describe keyspace (<keyspace>)?;\n"); state.out.println("Show additional information about the specified keyspace."); state.out.println("Command could be used without <keyspace> argument if you are already authenticated to keyspace.\n"); state.out.println("example:"); state.out.println("describe keyspace system;"); break; case CliParser.NODE_DESCRIBE_CLUSTER: state.out.println("describe cluster;\n"); state.out.println("Display information about cluster: snitch, partitioner, schema versions."); break; case CliParser.NODE_EXIT: state.out.println("exit;"); state.out.println("quit;\n"); state.out.println("Exit this utility."); break; case CliParser.NODE_SHOW_CLUSTER_NAME: state.out.println("show cluster name;\n"); state.out.println("Displays the name of the currently connected cluster."); break; case CliParser.NODE_SHOW_VERSION: state.out.println("show api version;\n"); state.out.println("Displays the API version number."); break; case CliParser.NODE_SHOW_KEYSPACES: state.out.println("show keyspaces;\n"); state.out.println("Displays a list of the keyspaces available on the currently connected cluster."); break; case CliParser.NODE_ADD_KEYSPACE: state.out.println("create keyspace <keyspace>;"); state.out.println("create keyspace <keyspace> with <att1>=<value1>;"); state.out.println("create keyspace <keyspace> with <att1>=<value1> and <att2>=<value2> ...;\n"); state.out.println("Create a new keyspace with the specified values for the given set of attributes.\n"); state.out.println("valid attributes are:"); state.out.println(" replication_factor: to how many nodes should entries to this keyspace be"); state.out.println(" replicated. Valid entries are integers greater than 0."); state.out.println(" Applies to Simple and OldNT strategies but NOT NTS."); state.out.println(" placement_strategy: the fully qualified class used to place replicas in"); state.out.println(" this keyspace. Valid values are"); state.out.println(" org.apache.cassandra.locator.SimpleStrategy,"); state.out.println(" org.apache.cassandra.locator.NetworkTopologyStrategy,"); state.out.println(" and org.apache.cassandra.locator.OldNetworkTopologyStrategy"); state.out.println(" strategy_options: additional options for placement_strategy."); state.out.println(" Applies only to NetworkTopologyStrategy."); state.out.println("\nexamples:"); state.out.println("create keyspace foo with"); state.out.println(" placement_strategy = 'org.apache.cassandra.locator.SimpleStrategy';"); state.out.println(" and replication_factor = 3;"); state.out.println("create keyspace foo with"); state.out.println(" placement_strategy = 'org.apache.cassandra.locator.NetworkTopologyStrategy';"); state.out.println(" and strategy_options=[{DC1:2, DC2:2}];"); break; case CliParser.NODE_UPDATE_KEYSPACE: state.out.println("update keyspace <keyspace>;"); state.out.println("update keyspace <keyspace> with <att1>=<value1>;"); state.out.println("update keyspace <keyspace> with <att1>=<value1> and <att2>=<value2> ...;\n"); state.out.println("Update a keyspace with the specified values for the given set of attributes.\n"); state.out.println("valid attributes are:"); state.out.println(" replication_factor: to how many nodes should entries to this keyspace be"); state.out.println(" replicated. Valid entries are integers greater than 0."); state.out.println(" Applies to Simple and OldNT strategies but NOT NTS."); state.out.println(" placement_strategy: the fully qualified class used to place replicas in"); state.out.println(" this keyspace. Valid values are"); state.out.println(" org.apache.cassandra.locator.SimpleStrategy,"); state.out.println(" org.apache.cassandra.locator.NetworkTopologyStrategy,"); state.out.println(" and org.apache.cassandra.locator.OldNetworkTopologyStrategy"); state.out.println(" strategy_options: additional options for placement_strategy."); state.out.println(" Applies only to NetworkTopologyStrategy."); state.out.println("\nexamples:"); state.out.println("update keyspace foo with"); state.out.println(" placement_strategy = 'org.apache.cassandra.locator.SimpleStrategy';"); state.out.println(" and replication_factor = 3;"); state.out.println("update keyspace foo with"); state.out.println(" placement_strategy = 'org.apache.cassandra.locator.NetworkTopologyStrategy';"); state.out.println(" and strategy_options=[{DC1:2, DC2:2}];"); break; case CliParser.NODE_ADD_COLUMN_FAMILY: state.out.println("create column family Bar;"); state.out.println("create column family Bar with <att1>=<value1>;"); state.out.println("create column family Bar with <att1>=<value1> and <att2>=<value2>...;\n"); state.out.println("create column family Bar with rowkey_size = 32 and columnfamily_size = 2048 and columnfamily_type = 'VARBINARY' and mysql_engine = 'MyISAM'"); state.out.println("create column family Bar with kc_dbclass = 'TreeDB'"); state.out.println("Create a new column family with the specified values for the given set of"); state.out.println("attributes. Note that you must be using a keyspace.\n"); state.out.println("valid attributes are:"); for (ColumnFamilyArgument argument : ColumnFamilyArgument.values()) state.out.printf(" - %s: %s%n", argument.toString().toLowerCase(), argumentExplanations.get(argument)); state.out.println(" - column_metadata: Metadata which describes columns of column family."); state.out.println(" Supported format is [{ k:v, k:v, ... }, { ... }, ...]"); state.out.println(" Valid attributes: column_name, validation_class (see comparator),"); state.out.println(" index_type (integer), index_name."); state.out.println("example:\n"); state.out.println("create column family Bar with column_type = 'Super' and comparator = 'AsciiType'"); state.out.println(" and rows_cached = 10000;"); state.out.println("create column family Baz with comparator = 'LongType' and rows_cached = 10000;"); state.out.print("create column family Foo with comparator=UTF8Type and column_metadata="); state.out.print("[{ column_name:test, validation_class:IntegerType, index_type:0, index_name:TextIdx"); state.out.println("}, { column_name:'other name', validation_class:LongType }];"); break; case CliParser.NODE_UPDATE_COLUMN_FAMILY: state.out.println("update column family Bar;"); state.out.println("update column family Bar with <att1>=<value1>;"); state.out.println("update column family Bar with <att1>=<value1> and <att2>=<value2>...;\n"); state.out.println("Update a column family with the specified values for the given set of"); state.out.println("attributes. Note that you must be using a keyspace.\n"); state.out.println("valid attributes are:"); for (ColumnFamilyArgument argument : ColumnFamilyArgument.values()) { if (argument == ColumnFamilyArgument.COMPARATOR || argument == ColumnFamilyArgument.SUBCOMPARATOR) continue; state.out.printf(" - %s: %s%n", argument.toString().toLowerCase(), argumentExplanations.get(argument)); } state.out.println(" - column_metadata: Metadata which describes columns of column family."); state.out.println(" Supported format is [{ k:v, k:v, ... }, { ... }, ...]"); state.out.println(" Valid attributes: column_name, validation_class (see comparator),"); state.out.println(" index_type (integer), index_name."); state.out.println("example:\n"); state.out.print("update column family Foo with column_metadata="); state.out.print("[{ column_name:Test, validation_class:IntegerType, index_type:0, index_name:IdxName"); state.out.println("}] and rows_cached=100 and comment='this is helpful comment.';"); break; case CliParser.NODE_DEL_KEYSPACE: state.out.println("drop keyspace <keyspace>;\n"); state.out.println("Drops the specified keyspace.\n"); state.out.println("example:"); state.out.println("drop keyspace foo;"); break; case CliParser.NODE_DEL_COLUMN_FAMILY: state.out.println("drop column family <name>;\n"); state.out.println("Drops the specified column family.\n"); state.out.println("example:"); state.out.println("drop column family foo;"); break; case CliParser.NODE_THRIFT_GET : state.out.println("get <cf>['<key>'];"); state.out.println("get <cf>['<key>']['<col>'] (as <type>)*;"); state.out.println("get <cf>['<key>']['<super>'];"); state.out.println("get <cf>['<key>'][<function>];"); state.out.println("get <cf>['<key>'][<function>(<super>)][<function>(<col>)];"); state.out.println("get <cf> where <column> = <value> [and <column> > <value> and ...] [limit <integer>];"); state.out.println("Default LIMIT is 100. Available operations: =, >, >=, <, <=\n"); state.out.println("get <cf>['<key>']['<super>']['<col>'] (as <type>)*;"); state.out.print("Note: `as <type>` is optional, it dynamically converts column value to the specified type"); state.out.println(", column value validator will be set to <type>."); state.out.println("Available functions: " + CliClient.Function.getFunctionNames()); state.out.println("Available types: IntegerType, LongType, UTF8Type, ASCIIType, TimeUUIDType, LexicalUUIDType.\n"); state.out.println("examples:"); state.out.println("get bar[testkey];"); state.out.println("get bar[testkey][test_column] as IntegerType;"); state.out.println("get bar[testkey][utf8(hello)];"); break; case CliParser.NODE_THRIFT_SET: state.out.println("set <cf>['<key>']['<col>'] = <value>;"); state.out.println("set <cf>['<key>']['<super>']['<col>'] = <value>;"); state.out.println("set <cf>['<key>']['<col>'] = <function>(<argument>);"); state.out.println("set <cf>['<key>']['<super>']['<col>'] = <function>(<argument>);"); state.out.println("set <cf>[<key>][<function>(<col>)] = <value> || <function>;"); state.out.println("set <cf>[<key>][<function>(<col>) || <col>] = <value> || <function> with ttl = <secs>;"); state.out.println("Available functions: " + CliClient.Function.getFunctionNames() + "\n"); state.out.println("examples:"); state.out.println("set bar['testkey']['my super']['test col']='this is a test';"); state.out.println("set baz['testkey']['test col']='this is also a test';"); state.out.println("set diz[testkey][testcol] = utf8('this is utf8 string.');"); state.out.println("set bar[testkey][timeuuid()] = utf('hello world');"); state.out.println("set bar[testkey][timeuuid()] = utf('hello world') with ttl = 30;"); state.out.println("set diz[testkey][testcol] = 'this is utf8 string.' with ttl = 150;"); break; case CliParser.NODE_THRIFT_DEL: state.out.println("del <cf>['<key>'];"); state.out.println("del <cf>['<key>']['<col>'];"); state.out.println("del <cf>['<key>']['<super>']['<col>'];\n"); state.out.println("Deletes a record, a column, or a subcolumn.\n"); state.out.println("example:"); state.out.println("del bar['testkey']['my super']['test col'];"); state.out.println("del baz['testkey']['test col'];"); state.out.println("del baz['testkey'];"); break; case CliParser.NODE_THRIFT_COUNT: state.out.println("count <cf>['<key>'];"); state.out.println("count <cf>['<key>']['<super>'];\n"); state.out.println("Count the number of columns in the specified key or subcolumns in the specified"); state.out.println("super column.\n"); state.out.println("example:"); state.out.println("count bar['testkey']['my super'];"); state.out.println("count baz['testkey'];"); break; case CliParser.NODE_LIST: state.out.println("list <cf>;"); state.out.println("list <cf>[<startKey>:];"); state.out.println("list <cf>[<startKey>:<endKey>];"); state.out.println("list ... limit N;"); state.out.println("List a range of rows in the column or supercolumn family.\n"); state.out.println("example:"); state.out.println("list Users[j:] limit 40;"); break; case CliParser.NODE_TRUNCATE: state.out.println("truncate <column_family>;"); state.out.println("Truncate specified column family.\n"); state.out.println("example:"); state.out.println("truncate Category;"); break; case CliParser.NODE_ASSUME: state.out.println("assume <column_family> comparator as <type>;"); state.out.println("assume <column_family> sub_comparator as <type>;"); state.out.println("assume <column_family> validator as <type>;"); state.out.println("assume <column_family> keys as <type>;\n"); state.out.println("Assume one of the attributes (comparator, sub_comparator, validator or keys)"); state.out.println("of the given column family to match specified type. Available types: " + CliClient.Function.getFunctionNames()); state.out.println("example:"); state.out.println("assume Users comparator as lexicaluuid;"); break; case CliParser.NODE_CONSISTENCY_LEVEL: state.out.println("consistencylevel as <level>"); state.out.println("example:"); state.out.println("consistencylevel as QUORUM"); break; default: state.out.println("?"); break; } } else { state.out.println("List of all CLI commands:"); state.out.println("? Display this message."); state.out.println("help; Display this help."); state.out.println("help <command>; Display detailed, command-specific help."); state.out.println("connect <hostname>/<port> (<username> '<password>')?; Connect to thrift service."); state.out.println("use <keyspace> [<username> 'password']; Switch to a keyspace."); state.out.println("describe keyspace (<keyspacename>)?; Describe keyspace."); state.out.println("exit; Exit CLI."); state.out.println("quit; Exit CLI."); state.out.println("describe cluster; Display information about cluster."); state.out.println("show cluster name; Display cluster name."); state.out.println("show keyspaces; Show list of keyspaces."); state.out.println("show api version; Show server API version."); state.out.println("create keyspace <keyspace> [with <att1>=<value1> [and <att2>=<value2> ...]];"); state.out.println(" Add a new keyspace with the specified attribute(s) and value(s)."); state.out.println("update keyspace <keyspace> [with <att1>=<value1> [and <att2>=<value2> ...]];"); state.out.println(" Update a keyspace with the specified attribute(s) and value(s)."); state.out.println("create column family <cf> [with <att1>=<value1> [and <att2>=<value2> ...]];"); state.out.println(" Create a new column family with the specified attribute(s) and value(s)."); state.out.println("update column family <cf> [with <att1>=<value1> [and <att2>=<value2> ...]];"); state.out.println(" Update a column family with the specified attribute(s) and value(s)."); state.out.println("drop keyspace <keyspace>; Delete a keyspace."); state.out.println("drop column family <cf>; Delete a column family."); state.out.println("get <cf>['<key>']; Get a slice of columns."); state.out.println("get <cf>['<key>']['<super>']; Get a slice of sub columns."); state.out.println("get <cf> where <column> = <value> [and <column> > <value> and ...] [limit int]; "); state.out.println("get <cf>['<key>']['<col>'] (as <type>)*; Get a column value."); state.out.println("get <cf>['<key>']['<super>']['<col>'] (as <type>)*; Get a sub column value."); state.out.println("set <cf>['<key>']['<col>'] = <value> (with ttl = <secs>)*; Set a column."); state.out.println("set <cf>['<key>']['<super>']['<col>'] = <value> (with ttl = <secs>)*;"); state.out.println(" Set a sub column."); state.out.println("del <cf>['<key>']; Delete record."); state.out.println("del <cf>['<key>']['<col>']; Delete column."); state.out.println("del <cf>['<key>']['<super>']['<col>']; Delete sub column."); state.out.println("count <cf>['<key>']; Count columns in record."); state.out.println("count <cf>['<key>']['<super>']; Count columns in a super column."); state.out.println("truncate <column_family>; Truncate specified column family."); state.out.println("assume <column_family> <attribute> as <type>;"); state.out.println(" Assume a given column family attributes to match a specified type."); state.out.println("consistencylevel as <level>;"); state.out.println(" Change the consistency level for set,get, and list operations."); state.out.println("list <cf>; List all rows in the column family."); state.out.println("list <cf>[<startKey>:];"); state.out.println(" List rows in the column family beginning with <startKey>."); state.out.println("list <cf>[<startKey>:<endKey>];"); state.out.println(" List rows in the column family in the range from <startKey> to <endKey>."); state.out.println("list ... limit N; Limit the list results to N."); } } }