Repository: cassandra
Updated Branches:
  refs/heads/cassandra-3.0 56965fd6f -> 9a2fd8ccf


Show CQL help in cqlsh in web browser

patch by Robert Stupp; reviewed by Paulo Motta for CASSANDRA-7225


Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/0ee8895b
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/0ee8895b
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/0ee8895b

Branch: refs/heads/cassandra-3.0
Commit: 0ee8895b27c2aa18260c73ec5c1941e48fbeaf75
Parents: 432a8a4
Author: Robert Stupp <sn...@snazy.de>
Authored: Fri Nov 27 15:24:51 2015 +0100
Committer: Robert Stupp <sn...@snazy.de>
Committed: Fri Nov 27 15:24:51 2015 +0100

----------------------------------------------------------------------
 CHANGES.txt                  |    1 +
 bin/cqlsh.py                 |   61 ++-
 build.xml                    |    7 +-
 conf/cqlshrc.sample          |   17 +
 debian/rules                 |    3 +-
 pylib/cqlshlib/helptopics.py | 1060 ++++---------------------------------
 6 files changed, 176 insertions(+), 973 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/0ee8895b/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index ce82bd0..af1a186 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)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/0ee8895b/bin/cqlsh.py
----------------------------------------------------------------------
diff --git a/bin/cqlsh.py b/bin/cqlsh.py
index 28054ba..e7dc121 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,

http://git-wip-us.apache.org/repos/asf/cassandra/blob/0ee8895b/build.xml
----------------------------------------------------------------------
diff --git a/build.xml b/build.xml
index fe30964..6110bb0 100644
--- a/build.xml
+++ b/build.xml
@@ -776,7 +776,7 @@
         depends="maven-ant-tasks-retrieve-build,build-project" 
description="Compile Cassandra classes"/>
     <target name="codecoverage" depends="jacoco-run,jacoco-report" 
description="Create code coverage report"/>
 
-    <target depends="init,gen-cql3-grammar"
+    <target depends="init,gen-cql3-grammar,generate-cql-html"
             name="build-project">
         <echo message="${ant.project.name}: ${ant.file}"/>
         <!-- Order matters! -->
@@ -1013,6 +1013,11 @@
       <copy todir="${dist.dir}/javadoc">
         <fileset dir="${javadoc.dir}"/>
       </copy>
+      <copy todir="${dist.dir}/doc">
+        <fileset dir="doc">
+          <exclude name="cql3/CQL.textile"/>
+        </fileset>
+      </copy>
       <copy todir="${dist.dir}/bin">
         <fileset dir="bin"/>
       </copy>

http://git-wip-us.apache.org/repos/asf/cassandra/blob/0ee8895b/conf/cqlshrc.sample
----------------------------------------------------------------------
diff --git a/conf/cqlshrc.sample b/conf/cqlshrc.sample
index 6558ad2..302d25f 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
 

http://git-wip-us.apache.org/repos/asf/cassandra/blob/0ee8895b/debian/rules
----------------------------------------------------------------------
diff --git a/debian/rules b/debian/rules
index d0d22a9..fedb32e 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

http://git-wip-us.apache.org/repos/asf/cassandra/blob/0ee8895b/pylib/cqlshlib/helptopics.py
----------------------------------------------------------------------
diff --git a/pylib/cqlshlib/helptopics.py b/pylib/cqlshlib/helptopics.py
index 8e296e1..c2eebe3 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
+    def help_text(self):
+        return 'constants'
+    help_ascii = help_text
 
-        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
+    def help_use(self):
+        return 'useStmt'
 
-        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.
+    def help_insert(self):
+        return 'insertStmt'
 
-        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_update(self):
+        return 'updateStmt'
 
-    def help_create_index(self):
-        print """
-        CREATE INDEX [<indexname>] ON <cfname> ( <colname> );
+    def help_delete(self):
+        return 'deleteStmt'
 
-        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_select(self):
+        return 'selectStmt'
 
-    def help_drop(self):
-        print """
-        There are different variants of DROP. For more information, see
-        one of the following:
+    def help_json(self):
+        return 'json'
+    def help_select_json(self):
+        return 'selectJson'
+    def help_insert_json(self):
+        return 'insertJson'
 
-          HELP DROP_KEYSPACE;
-          HELP DROP_TABLE;
-          HELP DROP_INDEX;
-          HELP DROP_FUNCTION;
-          HELP DROP_AGGREGATE;
-        """
+    def help_batch(self):
+        return 'batchStmt'
+    help_begin = help_batch
+    help_apply = help_batch
 
+    def help_create_keyspace(self):
+        return 'createKeyspaceStmt'
+    def help_alter_keyspace(self):
+        return 'alterKeyspaceStmt'
     def help_drop_keyspace(self):
-        print """
-        DROP KEYSPACE <keyspacename>;
-
-        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.
-        """
+        return 'dropKeyspaceStmt'
 
+    def help_create_table(self):
+        return 'createTableStmt'
+    help_create_columnfamily = help_create_table
+    def help_alter_table(self):
+        return 'alterTableStmt'
     def help_drop_table(self):
-        print """
-        DROP TABLE <tablename>;
-
-        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.
-        """
+        return 'dropTableStmt'
     help_drop_columnfamily = help_drop_table
-
+    def help_create_index(self):
+        return 'createIndexStmt'
     def help_drop_index(self):
-        print """
-        DROP INDEX <indexname>;
-
-        A DROP INDEX statement is used to drop an existing secondary index.
-        """
-
-    def help_drop_function(self):
-        print """
-        DROP FUNCTION ( IF EXISTS )?
-                         ( <keyspace> '.' )? <function-name>
-                         ( '(' <arg-type> ( ',' <arg-type> )* ')' )?
-
-        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 )?
-                         ( <keyspace> '.' )? <aggregate-name>
-                         ( '(' <arg-type> ( ',' <arg-type> )* ')' )?
-
-        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.
-        """
+        return 'dropIndexStmt'
 
     def help_truncate(self):
-        print """
-        TRUNCATE <tablename>;
-
-        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_use(self):
-        print """
-        USE <keyspacename>;
-
-        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 )?
-                            ( <keyspace> '.' )? <aggregate-name>
-                            '(' <arg-type> ( ',' <arg-type> )* ')'
-                            SFUNC ( <keyspace> '.' )? <state-functionname>
-                            STYPE <state-type>
-                            ( FINALFUNC ( <keyspace> '.' )? 
<final-functionname> )?
-                            ( INITCOND <init-cond> )?
-
-        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 
<aggregate-name>, 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.
+        return 'truncateStmt'
 
-        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_type(self):
+        return 'createTypeStmt'
+    def help_alter_type(self):
+        return 'alterTypeStmt'
+    def help_drop_type(self):
+        return 'dropTypeStmt'
 
     def help_create_function(self):
-        print """
-        CREATE ( OR REPLACE )? FUNCTION ( IF NOT EXISTS )?
-                            ( <keyspace> '.' )? <function-name>
-                            '(' <arg-name> <arg-type> ( ',' <arg-name> 
<arg-type> )* ')'
-                            ( CALLED | RETURNS NULL ) ON NULL INPUT
-                            RETURNS <type>
-                            LANGUAGE <language>
-                            AS <body>
-
-        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 
<function-name>, 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 <cfname> ( <colname> <type> PRIMARY KEY [,
-                                <colname> <type> [, ...]] )
-               [WITH <optionname> = <val> [AND <optionname> = <val> [...]]];
-
-        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 <cfname> ( <partition_key> <type>, <clustering_key1> 
type, <clustering_key2> type,
-                                [, ...]], PRIMARY KEY (<partition_key>, 
<clustering_key1>, <clustering_key2>);
-
-        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( <key1>, <key2>, ... )
-
-        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 ((<partition_key_part1>, <partition_key_part2>), 
<clustering_key>)
-        """
-
-    def help_create_table_types(self):
-        print """
-        CREATE TABLE: Specifying column types
-
-          CREATE ... (KEY <type> PRIMARY KEY,
-                      othercol <type>) ...
-
-        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 <key> = keyname;
-          UPDATE ... SET name1 = value1, name2 = value2
-                   WHERE <key> IN ('<key1>', '<key2>', ...)
-
-        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 + <value> ...
-          UPDATE ... SET name1 = name1 - <value> ...
-
-        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 <keyname> = <keyval>;
-          UPDATE ... WHERE <keyname> IN (<keyval1>, <keyval2>, ...);
-          UPDATE ... WHERE <keycol1> = <keyval1> AND <keycol2> = <keyval2>;
-
-        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 [<keyspace>.]<tablename> ...
-
-        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 <key> = keyname AND name1 = value1
-          SELECT ... WHERE <key> >= startkey and <key> =< endkey AND name1 = 
value1
-          SELECT ... WHERE <key> IN ('<key>', '<key>', '<key>', ...)
-
-        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 <clause> [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 <ksname>
-            WITH replication = {'class':'<strategy>' [,'<option>':<val>]};
-
-        The CREATE KEYSPACE statement creates a new top-level namespace (aka
-        "keyspace"). Valid names are any string constructed of alphanumeric
-        characters and underscores. Names which do not work as valid
-        identifiers or integers should be quoted as string literals. Properties
-        such as replication strategy and count are specified during creation
-        as key-value pairs in the 'replication' map:
-
-          class [required]: The name of the replication strategy class
-          which should be used for the new keyspace. Some often-used classes
-          are SimpleStrategy and NetworkTopologyStrategy.
-
-          other options [optional]: Most strategies require additional 
arguments
-          which can be supplied as key-value pairs in the 'replication' map.
-
-        Examples:
-
-          To create a keyspace with NetworkTopologyStrategy and strategy 
option of "DC1"
-          with a value of "1" and "DC2" with a value of "2" you would use
-          the following statement:
-            CREATE KEYSPACE <ksname>
-                WITH replication = {'class':'NetworkTopologyStrategy', 
'DC1':1, 'DC2':2};
-
-         To create a keyspace with SimpleStrategy and "replication_factor" 
option
-         with a value of "3" you would use this statement:
-            CREATE KEYSPACE <ksname>
-                WITH replication = {'class':'SimpleStrategy', 
'replication_factor':3};
-        """
-
-    def help_begin(self):
-        print """
-        BEGIN [UNLOGGED|COUNTER] BATCH [USING TIMESTAMP <timestamp>]
-          <insert or update or delete statement> ;
-          [ <another insert or update or delete statement ;
-            [...]]
-        APPLY BATCH;
-
-        BATCH supports setting a client-supplied optional global timestamp
-        which will be used for each of the operations included in the batch.
-
-        Only data modification statements (specifically, UPDATE, INSERT,
-        and DELETE) are allowed in a BATCH statement. BATCH is _not_ an
-        analogue for SQL transactions.
-
-        _NOTE: Counter mutations are allowed only within COUNTER batches._
-
-        _NOTE: While there are no isolation guarantees, UPDATE queries are
-        atomic within a given record._
-        """
-    help_apply = help_begin
-
-    def help_select(self):
-        print """
-        SELECT <selectExpr>
-          FROM [<keyspace>.]<table>
-            [WHERE <clause>]
-            [ORDER BY <colname> [DESC]]
-            [LIMIT m];
-
-        SELECT is used to read one or more records from a CQL table. It returns
-        a set of rows matching the selection criteria specified.
-
-        For more information, see one of the following:
-
-          HELP SELECT_EXPR
-          HELP SELECT_TABLE
-          HELP SELECT_WHERE
-          HELP SELECT_LIMIT
-        """
-
-    def help_delete(self):
-        print """
-        DELETE [<col1> [, <col2>, ...] FROM [<keyspace>.]<tablename>
-               [USING TIMESTAMP <timestamp>]
-            WHERE <keyname> = <keyvalue>;
-
-        A DELETE is used to perform the removal of one or more columns from one
-        or more rows. Each DELETE statement requires a precise set of row keys
-        to be specified using a WHERE clause and the KEY keyword or key alias.
-
-        For more information, see one of the following:
-
-          HELP DELETE_USING
-          HELP DELETE_COLUMNS
-          HELP DELETE_WHERE
-        """
-
-    def help_delete_using(self):
-        print """
-        DELETE: the USING clause
-
-          DELETE ... USING TIMESTAMP <timestamp>;
-
-        <timestamp> defines the optional timestamp for the new tombstone
-        record. It must be an integer. Cassandra timestamps are generally
-        specified using milliseconds since the Unix epoch (1970-01-01 00:00:00
-        UTC).
-        """
-
-    def help_update(self):
-        print """
-        UPDATE [<keyspace>.]<columnFamily>
-                              [USING [TIMESTAMP <timestamp>]
-                                [AND TTL <timeToLive>]]
-               SET name1 = value1, name2 = value2 WHERE <keycol> = keyval
-               [IF EXISTS];
-
-        An UPDATE is used to write one or more columns to a record in a table.
-        No results are returned. The record's primary key must be completely
-        and uniquely specified; that is, if the primary key includes multiple
-        columns, all must be explicitly given in the WHERE clause.
-
-        Statements begin with the UPDATE keyword followed by the name of the
-        table to be updated.
-
-        For more information, see one of the following:
-
-          HELP UPDATE_USING
-          HELP UPDATE_SET
-          HELP UPDATE_COUNTERS
-          HELP UPDATE_WHERE
-        """
-
-    def help_update_using(self):
-        print """
-        UPDATE: the USING clause
-
-          UPDATE ... USING TIMESTAMP <timestamp>;
-          UPDATE ... USING TTL <timeToLive>;
-
-        The USING clause allows setting of certain query and data parameters.
-        If multiple parameters need to be set, these may be joined using AND.
-        Example:
-
-          UPDATE ... USING TTL 43200 AND TIMESTAMP 1351620509603
-
-        <timestamp> defines the optional timestamp for the new column value(s).
-        It must be an integer. Cassandra timestamps are generally specified
-        using milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC).
-
-        <timeToLive> defines the optional time to live (TTL) in seconds for the
-        new column value(s). It must be an integer.
-        """
-
-    def help_insert(self):
-        print """
-        INSERT INTO [<keyspace>.]<tablename>
-                    ( <colname1>, <colname2> [, <colname3> [, ...]] )
-               VALUES ( <colval1>, <colval2> [, <colval3> [, ...]] )
-               [USING TIMESTAMP <timestamp>]
-                 [AND TTL <timeToLive>];
-
-        An INSERT is used to write one or more columns to a record in a
-        CQL table. No results are returned.
-
-        Values for all component columns in the table's primary key must
-        be given. Also, there must be at least one non-primary-key column
-        specified (Cassandra rows are not considered to exist with only
-        a key and no associated columns).
-
-        Unlike in SQL, the semantics of INSERT and UPDATE are identical.
-        In either case a record is created if none existed before, and
-        udpated when it does. For more information, see one of the
-        following:
-
-          HELP UPDATE
-          HELP UPDATE_USING
-        """
-
-    def help_select_expr(self):
-        print """
-        SELECT: Specifying Columns
-
-          SELECT name1, name2, name3 FROM ...
-          SELECT COUNT(*) FROM ...
-
-        The SELECT expression determines which columns will appear in the
-        results and takes the form of a comma separated list of names.
-
-        It is worth noting that unlike the projection in a SQL SELECT, there is
-        no guarantee that the results will contain all of the columns
-        specified. This is because Cassandra is schema-less and there are no
-        guarantees that a given column exists.
-
-        When the COUNT aggregate function is specified as a column to fetch, a
-        single row will be returned, with a single column named "count" whose
-        value is the number of rows from the pre-aggregation resultset.
-
-        Currently, COUNT is the only function supported by CQL.
-        """
-
-    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. Dropped columns will immediately
-        become unavailable in the queries and will not be included in
-        compacted sstables in the future. If a column is readded, queries
-        won't return values written before the column was last dropped.
-        It is assumed that timestamps represent actual time, so if this
-        is not your case, you should NOT readd previously dropped columns.
-        Columns can't be dropped from tables defined with COMPACT STORAGE.
-        """
-
-    def help_create(self):
-        super(CQL3HelpTopics, self).help_create()
-        print """          HELP CREATE_USER;
-          HELP CREATE_ROLE;
-        """
-
-    def help_alter(self):
-        print """
-        ALTER TABLE <tablename> ALTER <columnname> TYPE <type>;
-        ALTER TABLE <tablename> ADD <columnname> <type>;
-        ALTER TABLE <tablename> RENAME <columnname> TO <columnname>
-            [AND <columnname> TO <columnname>]
-        ALTER TABLE <tablename> WITH <optionname> = <val> [AND <optionname> = 
<val> [...]];
-
-        An ALTER statement is used to manipulate table metadata. It allows you
-        to add new typed columns, drop existing columns, change the data
-        storage type of existing columns, or change table properties.
-        No results are returned.
-
-        See one of the following for more information:
-
-          HELP ALTER_ALTER;
-          HELP ALTER_ADD;
-          HELP ALTER_DROP;
-          HELP ALTER_RENAME;
-          HELP ALTER_WITH;
-        """
-
-    def help_alter_rename(self):
-        print """
-        ALTER TABLE: renaming a column
-
-          ALTER TABLE <tablename> RENAME <columnname> TO <columnname>
-              [AND <columnname> TO <columnname>]
-
-        The ALTER TABLE ... RENAME variant renames a typed column in a column
-        family.
-        """
+        return 'createFunctionStmt'
+    def help_drop_function(self):
+        return 'dropFunctionStmt'
+    def help_functions(self):
+        return 'functions'
 
-    def help_drop(self):
-        super(CQL3HelpTopics, self).help_create()
-        print """          HELP DROP_USER;
-          HELP DROP_ROLE;
-        """
+    def help_create_aggregate(self):
+        return 'createAggregateStmt'
+    def help_drop_aggregate(self):
+        return 'dropAggregateStmt'
+    def help_aggregates(self):
+        return 'aggregates'
 
-    def help_list(self):
-        print """
-        There are different variants of LIST. For more information, see
-        one of the following:
+    def help_create_trigger(self):
+        return 'createTriggerStmt'
+    def help_drop_trigger(self):
+        return 'dropTriggerStmt'
 
-          HELP LIST_USERS;
-          HELP LIST_PERMISSIONS;
-        """
+    def help_keywords(self):
+        return 'appendixA'
 
     def help_create_user(self):
-        print """
-        CREATE USER <username> [WITH PASSWORD 'password'] [NOSUPERUSER | 
SUPERUSER];
-
-        CREATE USER creates a new Cassandra user account.
-        Only superusers can issue CREATE USER requests.
-        To create a superuser account use SUPERUSER option (NOSUPERUSER is the 
default).
-
-        WITH PASSWORD clause should only be used with password-based 
authenticators,
-        e.g. PasswordAuthenticator, SimpleAuthenticator.
-        """
-
+        return 'createUserStmt'
     def help_alter_user(self):
-        print """
-        ALTER USER <username> [WITH PASSWORD 'password'] [NOSUPERUSER | 
SUPERUSER];
-
-        Use ALTER USER to change a user's superuser status and/or password 
(only
-        with password-based authenticators).
-        Superusers can change a user's password or superuser status (except 
their own).
-        Users cannot change their own superuser status. Ordinary users can 
only change their
-        password (if the configured authenticator is password-based).
-        """
-
+        return 'alterUserStmt'
     def help_drop_user(self):
-        print """
-        DROP USER <username>;
-
-        DROP USER removes an existing user. You have to be logged in as a 
superuser
-        to issue a DROP USER statement. A user cannot drop themselves.
-        """
-
+        return 'dropUserStmt'
     def help_list_users(self):
-        print """
-        LIST USERS;
+        return 'listUsersStmt'
 
-        List existing users and their superuser status.
-        """
+    def help_permissions(self):
+        return 'permissions'
+    def help_list_permissions(self):
+        return 'listPermissionsStmt'
 
     def help_grant(self):
-        print """
-        GRANT (<permission> [PERMISSION] | ALL [PERMISSIONS])
-                  ON ALL KEYSPACES
-                   | KEYSPACE <keyspace>
-                   | [TABLE] [<keyspace>.]<table>
-                  TO [ROLE <rolename> | USER <username>]
-
-        Grant the specified permission (or all permissions) on a resource
-        to a role or user.
-
-        To be able to grant a permission on some resource you have to
-        have that permission yourself and also AUTHORIZE permission on it,
-        or on one of its parent resources.
-
-        See HELP PERMISSIONS for more info on the available permissions.
-        """
-
+        return 'grantRoleStmt'
     def help_revoke(self):
-        print """
-        REVOKE (<permission> [PERMISSION] | ALL [PERMISSIONS])
-                  ON ALL KEYSPACES
-                   | KEYSPACE <keyspace>
-                   | [TABLE] [<keyspace>.]<table>
-                  FROM [ROLE <rolename> | USER <username>]
-
-        Revokes the specified permission (or all permissions) on a resource
-        from a role or user.
-
-        To be able to revoke a permission on some resource you have to
-        have that permission yourself and also AUTHORIZE permission on it,
-        or on one of its parent resources.
-
-        See HELP PERMISSIONS for more info on the available permissions.
-        """
-
-    def help_list_permissions(self):
-        print """
-        LIST (<permission> [PERMISSION] | ALL [PERMISSIONS])
-                  [ON ALL KEYSPACES
-                    | KEYSPACE <keyspace>
-                    | [TABLE] [<keyspace>.]<table>]
-                  [OF [ROLE <rolename> | USER <username>]
-                  [NORECURSIVE]
-
-        Omitting ON <resource> part will list permissions on ALL KEYSPACES,
-        every keyspace and table.
-        Omitting OF [ROLE <rolename> | USER <username>] part will list 
permissions
-        of all roles and users.
-        Omitting NORECURSIVE specifier will list permissions of the resource
-        and all its parents (table, table's keyspace and ALL KEYSPACES).
-
-        See HELP PERMISSIONS for more info on the available permissions.
-        """
-
-    def help_permissions(self):
-        print """
-        PERMISSIONS
-
-        Cassandra has 6 permissions:
-          ALTER: required for ALTER KEYSPCE, ALTER TABLE, CREATE INDEX, DROP 
INDEX
-          AUTHORIZE: required for GRANT, REVOKE
-          CREATE: required for CREATE KEYSPACE, CREATE TABLE
-          DROP: required for DROP KEYSPACE, DROP TABLE
-          MODIFY: required for INSERT, DELETE, UPDATE, TRUNCATE
-          SELECT: required for SELECT
-        """
-
-    def help_create_role(self):
-        print """
-        CREATE ROLE <rolename>;
-
-        CREATE ROLE creates a new Cassandra role.
-        Only superusers can issue CREATE ROLE requests.
-        To create a superuser account use SUPERUSER option (NOSUPERUSER is the 
default).
-        """
-
-    def help_drop_role(self):
-        print """
-        DROP ROLE <rolename>;
-
-        DROP ROLE removes an existing role. You have to be logged in as a 
superuser
-        to issue a DROP ROLE statement.
-        """
-
-    def help_list_roles(self):
-        print """
-        LIST ROLES [OF [ROLE <rolename> | USER <username>] [NORECURSIVE]];
-
-        Only superusers can use the OF clause to list the roles granted to a 
role or user.
-        If a superuser omits the OF clause then all the created roles will be 
listed.
-        If a non-superuser calls LIST ROLES then the roles granted to that 
user are listed.
-        If NORECURSIVE is provided then only directly granted roles are listed.
-        """
-
-    def help_grant_role(self):
-        print """
-        GRANT ROLE <rolename> TO [ROLE <rolename> | USER <username>]
-
-        Grant the specified role to another role or user. You have to be logged
-        in as superuser to issue a GRANT ROLE statement.
-        """
-
-    def help_revoke_role(self):
-        print """
-        REVOKE ROLE <rolename> FROM [ROLE <rolename> | USER <username>]
-
-        Revoke the specified role from another role or user. You have to be 
logged
-        in as superuser to issue a REVOKE ROLE statement.
-        """
+        return 'revokeRoleStmt'

Reply via email to