Merge branch cassandra-2.1 into cassandra-2.2
Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/94a7d068 Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/94a7d068 Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/94a7d068 Branch: refs/heads/cassandra-3.0 Commit: 94a7d0682e037c8fb4226a1c5f1f47918912f2e2 Parents: 3b7ccdf 806378c Author: blerer <benjamin.le...@datastax.com> Authored: Fri Oct 16 11:52:51 2015 +0200 Committer: blerer <benjamin.le...@datastax.com> Committed: Fri Oct 16 11:53:52 2015 +0200 ---------------------------------------------------------------------- pylib/cqlshlib/cql3handling.py | 8 +- pylib/cqlshlib/cqlhandling.py | 10 + pylib/cqlshlib/test/run_cqlsh.py | 2 +- pylib/cqlshlib/test/test_cql_parsing.py | 240 +++++++++++----------- pylib/cqlshlib/test/test_cqlsh_completion.py | 10 +- pylib/cqlshlib/test/test_cqlsh_output.py | 9 +- 6 files changed, 145 insertions(+), 134 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/94a7d068/pylib/cqlshlib/cql3handling.py ---------------------------------------------------------------------- diff --cc pylib/cqlshlib/cql3handling.py index 40b7d6b,5f93003..0ee0a38 --- a/pylib/cqlshlib/cql3handling.py +++ b/pylib/cqlshlib/cql3handling.py @@@ -166,10 -162,10 +166,14 @@@ JUNK ::= /([ \t\r\f\v]+|(--|[/][/])[^\n | <boolean> | <blobLiteral> | <collectionLiteral> -- | <functionName> <functionArguments> ++ | <functionLiteral> <functionArguments> | "NULL" ; ++<functionLiteral> ::= (<identifier> ( "." <identifier> )?) ++ | "TOKEN" ++ ; ++ <functionArguments> ::= "(" ( <term> ( "," <term> )* )? ")" ; @@@ -1391,21 -1227,6 +1395,21 @@@ def username_name_completer(ctxt, cass) session = cass.session return [maybe_quote(row.values()[0].replace("'", "''")) for row in session.execute("LIST USERS")] + +@completer_for('rolename', 'role') +def rolename_completer(ctxt, cass): + def maybe_quote(name): + if CqlRuleSet.is_valid_cql3_name(name): + return name + return "'%s'" % name + + # disable completion for CREATE ROLE. - if ctxt.matched[0][0] == 'K_CREATE': ++ if ctxt.matched[0][1].upper() == 'CREATE': + return [Hint('<rolename>')] + + session = cass.session + return [maybe_quote(row[0].replace("'", "''")) for row in session.execute("LIST ROLES")] + syntax_rules += r''' <createTriggerStatement> ::= "CREATE" "TRIGGER" ( "IF" "NOT" "EXISTS" )? <cident> "ON" cf=<columnFamilyName> "USING" class=<stringLiteral> http://git-wip-us.apache.org/repos/asf/cassandra/blob/94a7d068/pylib/cqlshlib/cqlhandling.py ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/94a7d068/pylib/cqlshlib/test/run_cqlsh.py ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/94a7d068/pylib/cqlshlib/test/test_cql_parsing.py ---------------------------------------------------------------------- diff --cc pylib/cqlshlib/test/test_cql_parsing.py index c011d94,f88b839..ad60c9b --- a/pylib/cqlshlib/test/test_cql_parsing.py +++ b/pylib/cqlshlib/test/test_cql_parsing.py @@@ -17,558 -17,60 +17,558 @@@ # to configure behavior, define $CQL_TEST_HOST to the destination address # for Thrift connections, and $CQL_TEST_PORT to the associated port. -from .basecase import BaseTestCase, cqlsh -from .cassconnect import get_test_keyspace, testrun_cqlsh, testcall_cqlsh +from unittest import TestCase +from operator import itemgetter -class TestCqlParsing(BaseTestCase): - def setUp(self): - self.cqlsh_runner = testrun_cqlsh(cqlver=cqlsh.DEFAULT_CQLVER, env={'COLUMNS': '100000'}) - self.cqlsh = self.cqlsh_runner.__enter__() +from ..cql3handling import CqlRuleSet - def tearDown(self): - pass +class TestCqlParsing(TestCase): def test_parse_string_literals(self): - pass + for n in ["'eggs'", "'Sausage 1'", "'spam\nspam\n\tsausage'", "''"]: + self.assertSequenceEqual(tokens_with_types(CqlRuleSet.lex(n)), + [(n, 'quotedStringLiteral')]) + self.assertSequenceEqual(tokens_with_types(CqlRuleSet.lex("'eggs'")), + [("'eggs'", 'quotedStringLiteral')]) + + tokens = CqlRuleSet.lex("'spam\nspam\n\tsausage'") + tokens = CqlRuleSet.cql_massage_tokens(tokens) + self.assertEqual(tokens[0][0], "quotedStringLiteral") + + tokens = CqlRuleSet.lex("'spam\nspam\n") + tokens = CqlRuleSet.cql_massage_tokens(tokens) + self.assertEqual(tokens[0][0], "unclosedString") + + tokens = CqlRuleSet.lex("'foo bar' 'spam\nspam\n") + tokens = CqlRuleSet.cql_massage_tokens(tokens) + self.assertEqual(tokens[1][0], "unclosedString") + + def test_parse_pgstring_literals(self): + for n in ["$$eggs$$", "$$Sausage 1$$", "$$spam\nspam\n\tsausage$$", "$$$$"]: + self.assertSequenceEqual(tokens_with_types(CqlRuleSet.lex(n)), + [(n, 'pgStringLiteral')]) + self.assertSequenceEqual(tokens_with_types(CqlRuleSet.lex("$$eggs$$")), + [("$$eggs$$", 'pgStringLiteral')]) + + tokens = CqlRuleSet.lex("$$spam\nspam\n\tsausage$$") + tokens = CqlRuleSet.cql_massage_tokens(tokens) + # [('pgStringLiteral', '$$spam\nspam\n\tsausage$$', (0, 22))] + self.assertEqual(tokens[0][0], "pgStringLiteral") + + tokens = CqlRuleSet.lex("$$spam\nspam\n") + tokens = CqlRuleSet.cql_massage_tokens(tokens) + # [('unclosedPgString', '$$', (0, 2)), ('identifier', 'spam', (2, 6)), ('identifier', 'spam', (7, 11))] + self.assertEqual(tokens[0][0], "unclosedPgString") + + tokens = CqlRuleSet.lex("$$foo bar$$ $$spam\nspam\n") + tokens = CqlRuleSet.cql_massage_tokens(tokens) + # [('pgStringLiteral', '$$foo bar$$', (0, 11)), ('unclosedPgString', '$$', (12, 14)), ('identifier', 'spam', (14, 18)), ('identifier', 'spam', (19, 23))] + self.assertEqual(tokens[0][0], "pgStringLiteral") + self.assertEqual(tokens[1][0], "unclosedPgString") def test_parse_numbers(self): - pass + for n in ['6', '398', '18018']: + self.assertSequenceEqual(tokens_with_types(CqlRuleSet.lex(n)), + [(n, 'wholenumber')]) def test_parse_uuid(self): - pass + uuids = ['4feeae80-e9cc-11e4-b571-0800200c9a66', + '7142303f-828f-4806-be9e-7a973da0c3f9', + 'dff8d435-9ca0-487c-b5d0-b0fe5c5768a8'] + for u in uuids: + self.assertSequenceEqual(tokens_with_types(CqlRuleSet.lex(u)), + [(u, 'uuid')]) def test_comments_in_string_literals(self): - pass + comment_strings = ["'sausage -- comment'", + "'eggs and spam // comment string'", + "'spam eggs sausage and spam /* still in string'"] + for s in comment_strings: + self.assertSequenceEqual(tokens_with_types(CqlRuleSet.lex(s)), + [(s, 'quotedStringLiteral')]) def test_colons_in_string_literals(self): - pass + comment_strings = ["'Movie Title: The Movie'", + "':a:b:c:'", + "'(>>=) :: (Monad m) => m a -> (a -> m b) -> m b'"] + for s in comment_strings: + self.assertSequenceEqual(tokens_with_types(CqlRuleSet.lex(s)), + [(s, 'quotedStringLiteral')]) def test_partial_parsing(self): - pass + [parsed] = CqlRuleSet.cql_parse('INSERT INTO ks.test') + self.assertSequenceEqual(parsed.matched, []) + self.assertSequenceEqual(tokens_with_types(parsed.remainder), - [('INSERT', 'identifier'), - ('INTO', 'identifier'), ++ [('INSERT', 'reserved_identifier'), ++ ('INTO', 'reserved_identifier'), + ('ks', 'identifier'), + ('.', 'op'), + ('test', 'identifier')]) def test_parse_select(self): - pass + parsed = parse_cqlsh_statements('SELECT FROM ks.tab;') + self.assertSequenceEqual(tokens_with_types(parsed), - [('SELECT', 'identifier'), - ('FROM', 'identifier'), ++ [('SELECT', 'reserved_identifier'), ++ ('FROM', 'reserved_identifier'), + ('ks', 'identifier'), + ('.', 'op'), + ('tab', 'identifier'), + (';', 'endtoken')]) + + parsed = parse_cqlsh_statements('SELECT FROM "MyTable";') + self.assertSequenceEqual(tokens_with_types(parsed), - [('SELECT', 'identifier'), - ('FROM', 'identifier'), ++ [('SELECT', 'reserved_identifier'), ++ ('FROM', 'reserved_identifier'), + ('"MyTable"', 'quotedName'), + (';', 'endtoken')]) + + parsed = parse_cqlsh_statements( + 'SELECT FROM tab WHERE foo = 3;') + self.assertSequenceEqual(tokens_with_types(parsed), - [('SELECT', 'identifier'), - ('FROM', 'identifier'), ++ [('SELECT', 'reserved_identifier'), ++ ('FROM', 'reserved_identifier'), + ('tab', 'identifier'), - ('WHERE', 'identifier'), ++ ('WHERE', 'reserved_identifier'), + ('foo', 'identifier'), + ('=', 'op'), + ('3', 'wholenumber'), + (';', 'endtoken')]) + + parsed = parse_cqlsh_statements( + 'SELECT FROM tab ORDER BY event_id DESC LIMIT 1000') + self.assertSequenceEqual(tokens_with_types(parsed), - [('SELECT', 'identifier'), - ('FROM', 'identifier'), ++ [('SELECT', 'reserved_identifier'), ++ ('FROM', 'reserved_identifier'), + ('tab', 'identifier'), - ('ORDER', 'identifier'), - ('BY', 'identifier'), ++ ('ORDER', 'reserved_identifier'), ++ ('BY', 'reserved_identifier'), + ('event_id', 'identifier'), - ('DESC', 'identifier'), - ('LIMIT', 'identifier'), ++ ('DESC', 'reserved_identifier'), ++ ('LIMIT', 'reserved_identifier'), + ('1000', 'wholenumber')]) + + parsed = parse_cqlsh_statements( + 'SELECT FROM tab WHERE clustering_column > 200 ' + 'AND clustering_column < 400 ALLOW FILTERING') + self.assertSequenceEqual(tokens_with_types(parsed), - [('SELECT', 'identifier'), - ('FROM', 'identifier'), ++ [('SELECT', 'reserved_identifier'), ++ ('FROM', 'reserved_identifier'), + ('tab', 'identifier'), - ('WHERE', 'identifier'), ++ ('WHERE', 'reserved_identifier'), + ('clustering_column', 'identifier'), + ('>', 'cmp'), + ('200', 'wholenumber'), - ('AND', 'identifier'), ++ ('AND', 'reserved_identifier'), + ('clustering_column', 'identifier'), + ('<', 'cmp'), + ('400', 'wholenumber'), + # 'allow' and 'filtering' are not keywords - ('ALLOW', 'identifier'), ++ ('ALLOW', 'reserved_identifier'), + ('FILTERING', 'identifier')]) def test_parse_insert(self): - pass + parsed = parse_cqlsh_statements('INSERT INTO mytable (x) VALUES (2);') + self.assertSequenceEqual(tokens_with_types(parsed), - [('INSERT', 'identifier'), - ('INTO', 'identifier'), ++ [('INSERT', 'reserved_identifier'), ++ ('INTO', 'reserved_identifier'), + ('mytable', 'identifier'), + ('(', 'op'), + ('x', 'identifier'), + (')', 'op'), + ('VALUES', 'identifier'), + ('(', 'op'), + ('2', 'wholenumber'), + (')', 'op'), + (';', 'endtoken')]) + + parsed = parse_cqlsh_statements( + "INSERT INTO mytable (x, y) VALUES (2, 'eggs');") + self.assertSequenceEqual(tokens_with_types(parsed), - [('INSERT', 'identifier'), - ('INTO', 'identifier'), ++ [('INSERT', 'reserved_identifier'), ++ ('INTO', 'reserved_identifier'), + ('mytable', 'identifier'), + ('(', 'op'), + ('x', 'identifier'), + (',', 'op'), + ('y', 'identifier'), + (')', 'op'), + ('VALUES', 'identifier'), + ('(', 'op'), + ('2', 'wholenumber'), + (',', 'op'), + ("'eggs'", 'quotedStringLiteral'), + (')', 'op'), + (';', 'endtoken')]) + + parsed = parse_cqlsh_statements( + "INSERT INTO mytable (x, y) VALUES (2, 'eggs');") + self.assertSequenceEqual(tokens_with_types(parsed), - [('INSERT', 'identifier'), - ('INTO', 'identifier'), ++ [('INSERT', 'reserved_identifier'), ++ ('INTO', 'reserved_identifier'), + ('mytable', 'identifier'), + ('(', 'op'), + ('x', 'identifier'), + (',', 'op'), + ('y', 'identifier'), + (')', 'op'), + ('VALUES', 'identifier'), + ('(', 'op'), + ('2', 'wholenumber'), + (',', 'op'), + ("'eggs'", 'quotedStringLiteral'), + (')', 'op'), + (';', 'endtoken')]) + + parsed = parse_cqlsh_statements( + "INSERT INTO mytable (ids) VALUES " + "(7ee251da-af52-49a4-97f4-3f07e406c7a7) " + "USING TTL 86400;") + self.assertSequenceEqual(tokens_with_types(parsed), - [('INSERT', 'identifier'), - ('INTO', 'identifier'), ++ [('INSERT', 'reserved_identifier'), ++ ('INTO', 'reserved_identifier'), + ('mytable', 'identifier'), + ('(', 'op'), + ('ids', 'identifier'), + (')', 'op'), + ('VALUES', 'identifier'), + ('(', 'op'), + ('7ee251da-af52-49a4-97f4-3f07e406c7a7', 'uuid'), + (')', 'op'), - ('USING', 'identifier'), ++ ('USING', 'reserved_identifier'), + ('TTL', 'identifier'), + ('86400', 'wholenumber'), + (';', 'endtoken')]) + + parsed = parse_cqlsh_statements( + "INSERT INTO test_table (username) VALUES ('Albert') " + "USING TIMESTAMP 1240003134 AND TTL 600;") + self.assertSequenceEqual(tokens_with_types(parsed), - [('INSERT', 'identifier'), - ('INTO', 'identifier'), ++ [('INSERT', 'reserved_identifier'), ++ ('INTO', 'reserved_identifier'), + ('test_table', 'identifier'), + ('(', 'op'), + ('username', 'identifier'), + (')', 'op'), + ('VALUES', 'identifier'), + ('(', 'op'), + ("'Albert'", 'quotedStringLiteral'), + (')', 'op'), - ('USING', 'identifier'), ++ ('USING', 'reserved_identifier'), + ('TIMESTAMP', 'identifier'), + ('1240003134', 'wholenumber'), - ('AND', 'identifier'), ++ ('AND', 'reserved_identifier'), + ('TTL', 'identifier'), + ('600', 'wholenumber'), + (';', 'endtoken')]) def test_parse_update(self): - pass + parsed = parse_cqlsh_statements( + "UPDATE tab SET x = 15 WHERE y = 'eggs';") + self.assertSequenceEqual(tokens_with_types(parsed), - [('UPDATE', 'identifier'), ++ [('UPDATE', 'reserved_identifier'), + ('tab', 'identifier'), - ('SET', 'identifier'), ++ ('SET', 'reserved_identifier'), + ('x', 'identifier'), + ('=', 'op'), + ('15', 'wholenumber'), - ('WHERE', 'identifier'), ++ ('WHERE', 'reserved_identifier'), + ('y', 'identifier'), + ('=', 'op'), + ("'eggs'", 'quotedStringLiteral'), + (';', 'endtoken')]) + + parsed = parse_cqlsh_statements( + "UPDATE tab USING TTL 432000 SET x = 15 WHERE y = 'eggs';") + self.assertSequenceEqual(tokens_with_types(parsed), - [('UPDATE', 'identifier'), ++ [('UPDATE', 'reserved_identifier'), + ('tab', 'identifier'), - ('USING', 'identifier'), ++ ('USING', 'reserved_identifier'), + ('TTL', 'identifier'), + ('432000', 'wholenumber'), - ('SET', 'identifier'), ++ ('SET', 'reserved_identifier'), + ('x', 'identifier'), + ('=', 'op'), + ('15', 'wholenumber'), - ('WHERE', 'identifier'), ++ ('WHERE', 'reserved_identifier'), + ('y', 'identifier'), + ('=', 'op'), + ("'eggs'", 'quotedStringLiteral'), + (';', 'endtoken')]) + + parsed = parse_cqlsh_statements( + "UPDATE tab SET x = 15, y = 'sausage' " + "WHERE y = 'eggs';") + self.assertSequenceEqual(tokens_with_types(parsed), - [('UPDATE', 'identifier'), ++ [('UPDATE', 'reserved_identifier'), + ('tab', 'identifier'), - ('SET', 'identifier'), ++ ('SET', 'reserved_identifier'), + ('x', 'identifier'), + ('=', 'op'), + ('15', 'wholenumber'), + (',', 'op'), + ('y', 'identifier'), + ('=', 'op'), + ("'sausage'", 'quotedStringLiteral'), - ('WHERE', 'identifier'), ++ ('WHERE', 'reserved_identifier'), + ('y', 'identifier'), + ('=', 'op'), + ("'eggs'", 'quotedStringLiteral'), + (';', 'endtoken')]) + + parsed = parse_cqlsh_statements( + "UPDATE tab SET x = 15 " + "WHERE y IN ('eggs', 'sausage', 'spam');") + self.assertSequenceEqual(tokens_with_types(parsed), - [('UPDATE', 'identifier'), ++ [('UPDATE', 'reserved_identifier'), + ('tab', 'identifier'), - ('SET', 'identifier'), ++ ('SET', 'reserved_identifier'), + ('x', 'identifier'), + ('=', 'op'), + ('15', 'wholenumber'), - ('WHERE', 'identifier'), ++ ('WHERE', 'reserved_identifier'), + ('y', 'identifier'), - ('IN', 'identifier'), ++ ('IN', 'reserved_identifier'), + ('(', 'op'), + ("'eggs'", 'quotedStringLiteral'), + (',', 'op'), + ("'sausage'", 'quotedStringLiteral'), + (',', 'op'), + ("'spam'", 'quotedStringLiteral'), + (')', 'op'), + (';', 'endtoken')]) + + parsed = parse_cqlsh_statements( + "UPDATE tab SET x = 15 " - "WHERE y = 'spam' if z = 'sausage';") ++ "WHERE y = 'spam' IF z = 'sausage';") + self.assertSequenceEqual(tokens_with_types(parsed), - [('UPDATE', 'identifier'), ++ [('UPDATE', 'reserved_identifier'), + ('tab', 'identifier'), - ('SET', 'identifier'), ++ ('SET', 'reserved_identifier'), + ('x', 'identifier'), + ('=', 'op'), + ('15', 'wholenumber'), - ('WHERE', 'identifier'), ++ ('WHERE', 'reserved_identifier'), + ('y', 'identifier'), + ('=', 'op'), + ("'spam'", 'quotedStringLiteral'), - ('if', 'identifier'), ++ ('IF', 'reserved_identifier'), + ('z', 'identifier'), + ('=', 'op'), + ("'sausage'", 'quotedStringLiteral'), + (';', 'endtoken')]) + + parsed = parse_cqlsh_statements( + "UPDATE tab SET x = 15 WHERE y = 'spam' " - "if z = 'sausage' AND w = 'spam';") ++ "IF z = 'sausage' AND w = 'spam';") + self.assertSequenceEqual(tokens_with_types(parsed), - [('UPDATE', 'identifier'), ++ [('UPDATE', 'reserved_identifier'), + ('tab', 'identifier'), - ('SET', 'identifier'), ++ ('SET', 'reserved_identifier'), + ('x', 'identifier'), + ('=', 'op'), + ('15', 'wholenumber'), - ('WHERE', 'identifier'), ++ ('WHERE', 'reserved_identifier'), + ('y', 'identifier'), + ('=', 'op'), + ("'spam'", 'quotedStringLiteral'), - ('if', 'identifier'), ++ ('IF', 'reserved_identifier'), + ('z', 'identifier'), + ('=', 'op'), + ("'sausage'", 'quotedStringLiteral'), - ('AND', 'identifier'), ++ ('AND', 'reserved_identifier'), + ('w', 'identifier'), + ('=', 'op'), + ("'spam'", 'quotedStringLiteral'), + (';', 'endtoken')]) + + parsed = parse_cqlsh_statements( + "UPDATE tab SET x = 15 WHERE y = 'spam' IF EXISTS") + self.assertSequenceEqual(tokens_with_types(parsed), - [('UPDATE', 'identifier'), ++ [('UPDATE', 'reserved_identifier'), + ('tab', 'identifier'), - ('SET', 'identifier'), ++ ('SET', 'reserved_identifier'), + ('x', 'identifier'), + ('=', 'op'), + ('15', 'wholenumber'), - ('WHERE', 'identifier'), ++ ('WHERE', 'reserved_identifier'), + ('y', 'identifier'), + ('=', 'op'), + ("'spam'", 'quotedStringLiteral'), - ('IF', 'identifier'), ++ ('IF', 'reserved_identifier'), + ('EXISTS', 'identifier')]) def test_parse_delete(self): - pass + parsed = parse_cqlsh_statements( + "DELETE FROM songs WHERE songid = 444;") + self.assertSequenceEqual(tokens_with_types(parsed), - [('DELETE', 'identifier'), - ('FROM', 'identifier'), ++ [('DELETE', 'reserved_identifier'), ++ ('FROM', 'reserved_identifier'), + ('songs', 'identifier'), - ('WHERE', 'identifier'), ++ ('WHERE', 'reserved_identifier'), + ('songid', 'identifier'), + ('=', 'op'), + ('444', 'wholenumber'), + (';', 'endtoken')]) + + parsed = parse_cqlsh_statements( + "DELETE FROM songs WHERE name IN " + "('Yellow Submarine', 'Eleanor Rigby');") + self.assertSequenceEqual(tokens_with_types(parsed), - [('DELETE', 'identifier'), - ('FROM', 'identifier'), ++ [('DELETE', 'reserved_identifier'), ++ ('FROM', 'reserved_identifier'), + ('songs', 'identifier'), - ('WHERE', 'identifier'), ++ ('WHERE', 'reserved_identifier'), + ('name', 'identifier'), - ('IN', 'identifier'), ++ ('IN', 'reserved_identifier'), + ('(', 'op'), + ("'Yellow Submarine'", 'quotedStringLiteral'), + (',', 'op'), + ("'Eleanor Rigby'", 'quotedStringLiteral'), + (')', 'op'), + (';', 'endtoken')]) + + parsed = parse_cqlsh_statements( - "DELETE task_map ['2014-12-25'] from tasks where user_id = 'Santa';") ++ "DELETE task_map ['2014-12-25'] FROM tasks WHERE user_id = 'Santa';") + self.assertSequenceEqual(tokens_with_types(parsed), - [('DELETE', 'identifier'), ++ [('DELETE', 'reserved_identifier'), + ('task_map', 'identifier'), + ('[', 'brackets'), + ("'2014-12-25'", 'quotedStringLiteral'), + (']', 'brackets'), - ('from', 'identifier'), ++ ('FROM', 'reserved_identifier'), + ('tasks', 'identifier'), - ('where', 'identifier'), ++ ('WHERE', 'reserved_identifier'), + ('user_id', 'identifier'), + ('=', 'op'), + ("'Santa'", 'quotedStringLiteral'), + (';', 'endtoken')]) + + parsed = parse_cqlsh_statements( - "DELETE my_list[0] from lists where user_id = 'Jim';") ++ "DELETE my_list[0] FROM lists WHERE user_id = 'Jim';") + self.assertSequenceEqual(tokens_with_types(parsed), - [('DELETE', 'identifier'), ++ [('DELETE', 'reserved_identifier'), + ('my_list', 'identifier'), + ('[', 'brackets'), + ('0', 'wholenumber'), + (']', 'brackets'), - ('from', 'identifier'), ++ ('FROM', 'reserved_identifier'), + ('lists', 'identifier'), - ('where', 'identifier'), ++ ('WHERE', 'reserved_identifier'), + ('user_id', 'identifier'), + ('=', 'op'), + ("'Jim'", 'quotedStringLiteral'), + (';', 'endtoken')]) def test_parse_batch(self): pass def test_parse_create_keyspace(self): - pass + parsed = parse_cqlsh_statements( + "CREATE KEYSPACE ks WITH REPLICATION = " + "{'class': 'SimpleStrategy', 'replication_factor': 1};") + self.assertSequenceEqual(tokens_with_types(parsed), - [('CREATE', 'identifier'), - ('KEYSPACE', 'identifier'), ++ [('CREATE', 'reserved_identifier'), ++ ('KEYSPACE', 'reserved_identifier'), + ('ks', 'identifier'), - ('WITH', 'identifier'), ++ ('WITH', 'reserved_identifier'), + ('REPLICATION', 'identifier'), + ('=', 'op'), + ('{', 'brackets'), + ("'class'", 'quotedStringLiteral'), + (':', 'colon'), + ("'SimpleStrategy'", 'quotedStringLiteral'), + (',', 'op'), + ("'replication_factor'", 'quotedStringLiteral'), + (':', 'colon'), + ('1', 'wholenumber'), + ('}', 'brackets'), + (';', 'endtoken')]) + + parsed = parse_cqlsh_statements( + 'CREATE KEYSPACE "Cql_test_KS" WITH REPLICATION = ' + "{'class': 'NetworkTopologyStrategy', 'dc1' : 3, 'dc2': 2};") + self.assertSequenceEqual(tokens_with_types(parsed), - [('CREATE', 'identifier'), - ('KEYSPACE', 'identifier'), ++ [('CREATE', 'reserved_identifier'), ++ ('KEYSPACE', 'reserved_identifier'), + ('"Cql_test_KS"', 'quotedName'), - ('WITH', 'identifier'), ++ ('WITH', 'reserved_identifier'), + ('REPLICATION', 'identifier'), + ('=', 'op'), + ('{', 'brackets'), + ("'class'", 'quotedStringLiteral'), + (':', 'colon'), + ("'NetworkTopologyStrategy'", + 'quotedStringLiteral'), + (',', 'op'), + ("'dc1'", 'quotedStringLiteral'), + (':', 'colon'), + ('3', 'wholenumber'), + (',', 'op'), + ("'dc2'", 'quotedStringLiteral'), + (':', 'colon'), + ('2', 'wholenumber'), + ('}', 'brackets'), + (';', 'endtoken')]) + + parsed = parse_cqlsh_statements( + "CREATE KEYSPACE ks WITH REPLICATION = " + "{'class': 'NetworkTopologyStrategy', 'dc1': 3} AND " + "DURABLE_WRITES = false;") + self.assertSequenceEqual(tokens_with_types(parsed), - [('CREATE', 'identifier'), - ('KEYSPACE', 'identifier'), ++ [('CREATE', 'reserved_identifier'), ++ ('KEYSPACE', 'reserved_identifier'), + ('ks', 'identifier'), - ('WITH', 'identifier'), ++ ('WITH', 'reserved_identifier'), + ('REPLICATION', 'identifier'), + ('=', 'op'), + ('{', 'brackets'), + ("'class'", 'quotedStringLiteral'), + (':', 'colon'), + ("'NetworkTopologyStrategy'", + 'quotedStringLiteral'), + (',', 'op'), + ("'dc1'", 'quotedStringLiteral'), + (':', 'colon'), + ('3', 'wholenumber'), + ('}', 'brackets'), - ('AND', 'identifier'), ++ ('AND', 'reserved_identifier'), + # 'DURABLE_WRITES' is not a keyword + ('DURABLE_WRITES', 'identifier'), + ('=', 'op'), + ('false', 'identifier'), + (';', 'endtoken')]) def test_parse_drop_keyspace(self): - pass + parsed = parse_cqlsh_statements( + 'DROP KEYSPACE ks;') + self.assertSequenceEqual(tokens_with_types(parsed), - [('DROP', 'identifier'), - ('KEYSPACE', 'identifier'), ++ [('DROP', 'reserved_identifier'), ++ ('KEYSPACE', 'reserved_identifier'), + ('ks', 'identifier'), + (';', 'endtoken')]) + + parsed = parse_cqlsh_statements( + 'DROP SCHEMA ks;') + self.assertSequenceEqual(tokens_with_types(parsed), - [('DROP', 'identifier'), - ('SCHEMA', 'identifier'), ++ [('DROP', 'reserved_identifier'), ++ ('SCHEMA', 'reserved_identifier'), + ('ks', 'identifier'), + (';', 'endtoken')]) - def test_parse_create_columnfamily(self): + parsed = parse_cqlsh_statements( + 'DROP KEYSPACE IF EXISTS "My_ks";') + self.assertSequenceEqual(tokens_with_types(parsed), - [('DROP', 'identifier'), - ('KEYSPACE', 'identifier'), - ('IF', 'identifier'), ++ [('DROP', 'reserved_identifier'), ++ ('KEYSPACE', 'reserved_identifier'), ++ ('IF', 'reserved_identifier'), + ('EXISTS', 'identifier'), + ('"My_ks"', 'quotedName'), + (';', 'endtoken')]) + + def test_parse_create_table(self): pass - def test_parse_drop_columnfamily(self): + def test_parse_drop_table(self): pass def test_parse_truncate(self): @@@ -581,129 -83,7 +581,129 @@@ pass def test_parse_create_index(self): - pass + parsed = parse_cqlsh_statements( + 'CREATE INDEX idx ON ks.tab (i);') + self.assertSequenceEqual(tokens_with_types(parsed), - (('CREATE', 'identifier'), - ('INDEX', 'identifier'), ++ (('CREATE', 'reserved_identifier'), ++ ('INDEX', 'reserved_identifier'), + ('idx', 'identifier'), - ('ON', 'identifier'), ++ ('ON', 'reserved_identifier'), + ('ks', 'identifier'), + ('.', 'op'), + ('tab', 'identifier'), + ('(', 'op'), + ('i', 'identifier'), + (')', 'op'), + (';', 'endtoken'))) + + parsed = parse_cqlsh_statements( + 'CREATE INDEX idx ON ks.tab (i) IF NOT EXISTS;') + self.assertSequenceEqual(tokens_with_types(parsed), - (('CREATE', 'identifier'), - ('INDEX', 'identifier'), ++ (('CREATE', 'reserved_identifier'), ++ ('INDEX', 'reserved_identifier'), + ('idx', 'identifier'), - ('ON', 'identifier'), ++ ('ON', 'reserved_identifier'), + ('ks', 'identifier'), + ('.', 'op'), + ('tab', 'identifier'), + ('(', 'op'), + ('i', 'identifier'), + (')', 'op'), - ('IF', 'identifier'), - ('NOT', 'identifier'), ++ ('IF', 'reserved_identifier'), ++ ('NOT', 'reserved_identifier'), + ('EXISTS', 'identifier'), + (';', 'endtoken'))) + + parsed = parse_cqlsh_statements( + 'CREATE INDEX idx ON tab (KEYS(i));') + self.assertSequenceEqual(tokens_with_types(parsed), - (('CREATE', 'identifier'), - ('INDEX', 'identifier'), ++ (('CREATE', 'reserved_identifier'), ++ ('INDEX', 'reserved_identifier'), + ('idx', 'identifier'), - ('ON', 'identifier'), ++ ('ON', 'reserved_identifier'), + ('tab', 'identifier'), + ('(', 'op'), + ('KEYS', 'identifier'), + ('(', 'op'), + ('i', 'identifier'), + (')', 'op'), + (')', 'op'), + (';', 'endtoken'))) + + parsed = parse_cqlsh_statements( + 'CREATE INDEX idx ON ks.tab FULL(i);') + self.assertSequenceEqual(tokens_with_types(parsed), - [('CREATE', 'identifier'), - ('INDEX', 'identifier'), ++ [('CREATE', 'reserved_identifier'), ++ ('INDEX', 'reserved_identifier'), + ('idx', 'identifier'), - ('ON', 'identifier'), ++ ('ON', 'reserved_identifier'), + ('ks', 'identifier'), + ('.', 'op'), + ('tab', 'identifier'), - ('FULL', 'identifier'), ++ ('FULL', 'reserved_identifier'), + ('(', 'op'), + ('i', 'identifier'), + (')', 'op'), + (';', 'endtoken')]) + + parsed = parse_cqlsh_statements( + 'CREATE CUSTOM INDEX idx ON ks.tab (i);') + self.assertSequenceEqual(tokens_with_types(parsed), - [('CREATE', 'identifier'), ++ [('CREATE', 'reserved_identifier'), + ('CUSTOM', 'identifier'), - ('INDEX', 'identifier'), ++ ('INDEX', 'reserved_identifier'), + ('idx', 'identifier'), - ('ON', 'identifier'), ++ ('ON', 'reserved_identifier'), + ('ks', 'identifier'), + ('.', 'op'), + ('tab', 'identifier'), + ('(', 'op'), + ('i', 'identifier'), + (')', 'op'), + (';', 'endtoken')]) + + parsed = parse_cqlsh_statements( + "CREATE INDEX idx ON ks.tab (i) USING " + "'org.custom.index.MyIndexClass';") + self.assertSequenceEqual(tokens_with_types(parsed), - [('CREATE', 'identifier'), - ('INDEX', 'identifier'), ++ [('CREATE', 'reserved_identifier'), ++ ('INDEX', 'reserved_identifier'), + ('idx', 'identifier'), - ('ON', 'identifier'), ++ ('ON', 'reserved_identifier'), + ('ks', 'identifier'), + ('.', 'op'), + ('tab', 'identifier'), + ('(', 'op'), + ('i', 'identifier'), + (')', 'op'), - ('USING', 'identifier'), ++ ('USING', 'reserved_identifier'), + ("'org.custom.index.MyIndexClass'", + 'quotedStringLiteral'), + (';', 'endtoken')]) + + parsed = parse_cqlsh_statements( + "CREATE INDEX idx ON ks.tab (i) WITH OPTIONS = " + "{'storage': '/mnt/ssd/indexes/'};") + self.assertSequenceEqual(tokens_with_types(parsed), - [('CREATE', 'identifier'), - ('INDEX', 'identifier'), ++ [('CREATE', 'reserved_identifier'), ++ ('INDEX', 'reserved_identifier'), + ('idx', 'identifier'), - ('ON', 'identifier'), ++ ('ON', 'reserved_identifier'), + ('ks', 'identifier'), + ('.', 'op'), + ('tab', 'identifier'), + ('(', 'op'), + ('i', 'identifier'), + (')', 'op'), - ('WITH', 'identifier'), ++ ('WITH', 'reserved_identifier'), + ('OPTIONS', 'identifier'), + ('=', 'op'), + ('{', 'brackets'), + ("'storage'", 'quotedStringLiteral'), + (':', 'colon'), + ("'/mnt/ssd/indexes/'", 'quotedStringLiteral'), + ('}', 'brackets'), + (';', 'endtoken')]) def test_parse_drop_index(self): pass http://git-wip-us.apache.org/repos/asf/cassandra/blob/94a7d068/pylib/cqlshlib/test/test_cqlsh_completion.py ---------------------------------------------------------------------- diff --cc pylib/cqlshlib/test/test_cqlsh_completion.py index 84d7ca6,5f7b6e4..7cf583d --- a/pylib/cqlshlib/test/test_cqlsh_completion.py +++ b/pylib/cqlshlib/test/test_cqlsh_completion.py @@@ -367,95 -365,7 +367,95 @@@ class TestCqlshCompletion(CqlshCompleti choices=['>=', '!=', '<=', 'IN', '[', ';', '=', '<', '>']) def test_complete_in_delete(self): - pass + self.trycompletions('DELETE F', choices=['FROM', '<identifier>', '<quotedName>']) + + self.trycompletions('DELETE a ', choices=['FROM', '[', ',']) + self.trycompletions('DELETE a [', + choices=['<wholenumber>', 'false', '-', '<uuid>', + '<pgStringLiteral>', '<float>', 'TOKEN', + '<identifier>', '<quotedStringLiteral>', + '{', '[', 'NULL', 'true', '<blobLiteral>']) + + self.trycompletions('DELETE a, ', + choices=['<identifier>', '<quotedName>']) + + self.trycompletions('DELETE a FROM ', + choices=['twenty_rows_table', + 'ascii_with_special_chars', 'users', + 'has_all_types', 'system.', + 'empty_composite_table', 'empty_table', + 'system_auth.', 'undefined_values_table', + 'dynamic_columns', + 'twenty_rows_composite_table', + 'utf8_with_special_chars', + 'system_traces.', 'songs', + '"' + self.cqlsh.keyspace + '".'], + other_choices_ok=True) + + self.trycompletions('DELETE FROM ', + choices=['twenty_rows_table', + 'ascii_with_special_chars', 'users', + 'has_all_types', 'system.', + 'empty_composite_table', 'empty_table', + 'system_auth.', 'undefined_values_table', + 'dynamic_columns', + 'twenty_rows_composite_table', + 'utf8_with_special_chars', + 'system_traces.', 'songs', + 'system_auth.', 'system_distributed.', - 'system_schema.','system_traces.', ++ 'system_traces.', + '"' + self.cqlsh.keyspace + '".'], + other_choices_ok=True) + self.trycompletions('DELETE FROM twenty_rows_composite_table ', + choices=['USING', 'WHERE']) + + self.trycompletions('DELETE FROM twenty_rows_composite_table U', + immediate='SING TIMESTAMP ') + + self.trycompletions('DELETE FROM twenty_rows_composite_table USING TIMESTAMP ', + choices=['<wholenumber>']) + self.trycompletions('DELETE FROM twenty_rows_composite_table USING TIMESTAMP 0', + choices=['<wholenumber>']) + self.trycompletions('DELETE FROM twenty_rows_composite_table USING TIMESTAMP 0 ', + immediate='WHERE ') + self.trycompletions('DELETE FROM twenty_rows_composite_table USING TIMESTAMP 0 WHERE ', + choices=['a', 'b', 'TOKEN(']) + + self.trycompletions('DELETE FROM twenty_rows_composite_table USING TIMESTAMP 0 WHERE a ', + choices=['<=', '>=', 'CONTAINS', 'IN', '[', '=', '<', '>']) + + self.trycompletions('DELETE FROM twenty_rows_composite_table USING TIMESTAMP 0 WHERE TOKEN(', + immediate='a ') + self.trycompletions('DELETE FROM twenty_rows_composite_table USING TIMESTAMP 0 WHERE TOKEN(a', + immediate=' ') + self.trycompletions('DELETE FROM twenty_rows_composite_table USING TIMESTAMP 0 WHERE TOKEN(a ', + choices=[')', ',']) + self.trycompletions('DELETE FROM twenty_rows_composite_table USING TIMESTAMP 0 WHERE TOKEN(a) ', + choices=['>=', '<=', '=', '<', '>']) + self.trycompletions('DELETE FROM twenty_rows_composite_table USING TIMESTAMP 0 WHERE TOKEN(a) >= ', + choices=['false', 'true', '<pgStringLiteral>', + 'token(', '-', '<float>', 'TOKEN', + '<identifier>', '<uuid>', '{', '[', 'NULL', + '<quotedStringLiteral>', '<blobLiteral>', + '<wholenumber>']) + self.trycompletions(('DELETE FROM twenty_rows_composite_table USING TIMESTAMP 0 WHERE ' + 'TOKEN(a) >= TOKEN(0) '), + choices=['AND', 'IF', ';']) + self.trycompletions(('DELETE FROM twenty_rows_composite_table USING TIMESTAMP 0 WHERE ' + 'TOKEN(a) >= TOKEN(0) IF '), + choices=['EXISTS', '<identifier>', '<quotedName>']) + self.trycompletions(('DELETE FROM twenty_rows_composite_table USING TIMESTAMP 0 WHERE ' + 'TOKEN(a) >= TOKEN(0) IF b '), + choices=['>=', '!=', '<=', 'IN', '[', '=', '<', '>']) + self.trycompletions(('DELETE FROM twenty_rows_composite_table USING TIMESTAMP 0 WHERE ' + 'TOKEN(a) >= TOKEN(0) IF b < 0 '), + choices=['AND', ';']) + self.trycompletions(('DELETE FROM twenty_rows_composite_table USING TIMESTAMP 0 WHERE ' + 'TOKEN(a) >= TOKEN(0) IF b < 0 AND '), + choices=['<identifier>', '<quotedName>']) + self.trycompletions(("DELETE FROM twenty_rows_composite_table USING TIMESTAMP 0 WHERE " + "b = 'eggs'"), + choices=['AND', 'IF', ';']) def test_complete_in_batch(self): pass @@@ -515,158 -425,11 +515,156 @@@ self.trycompletions("create keyspace blah with replication = {'class': 'Sim", "pleStrategy'") + def test_complete_in_drop(self): + self.trycompletions('DR', immediate='OP ') + self.trycompletions('DROP ', + choices=['AGGREGATE', 'COLUMNFAMILY', 'FUNCTION', + 'INDEX', 'KEYSPACE', 'ROLE', 'TABLE', - 'TRIGGER', 'TYPE', 'USER', 'MATERIALIZED']) ++ 'TRIGGER', 'TYPE', 'USER']) + def test_complete_in_drop_keyspace(self): - pass + self.trycompletions('DROP K', immediate='EYSPACE ') + quoted_keyspace = '"' + self.cqlsh.keyspace + '"' + self.trycompletions('DROP KEYSPACE ', + choices=['IF', quoted_keyspace]) + + self.trycompletions('DROP KEYSPACE ' + quoted_keyspace, + choices=[';']) + + self.trycompletions('DROP KEYSPACE I', + immediate='F EXISTS ' + quoted_keyspace + ';') + + def create_columnfamily_table_template(self, name): + """Parameterized test for CREATE COLUMNFAMILY and CREATE TABLE. Since + they're synonyms, they should have the same completion behavior, so this + test avoids duplication between tests for the two statements.""" + prefix = 'CREATE ' + name + ' ' + quoted_keyspace = '"' + self.cqlsh.keyspace + '"' + self.trycompletions(prefix + '', + choices=['IF', quoted_keyspace, '<new_table_name>']) + self.trycompletions(prefix + 'IF ', + immediate='NOT EXISTS ') + self.trycompletions(prefix + 'IF NOT EXISTS ', + choices=['<new_table_name>', quoted_keyspace]) + self.trycompletions(prefix + 'IF NOT EXISTS new_table ', + immediate='( ') + + self.trycompletions(prefix + quoted_keyspace, choices=['.', '(']) + + self.trycompletions(prefix + quoted_keyspace + '( ', + choices=['<new_column_name>', '<identifier>', + '<quotedName>']) + + self.trycompletions(prefix + quoted_keyspace + '.', + choices=['<new_table_name>']) + self.trycompletions(prefix + quoted_keyspace + '.new_table ', + immediate='( ') + self.trycompletions(prefix + quoted_keyspace + '.new_table ( ', + choices=['<new_column_name>', '<identifier>', + '<quotedName>']) + + self.trycompletions(prefix + ' new_table ( ', + choices=['<new_column_name>', '<identifier>', + '<quotedName>']) + self.trycompletions(prefix + ' new_table (col_a ine', + immediate='t ') + self.trycompletions(prefix + ' new_table (col_a int ', + choices=[',', 'PRIMARY']) + self.trycompletions(prefix + ' new_table (col_a int P', + immediate='RIMARY KEY ') + self.trycompletions(prefix + ' new_table (col_a int PRIMARY KEY ', + choices=[')', ',']) + + self.trycompletions(prefix + ' new_table (col_a int PRIMARY KEY,', + choices=['<identifier>', '<quotedName>']) + self.trycompletions(prefix + ' new_table (col_a int PRIMARY KEY)', + immediate=' ') + self.trycompletions(prefix + ' new_table (col_a int PRIMARY KEY) ', + choices=[';', 'WITH']) + self.trycompletions(prefix + ' new_table (col_a int PRIMARY KEY) W', + immediate='ITH ') + self.trycompletions(prefix + ' new_table (col_a int PRIMARY KEY) WITH ', + choices=['bloom_filter_fp_chance', 'compaction', + 'compression', + 'dclocal_read_repair_chance', + 'default_time_to_live', 'gc_grace_seconds', + 'max_index_interval', + 'memtable_flush_period_in_ms', + 'read_repair_chance', 'CLUSTERING', + 'COMPACT', 'caching', 'comment', + 'min_index_interval', 'speculative_retry']) + self.trycompletions(prefix + ' new_table (col_a int PRIMARY KEY) WITH ', + choices=['bloom_filter_fp_chance', 'compaction', + 'compression', + 'dclocal_read_repair_chance', + 'default_time_to_live', 'gc_grace_seconds', + 'max_index_interval', + 'memtable_flush_period_in_ms', + 'read_repair_chance', 'CLUSTERING', + 'COMPACT', 'caching', 'comment', + 'min_index_interval', 'speculative_retry']) + self.trycompletions(prefix + ' new_table (col_a int PRIMARY KEY) WITH bloom_filter_fp_chance ', + immediate='= ') + self.trycompletions(prefix + ' new_table (col_a int PRIMARY KEY) WITH bloom_filter_fp_chance = ', + choices=['<float_between_0_and_1>']) + + self.trycompletions(prefix + ' new_table (col_a int PRIMARY KEY) WITH compaction ', + immediate="= {'class': '") + self.trycompletions(prefix + " new_table (col_a int PRIMARY KEY) WITH compaction = " + + "{'class': '", + choices=['SizeTieredCompactionStrategy', + 'LeveledCompactionStrategy', + 'DateTieredCompactionStrategy']) + self.trycompletions(prefix + " new_table (col_a int PRIMARY KEY) WITH compaction = " + + "{'class': 'S", + immediate="izeTieredCompactionStrategy'") + self.trycompletions(prefix + " new_table (col_a int PRIMARY KEY) WITH compaction = " + + "{'class': 'SizeTieredCompactionStrategy", + immediate="'") + self.trycompletions(prefix + " new_table (col_a int PRIMARY KEY) WITH compaction = " + + "{'class': 'SizeTieredCompactionStrategy'", + choices=['}', ',']) + self.trycompletions(prefix + " new_table (col_a int PRIMARY KEY) WITH compaction = " + + "{'class': 'SizeTieredCompactionStrategy', ", + immediate="'") + self.trycompletions(prefix + " new_table (col_a int PRIMARY KEY) WITH compaction = " + + "{'class': 'SizeTieredCompactionStrategy', '", + choices=['bucket_high', 'bucket_low', 'class', + 'enabled', 'max_threshold', + 'min_sstable_size', 'min_threshold', + 'tombstone_compaction_interval', + 'tombstone_threshold', - 'unchecked_tombstone_compaction', - 'only_purge_repaired_tombstones']) ++ 'unchecked_tombstone_compaction']) + self.trycompletions(prefix + " new_table (col_a int PRIMARY KEY) WITH compaction = " + + "{'class': 'SizeTieredCompactionStrategy'}", + choices=[';', 'AND']) + self.trycompletions(prefix + " new_table (col_a int PRIMARY KEY) WITH compaction = " + + "{'class': 'SizeTieredCompactionStrategy'} AND ", + choices=['bloom_filter_fp_chance', 'compaction', + 'compression', + 'dclocal_read_repair_chance', + 'default_time_to_live', 'gc_grace_seconds', + 'max_index_interval', + 'memtable_flush_period_in_ms', + 'read_repair_chance', 'CLUSTERING', + 'COMPACT', 'caching', 'comment', + 'min_index_interval', 'speculative_retry']) + self.trycompletions(prefix + " new_table (col_a int PRIMARY KEY) WITH compaction = " + + "{'class': 'DateTieredCompactionStrategy', '", + choices=['base_time_seconds', 'max_sstable_age_days', + 'timestamp_resolution', 'min_threshold', 'class', 'max_threshold', + 'tombstone_compaction_interval', 'tombstone_threshold', - 'enabled', 'unchecked_tombstone_compaction', - 'only_purge_repaired_tombstones']) ++ 'enabled', 'unchecked_tombstone_compaction']) def test_complete_in_create_columnfamily(self): - pass + self.trycompletions('CREATE C', choices=['COLUMNFAMILY', 'CUSTOM']) + self.trycompletions('CREATE CO', immediate='LUMNFAMILY ') + self.create_columnfamily_table_template('COLUMNFAMILY') + + def test_complete_in_create_table(self): + self.trycompletions('CREATE T', choices=['TRIGGER', 'TABLE', 'TYPE']) + self.trycompletions('CREATE TA', immediate='BLE ') + self.create_columnfamily_table_template('TABLE') def test_complete_in_drop_columnfamily(self): pass http://git-wip-us.apache.org/repos/asf/cassandra/blob/94a7d068/pylib/cqlshlib/test/test_cqlsh_output.py ----------------------------------------------------------------------