From 1456ec83186f4e91a80129f6487416b81d7a92b2 Mon Sep 17 00:00:00 2001 From: Mikhail Stepura Date: Thu, 28 Aug 2014 16:10:36 -0700 Subject: [PATCH] (cqlsh) tab completion for triggers patch by Mikhail Stepura; reviewed by Tyler Hobbs for CASSANDRA-7824 --- CHANGES.txt | 1 + bin/cqlsh | 8 ++++++++ doc/cql3/CQL.textile | 33 +++++++++++++++++++++++++++++++++ pylib/cqlshlib/cql3handling.py | 24 ++++++++++++++++++++++++ 4 files changed, 66 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index c4698d67c2..1706faf06e 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,5 @@ 2.1.1 + * (cqlsh) tab-completion for triggers (CASSANDRA-7824) * (cqlsh): Support for query paging (CASSANDRA-7514) * (cqlsh): Show progress of COPY operations (CASSANDRA-7789) * Add syntax to remove multiple elements from a map (CASSANDRA-6599) diff --git a/bin/cqlsh b/bin/cqlsh index d61a0082fe..fa5de0584c 100755 --- a/bin/cqlsh +++ b/bin/cqlsh @@ -711,6 +711,14 @@ class Shell(cmd.Cmd): return cql3handling.UserTypesMeta.from_layout(data) + def get_trigger_names(self, ksname=None): + if ksname is None: + ksname = self.current_keyspace + + return [trigger.name + for table in self.get_keyspace_meta(ksname).tables.values() + for trigger in table.triggers.values()] + def reset_statement(self): self.reset_prompt() self.statement.truncate(0) diff --git a/doc/cql3/CQL.textile b/doc/cql3/CQL.textile index 611bbb8a43..3b322d5c98 100644 --- a/doc/cql3/CQL.textile +++ b/doc/cql3/CQL.textile @@ -540,6 +540,39 @@ The @DROP TYPE@ statement results in the immediate, irreversible removal of a ty If the type does not exist, an error will be returned unless @IF EXISTS@ is used, in which case the operation is a no-op. +h3(#createTriggerStmt). CREATE TRIGGER + +__Syntax:__ + +bc(syntax).. + ::= CREATE TRIGGER ( IF NOT EXISTS )? ( )? + ON + USING + +p. +__Sample:__ + +bc(sample). +CREATE TRIGGER myTrigger ON myTable USING 'org.apache.cassandra.triggers.InvertedIndex'; + +The actual logic that makes up the trigger can be written in any Java (JVM) language and exists outside the database. You place the trigger code in a @lib/triggers@ subdirectory of the Cassandra installation directory, it loads during cluster startup, and exists on every node that participates in a cluster. The trigger defined on a table fires before a requested DML statement occurs, which ensures the atomicity of the transaction. + +h3(#dropTriggerStmt). DROP TRIGGER + +__Syntax:__ + +bc(syntax).. + ::= DROP TRIGGER ( IF EXISTS )? ( )? + ON + +p. +__Sample:__ + +bc(sample). +DROP TRIGGER myTrigger ON myTable; + +@DROP TRIGGER@ statement removes the registration of a trigger created using @CREATE TRIGGER@. + h2(#dataManipulation). Data Manipulation h3(#insertStmt). INSERT diff --git a/pylib/cqlshlib/cql3handling.py b/pylib/cqlshlib/cql3handling.py index e58f41d728..43882dec5f 100644 --- a/pylib/cqlshlib/cql3handling.py +++ b/pylib/cqlshlib/cql3handling.py @@ -228,10 +228,12 @@ JUNK ::= /([ \t\r\f\v]+|(--|[/][/])[^\n\r]*([\n\r]|$)|[/][*].*?[*][/])/ ; | | | + | | | | | + | | | | @@ -1153,6 +1155,28 @@ def username_name_completer(ctxt, cass): session = cass.session return [maybe_quote(row.values()[0].replace("'", "''")) for row in session.execute("LIST USERS")] +syntax_rules += r''' + ::= "CREATE" "TRIGGER" ( "IF" "NOT" "EXISTS" )? + "ON" cf= "USING" class= + ; + + ::= "DROP" "TRIGGER" ( "IF" "EXISTS" )? triggername= + "ON" cf= + ; +''' +explain_completion('createTriggerStatement', 'class', '\'fully qualified class name\'') + +def get_trigger_names(ctxt, cass): + ks = ctxt.get_binding('ksname', None) + if ks is not None: + ks = dequote_name(ks) + return cass.get_trigger_names(ks) + +@completer_for('dropTriggerStatement', 'triggername') +def alter_type_field_completer(ctxt, cass): + names = get_trigger_names(ctxt, cass) + return map(maybe_escape_name, names) + # END SYNTAX/COMPLETION RULE DEFINITIONS CqlRuleSet.append_rules(syntax_rules)