| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.cassandra.cql3.statements; |
| |
| import java.util.Iterator; |
| import java.util.Optional; |
| |
| import com.google.common.collect.ImmutableList; |
| import com.google.common.collect.ImmutableMap; |
| |
| import org.apache.commons.lang3.ArrayUtils; |
| |
| import org.junit.Test; |
| |
| import com.datastax.driver.core.ResultSet; |
| import com.datastax.driver.core.Row; |
| import com.datastax.driver.core.SimpleStatement; |
| import com.datastax.driver.core.exceptions.InvalidQueryException; |
| |
| import org.apache.cassandra.config.DatabaseDescriptor; |
| import org.apache.cassandra.cql3.CQLTester; |
| import org.apache.cassandra.dht.Token; |
| import org.apache.cassandra.locator.InetAddressAndPort; |
| import org.apache.cassandra.locator.TokenMetadata; |
| import org.apache.cassandra.schema.Schema; |
| import org.apache.cassandra.schema.TableId; |
| import org.apache.cassandra.service.StorageService; |
| import org.apache.cassandra.transport.ProtocolVersion; |
| |
| import static java.lang.String.format; |
| import static org.apache.cassandra.schema.SchemaConstants.*; |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertTrue; |
| import static org.junit.Assert.fail; |
| |
| public class DescribeStatementTest extends CQLTester |
| { |
| @Test |
| public void testSchemaChangeDuringPaging() |
| { |
| SimpleStatement stmt = new SimpleStatement("DESCRIBE KEYSPACES"); |
| stmt.setFetchSize(1); |
| ResultSet rs = executeNet(ProtocolVersion.CURRENT, stmt); |
| Iterator<Row> iter = rs.iterator(); |
| assertTrue(iter.hasNext()); |
| iter.next(); |
| |
| createKeyspace("CREATE KEYSPACE %s WITH REPLICATION = {'class' : 'SimpleStrategy', 'replication_factor' : 1};"); |
| |
| try |
| { |
| iter.next(); |
| fail("Expected InvalidQueryException"); |
| } |
| catch (InvalidQueryException e) |
| { |
| assertEquals(DescribeStatement.SCHEMA_CHANGED_WHILE_PAGING_MESSAGE, e.getMessage()); |
| } |
| } |
| |
| @Test |
| public void testDescribeFunctionAndAggregate() throws Throwable |
| { |
| String fNonOverloaded = createFunction(KEYSPACE_PER_TEST, |
| "", |
| "CREATE OR REPLACE FUNCTION %s() " + |
| "CALLED ON NULL INPUT " + |
| "RETURNS int " + |
| "LANGUAGE java " + |
| "AS 'throw new RuntimeException();';"); |
| |
| String fOverloaded = createFunction(KEYSPACE_PER_TEST, |
| "int, ascii", |
| "CREATE FUNCTION %s (input int, other_in ascii) " + |
| "RETURNS NULL ON NULL INPUT " + |
| "RETURNS text " + |
| "LANGUAGE java " + |
| "AS 'return \"Hello World\";'"); |
| createFunctionOverload(fOverloaded, |
| "text, ascii", |
| "CREATE FUNCTION %s (input text, other_in ascii) " + |
| "RETURNS NULL ON NULL INPUT " + |
| "RETURNS text " + |
| "LANGUAGE java " + |
| "AS 'return \"Hello World\";'"); |
| |
| for (String describeKeyword : new String[]{"DESCRIBE", "DESC"}) |
| { |
| assertRowsNet(executeDescribeNet(describeKeyword + " FUNCTION " + fNonOverloaded), |
| row(KEYSPACE_PER_TEST, |
| "function", |
| shortFunctionName(fNonOverloaded) + "()", |
| "CREATE FUNCTION " + fNonOverloaded + "()\n" + |
| " CALLED ON NULL INPUT\n" + |
| " RETURNS int\n" + |
| " LANGUAGE java\n" + |
| " AS $$throw new RuntimeException();$$;")); |
| |
| assertRowsNet(executeDescribeNet(describeKeyword + " FUNCTION " + fOverloaded), |
| row(KEYSPACE_PER_TEST, |
| "function", |
| shortFunctionName(fOverloaded) + "(int, ascii)", |
| "CREATE FUNCTION " + fOverloaded + "(input int, other_in ascii)\n" + |
| " RETURNS NULL ON NULL INPUT\n" + |
| " RETURNS text\n" + |
| " LANGUAGE java\n" + |
| " AS $$return \"Hello World\";$$;"), |
| row(KEYSPACE_PER_TEST, |
| "function", |
| shortFunctionName(fOverloaded) + "(text, ascii)", |
| "CREATE FUNCTION " + fOverloaded + "(input text, other_in ascii)\n" + |
| " RETURNS NULL ON NULL INPUT\n" + |
| " RETURNS text\n" + |
| " LANGUAGE java\n" + |
| " AS $$return \"Hello World\";$$;")); |
| |
| assertRowsNet(executeDescribeNet(describeKeyword + " FUNCTIONS"), |
| row(KEYSPACE_PER_TEST, |
| "function", |
| shortFunctionName(fNonOverloaded) + "()"), |
| row(KEYSPACE_PER_TEST, |
| "function", |
| shortFunctionName(fOverloaded) + "(int, ascii)"), |
| row(KEYSPACE_PER_TEST, |
| "function", |
| shortFunctionName(fOverloaded) + "(text, ascii)")); |
| } |
| |
| String fIntState = createFunction(KEYSPACE_PER_TEST, |
| "int, int", |
| "CREATE FUNCTION %s (state int, add_to int) " + |
| "CALLED ON NULL INPUT " + |
| "RETURNS int " + |
| "LANGUAGE java " + |
| "AS 'return state + add_to;'"); |
| String fFinal = createFunction(KEYSPACE_PER_TEST, |
| "int", |
| "CREATE FUNCTION %s (state int) " + |
| "RETURNS NULL ON NULL INPUT " + |
| "RETURNS int " + |
| "LANGUAGE java " + |
| "AS 'return state;'"); |
| |
| String aNonDeterministic = createAggregate(KEYSPACE_PER_TEST, |
| "int", |
| format("CREATE AGGREGATE %%s(int) " + |
| "SFUNC %s " + |
| "STYPE int " + |
| "INITCOND 42", |
| shortFunctionName(fIntState))); |
| String aDeterministic = createAggregate(KEYSPACE_PER_TEST, |
| "int", |
| format("CREATE AGGREGATE %%s(int) " + |
| "SFUNC %s " + |
| "STYPE int " + |
| "FINALFUNC %s ", |
| shortFunctionName(fIntState), |
| shortFunctionName(fFinal))); |
| |
| for (String describeKeyword : new String[]{"DESCRIBE", "DESC"}) |
| { |
| assertRowsNet(executeDescribeNet(describeKeyword + " AGGREGATE " + aNonDeterministic), |
| row(KEYSPACE_PER_TEST, |
| "aggregate", |
| shortFunctionName(aNonDeterministic) + "(int)", |
| "CREATE AGGREGATE " + aNonDeterministic + "(int)\n" + |
| " SFUNC " + shortFunctionName(fIntState) + "\n" + |
| " STYPE int\n" + |
| " INITCOND 42;")); |
| assertRowsNet(executeDescribeNet(describeKeyword + " AGGREGATE " + aDeterministic), |
| row(KEYSPACE_PER_TEST, |
| "aggregate", |
| shortFunctionName(aDeterministic) + "(int)", |
| "CREATE AGGREGATE " + aDeterministic + "(int)\n" + |
| " SFUNC " + shortFunctionName(fIntState) + "\n" + |
| " STYPE int\n" + |
| " FINALFUNC " + shortFunctionName(fFinal) + ";")); |
| assertRowsNet(executeDescribeNet(describeKeyword + " AGGREGATES"), |
| row(KEYSPACE_PER_TEST, |
| "aggregate", |
| shortFunctionName(aNonDeterministic) + "(int)"), |
| row(KEYSPACE_PER_TEST, |
| "aggregate", |
| shortFunctionName(aDeterministic) + "(int)")); |
| } |
| } |
| |
| @Test |
| public void testDescribeFunctionWithTuples() throws Throwable |
| { |
| String function = createFunction(KEYSPACE_PER_TEST, |
| "tuple<int>, list<frozen<tuple<int, text>>>, tuple<frozen<tuple<int, text>>, text>", |
| "CREATE OR REPLACE FUNCTION %s(t tuple<int>, l list<frozen<tuple<int, text>>>, nt tuple<frozen<tuple<int, text>>, text>) " + |
| "CALLED ON NULL INPUT " + |
| "RETURNS tuple<int, text> " + |
| "LANGUAGE java " + |
| "AS 'throw new RuntimeException();';"); |
| |
| assertRowsNet(executeDescribeNet("DESCRIBE FUNCTION " + function), |
| row(KEYSPACE_PER_TEST, |
| "function", |
| shortFunctionName(function) + "(tuple<int>, list<frozen<tuple<int, text>>>, tuple<frozen<tuple<int, text>>, text>)", |
| "CREATE FUNCTION " + function + "(t tuple<int>, l list<frozen<tuple<int, text>>>, nt tuple<frozen<tuple<int, text>>, text>)\n" + |
| " CALLED ON NULL INPUT\n" + |
| " RETURNS tuple<int, text>\n" + |
| " LANGUAGE java\n" + |
| " AS $$throw new RuntimeException();$$;")); |
| } |
| |
| @Test |
| public void testDescribeVirtualTables() throws Throwable |
| { |
| assertRowsNet(executeDescribeNet("DESCRIBE ONLY KEYSPACE system_virtual_schema;"), |
| row("system_virtual_schema", |
| "keyspace", |
| "system_virtual_schema", |
| "/*\n" + |
| "Warning: Keyspace system_virtual_schema is a virtual keyspace and cannot be recreated with CQL.\n" + |
| "Structure, for reference:\n" + |
| "VIRTUAL KEYSPACE system_virtual_schema;\n" + |
| "*/")); |
| |
| assertRowsNet(executeDescribeNet("DESCRIBE TABLE system_virtual_schema.columns;"), |
| row("system_virtual_schema", |
| "table", |
| "columns", |
| "/*\n" + |
| "Warning: Table system_virtual_schema.columns is a virtual table and cannot be recreated with CQL.\n" + |
| "Structure, for reference:\n" + |
| "VIRTUAL TABLE system_virtual_schema.columns (\n" + |
| " keyspace_name text,\n" + |
| " table_name text,\n" + |
| " column_name text,\n" + |
| " clustering_order text,\n" + |
| " column_name_bytes blob,\n" + |
| " kind text,\n" + |
| " position int,\n" + |
| " type text,\n" + |
| " PRIMARY KEY (keyspace_name, table_name, column_name)\n" + |
| ") WITH CLUSTERING ORDER BY (table_name ASC, column_name ASC)\n" + |
| " AND comment = 'virtual column definitions';\n" + |
| "*/")); |
| } |
| |
| @Test |
| public void testDescribe() throws Throwable |
| { |
| try |
| { |
| execute("CREATE KEYSPACE test WITH REPLICATION = {'class' : 'SimpleStrategy', 'replication_factor' : 1};"); |
| execute("CREATE TABLE test.users ( userid text PRIMARY KEY, firstname text, lastname text, age int);"); |
| execute("CREATE INDEX myindex ON test.users (age);"); |
| execute("CREATE TABLE test.\"Test\" (id int, col int, val text, PRIMARY KEY(id, col));"); |
| execute("CREATE INDEX ON test.\"Test\" (col);"); |
| execute("CREATE INDEX ON test.\"Test\" (val)"); |
| execute("CREATE TABLE test.users_mv (username varchar, password varchar, gender varchar, session_token varchar, " + |
| "state varchar, birth_year bigint, PRIMARY KEY (username));"); |
| execute("CREATE MATERIALIZED VIEW test.users_by_state AS SELECT * FROM test.users_mv " + |
| "WHERE STATE IS NOT NULL AND username IS NOT NULL PRIMARY KEY (state, username)"); |
| execute(allTypesTable()); |
| |
| // Test describe schema |
| |
| Object[][] testSchemaOutput = rows( |
| row(KEYSPACE, "keyspace", KEYSPACE, |
| "CREATE KEYSPACE " + KEYSPACE + |
| " WITH replication = {'class': 'SimpleStrategy', 'replication_factor': '1'}" + |
| " AND durable_writes = true;"), |
| row(KEYSPACE_PER_TEST, "keyspace", KEYSPACE_PER_TEST, |
| "CREATE KEYSPACE " + KEYSPACE_PER_TEST + |
| " WITH replication = {'class': 'SimpleStrategy', 'replication_factor': '1'}" + |
| " AND durable_writes = true;"), |
| row("test", "keyspace", "test", keyspaceOutput()), |
| row("test", "table", "has_all_types", allTypesTable()), |
| row("test", "table", "\"Test\"", testTableOutput()), |
| row("test", "index", "\"Test_col_idx\"", indexOutput("\"Test_col_idx\"", "\"Test\"", "col")), |
| row("test", "index", "\"Test_val_idx\"", indexOutput("\"Test_val_idx\"", "\"Test\"", "val")), |
| row("test", "table", "users", userTableOutput()), |
| row("test", "index", "myindex", indexOutput("myindex", "users", "age")), |
| row("test", "table", "users_mv", usersMvTableOutput()), |
| row("test", "materialized_view", "users_by_state", usersByStateMvOutput())); |
| |
| assertRowsNet(executeDescribeNet(KEYSPACE_PER_TEST, "DESCRIBE SCHEMA"), testSchemaOutput); |
| assertRowsNet(executeDescribeNet(KEYSPACE_PER_TEST, "DESC SCHEMA"), testSchemaOutput); |
| |
| // Test describe keyspaces/keyspace |
| |
| Object[][] testKeyspacesOutput = rows(row(KEYSPACE, "keyspace", KEYSPACE), |
| row(KEYSPACE_PER_TEST, "keyspace", KEYSPACE_PER_TEST), |
| row(SYSTEM_KEYSPACE_NAME, "keyspace", SYSTEM_KEYSPACE_NAME), |
| row(AUTH_KEYSPACE_NAME, "keyspace", AUTH_KEYSPACE_NAME), |
| row(DISTRIBUTED_KEYSPACE_NAME, "keyspace", DISTRIBUTED_KEYSPACE_NAME), |
| row(SCHEMA_KEYSPACE_NAME, "keyspace", SCHEMA_KEYSPACE_NAME), |
| row(TRACE_KEYSPACE_NAME, "keyspace", TRACE_KEYSPACE_NAME), |
| row(VIRTUAL_SCHEMA, "keyspace", VIRTUAL_SCHEMA), |
| row("test", "keyspace", "test")); |
| |
| for (String describeKeyword : new String[]{"DESCRIBE", "DESC"}) |
| { |
| assertRowsNet(executeDescribeNet(describeKeyword + " KEYSPACES"), testKeyspacesOutput); |
| assertRowsNet(executeDescribeNet("test", describeKeyword + " KEYSPACES"), testKeyspacesOutput); |
| |
| assertRowsNet(executeDescribeNet(describeKeyword + " ONLY KEYSPACE test"), |
| row("test", "keyspace", "test", keyspaceOutput())); |
| } |
| |
| Object[][] testKeyspaceOutput = rows(row("test", "keyspace", "test", keyspaceOutput()), |
| row("test", "table", "has_all_types", allTypesTable()), |
| row("test", "table", "\"Test\"", testTableOutput()), |
| row("test", "index", "\"Test_col_idx\"", indexOutput("\"Test_col_idx\"", "\"Test\"", "col")), |
| row("test", "index", "\"Test_val_idx\"", indexOutput("\"Test_val_idx\"", "\"Test\"", "val")), |
| row("test", "table", "users", userTableOutput()), |
| row("test", "index", "myindex", indexOutput("myindex", "users", "age")), |
| row("test", "table", "users_mv", usersMvTableOutput()), |
| row("test", "materialized_view", "users_by_state", usersByStateMvOutput())); |
| |
| for (String describeKeyword : new String[]{"DESCRIBE", "DESC"}) |
| { |
| assertRowsNet(executeDescribeNet(describeKeyword + " KEYSPACE test"), testKeyspaceOutput); |
| assertRowsNet(executeDescribeNet(describeKeyword + " test"), testKeyspaceOutput); |
| |
| describeError(describeKeyword + " test2", "'test2' not found in keyspaces"); |
| } |
| |
| // Test describe tables/table |
| for (String cmd : new String[]{"describe TABLES", "DESC tables"}) |
| assertRowsNet(executeDescribeNet("test", cmd), |
| row("test", "table", "has_all_types"), |
| row("test", "table", "\"Test\""), |
| row("test", "table", "users"), |
| row("test", "table", "users_mv")); |
| |
| testDescribeTable("test", "has_all_types", row("test", "table", "has_all_types", allTypesTable())); |
| |
| testDescribeTable("test", "\"Test\"", |
| row("test", "table", "\"Test\"", testTableOutput()), |
| row("test", "index", "\"Test_col_idx\"", indexOutput("\"Test_col_idx\"", "\"Test\"", "col")), |
| row("test", "index", "\"Test_val_idx\"", indexOutput("\"Test_val_idx\"", "\"Test\"", "val"))); |
| |
| testDescribeTable("test", "users", row("test", "table", "users", userTableOutput()), |
| row("test", "index", "myindex", indexOutput("myindex", "users", "age"))); |
| |
| describeError("test", "DESCRIBE users2", "'users2' not found in keyspace 'test'"); |
| describeError("DESCRIBE test.users2", "'users2' not found in keyspace 'test'"); |
| |
| // Test describe index |
| |
| testDescribeIndex("test", "myindex", row("test", "index", "myindex", indexOutput("myindex", "users", "age"))); |
| testDescribeIndex("test", "\"Test_col_idx\"", row("test", "index", "\"Test_col_idx\"", indexOutput("\"Test_col_idx\"", "\"Test\"", "col"))); |
| testDescribeIndex("test", "\"Test_val_idx\"", row("test", "index", "\"Test_val_idx\"", indexOutput("\"Test_val_idx\"", "\"Test\"", "val"))); |
| |
| describeError("DESCRIBE test.myindex2", "'myindex2' not found in keyspace 'test'"); |
| describeError("test", "DESCRIBE myindex2", "'myindex2' not found in keyspace 'test'"); |
| |
| // Test describe materialized view |
| |
| testDescribeMaterializedView("test", "users_by_state", row("test", "materialized_view", "users_by_state", usersByStateMvOutput())); |
| } |
| finally |
| { |
| execute("DROP KEYSPACE IF EXISTS test"); |
| } |
| } |
| |
| private void testDescribeTable(String keyspace, String table, Object[]... rows) throws Throwable |
| { |
| for (String describeKeyword : new String[]{"describe", "desc"}) |
| { |
| for (String cmd : new String[]{describeKeyword + " table " + keyspace + "." + table, |
| describeKeyword + " columnfamily " + keyspace + "." + table, |
| describeKeyword + " " + keyspace + "." + table}) |
| { |
| assertRowsNet(executeDescribeNet(cmd), rows); |
| } |
| |
| for (String cmd : new String[]{describeKeyword + " table " + table, |
| describeKeyword + " columnfamily " + table, |
| describeKeyword + " " + table}) |
| { |
| assertRowsNet(executeDescribeNet(keyspace, cmd), rows); |
| } |
| } |
| } |
| |
| private void testDescribeIndex(String keyspace, String index, Object[]... rows) throws Throwable |
| { |
| for (String describeKeyword : new String[]{"describe", "desc"}) |
| { |
| for (String cmd : new String[]{describeKeyword + " index " + keyspace + "." + index, |
| describeKeyword + " " + keyspace + "." + index}) |
| { |
| assertRowsNet(executeDescribeNet(cmd), rows); |
| } |
| |
| for (String cmd : new String[]{describeKeyword + " index " + index, |
| describeKeyword + " " + index}) |
| { |
| assertRowsNet(executeDescribeNet(keyspace, cmd), rows); |
| } |
| } |
| } |
| |
| private void testDescribeMaterializedView(String keyspace, String view, Object[]... rows) throws Throwable |
| { |
| for (String describeKeyword : new String[]{"describe", "desc"}) |
| { |
| for (String cmd : new String[]{describeKeyword + " materialized view " + keyspace + "." + view, |
| describeKeyword + " " + keyspace + "." + view}) |
| { |
| assertRowsNet(executeDescribeNet(cmd), rows); |
| } |
| |
| for (String cmd : new String[]{describeKeyword + " materialized view " + view, |
| describeKeyword + " " + view}) |
| { |
| assertRowsNet(executeDescribeNet(keyspace, cmd), rows); |
| } |
| } |
| } |
| |
| @Test |
| public void testDescribeCluster() throws Throwable |
| { |
| for (String describeKeyword : new String[]{"DESCRIBE", "DESC"}) |
| { |
| assertRowsNet(executeDescribeNet(describeKeyword + " CLUSTER"), |
| row("Test Cluster", |
| "ByteOrderedPartitioner", |
| DatabaseDescriptor.getEndpointSnitch().getClass().getName())); |
| |
| assertRowsNet(executeDescribeNet("system_virtual_schema", describeKeyword + " CLUSTER"), |
| row("Test Cluster", |
| "ByteOrderedPartitioner", |
| DatabaseDescriptor.getEndpointSnitch().getClass().getName())); |
| } |
| |
| TokenMetadata tokenMetadata = StorageService.instance.getTokenMetadata(); |
| Token token = tokenMetadata.sortedTokens().get(0); |
| InetAddressAndPort addressAndPort = tokenMetadata.getAllEndpoints().iterator().next(); |
| |
| assertRowsNet(executeDescribeNet(KEYSPACE_PER_TEST, "DESCRIBE CLUSTER"), |
| row("Test Cluster", |
| "ByteOrderedPartitioner", |
| DatabaseDescriptor.getEndpointSnitch().getClass().getName(), |
| ImmutableMap.of(token.toString(), ImmutableList.of(addressAndPort.toString())))); |
| } |
| |
| @Test |
| public void testDescribeTableWithInternals() throws Throwable |
| { |
| String table = createTable(KEYSPACE_PER_TEST, "CREATE TABLE %s (pk1 text, pk2 int, c int, s decimal static, v1 text, v2 int, v3 int, PRIMARY KEY ((pk1, pk2), c ))"); |
| |
| TableId id = Schema.instance.getTableMetadata(KEYSPACE_PER_TEST, table).id; |
| |
| String tableCreateStatement = "CREATE TABLE " + KEYSPACE_PER_TEST + "." + table + " (\n" + |
| " pk1 text,\n" + |
| " pk2 int,\n" + |
| " c int,\n" + |
| " s decimal static,\n" + |
| " v1 text,\n" + |
| " v2 int,\n" + |
| " v3 int,\n" + |
| " PRIMARY KEY ((pk1, pk2), c)\n" + |
| ") WITH ID = " + id + "\n" + |
| " AND CLUSTERING ORDER BY (c ASC)\n" + |
| " AND " + tableParametersCql(); |
| |
| assertRowsNet(executeDescribeNet("DESCRIBE TABLE " + KEYSPACE_PER_TEST + "." + table + " WITH INTERNALS"), |
| row(KEYSPACE_PER_TEST, |
| "table", |
| table, |
| tableCreateStatement)); |
| |
| String dropStatement = "ALTER TABLE " + KEYSPACE_PER_TEST + "." + table + " DROP v3 USING TIMESTAMP 1589286942065000;"; |
| |
| execute(dropStatement); |
| |
| assertRowsNet(executeDescribeNet("DESCRIBE TABLE " + KEYSPACE_PER_TEST + "." + table + " WITH INTERNALS"), |
| row(KEYSPACE_PER_TEST, |
| "table", |
| table, |
| tableCreateStatement + "\n" + |
| dropStatement)); |
| |
| String addStatement = "ALTER TABLE " + KEYSPACE_PER_TEST + "." + table + " ADD v3 int;"; |
| |
| execute(addStatement); |
| |
| assertRowsNet(executeDescribeNet("DESCRIBE TABLE " + KEYSPACE_PER_TEST + "." + table + " WITH INTERNALS"), |
| row(KEYSPACE_PER_TEST, |
| "table", |
| table, |
| tableCreateStatement + "\n" + |
| dropStatement + "\n" + |
| addStatement)); |
| } |
| |
| @Test |
| public void testDescribeTableAndMaterializedViewWithClustringOrder() throws Throwable |
| { |
| String table = createTable(KEYSPACE_PER_TEST, "CREATE TABLE IF NOT EXISTS %s (pk1 int, pk2 int, ck1 int, ck2 int, reg1 int, reg2 list<int>, reg3 int, PRIMARY KEY ((pk1, pk2), ck1, ck2)) WITH CLUSTERING ORDER BY (ck1 ASC, ck2 DESC);"); |
| |
| execute("CREATE MATERIALIZED VIEW IF NOT EXISTS " + KEYSPACE_PER_TEST + ".mv AS SELECT * FROM " + KEYSPACE_PER_TEST + "." + table |
| + " WHERE pk2 IS NOT NULL AND pk1 IS NOT NULL AND ck2 IS NOT NULL AND ck1 IS NOT NULL PRIMARY KEY ((pk2, pk1), ck2, ck1)"); |
| |
| String tableCreateStatement = "CREATE TABLE " + KEYSPACE_PER_TEST + "." + table + " (\n" + |
| " pk1 int,\n" + |
| " pk2 int,\n" + |
| " ck1 int,\n" + |
| " ck2 int,\n" + |
| " reg1 int,\n" + |
| " reg3 int,\n" + |
| " reg2 list<int>,\n" + |
| " PRIMARY KEY ((pk1, pk2), ck1, ck2)\n" + |
| ") WITH CLUSTERING ORDER BY (ck1 ASC, ck2 DESC)\n" + |
| " AND " + tableParametersCql(); |
| |
| String mvCreateStatement ="CREATE MATERIALIZED VIEW " + KEYSPACE_PER_TEST + ".mv AS\n" + |
| " SELECT *\n" + |
| " FROM " + KEYSPACE_PER_TEST + "." + table + "\n" + |
| " WHERE pk2 IS NOT NULL AND pk1 IS NOT NULL AND ck2 IS NOT NULL AND ck1 IS NOT NULL\n" + |
| " PRIMARY KEY ((pk2, pk1), ck2, ck1)\n" + |
| " WITH CLUSTERING ORDER BY (ck2 DESC, ck1 ASC)\n" + |
| " AND " + mvParametersCql(); |
| |
| try |
| { |
| |
| assertRowsNet(executeDescribeNet("DESCRIBE TABLE " + KEYSPACE_PER_TEST + "." + table), |
| row(KEYSPACE_PER_TEST, "table", table, tableCreateStatement)); |
| |
| assertRowsNet(executeDescribeNet("DESCRIBE MATERIALIZED VIEW " + KEYSPACE_PER_TEST + ".mv"), |
| row(KEYSPACE_PER_TEST, "materialized_view", "mv", mvCreateStatement)); |
| } |
| finally |
| { |
| execute("DROP MATERIALIZED VIEW " + KEYSPACE_PER_TEST + ".mv"); |
| } |
| } |
| |
| @Test |
| public void testPrimaryKeyPositionWithAndWithoutInternals() throws Throwable |
| { |
| String table = createTable(KEYSPACE_PER_TEST, "CREATE TABLE %s (pk text, v1 text, v2 int, v3 int, PRIMARY KEY (pk))"); |
| |
| TableId id = Schema.instance.getTableMetadata(KEYSPACE_PER_TEST, table).id; |
| |
| String tableCreateStatement = "CREATE TABLE " + KEYSPACE_PER_TEST + "." + table + " (\n" + |
| " pk text PRIMARY KEY,\n" + |
| " v1 text,\n" + |
| " v2 int,\n" + |
| " v3 int\n" + |
| ") WITH ID = " + id + "\n" + |
| " AND " + tableParametersCql(); |
| |
| assertRowsNet(executeDescribeNet("DESCRIBE TABLE " + KEYSPACE_PER_TEST + "." + table + " WITH INTERNALS"), |
| row(KEYSPACE_PER_TEST, |
| "table", |
| table, |
| tableCreateStatement)); |
| |
| String dropStatement = "ALTER TABLE " + KEYSPACE_PER_TEST + "." + table + " DROP v3 USING TIMESTAMP 1589286942065000;"; |
| |
| execute(dropStatement); |
| |
| assertRowsNet(executeDescribeNet("DESCRIBE TABLE " + KEYSPACE_PER_TEST + "." + table + " WITH INTERNALS"), |
| row(KEYSPACE_PER_TEST, |
| "table", |
| table, |
| tableCreateStatement + "\n" + |
| dropStatement)); |
| |
| String tableCreateStatementWithoutDroppedColumn = "CREATE TABLE " + KEYSPACE_PER_TEST + "." + table + " (\n" + |
| " pk text PRIMARY KEY,\n" + |
| " v1 text,\n" + |
| " v2 int\n" + |
| ") WITH " + tableParametersCql(); |
| |
| assertRowsNet(executeDescribeNet("DESCRIBE TABLE " + KEYSPACE_PER_TEST + "." + table), |
| row(KEYSPACE_PER_TEST, |
| "table", |
| table, |
| tableCreateStatementWithoutDroppedColumn)); |
| } |
| |
| |
| @Test |
| public void testDescribeMissingKeyspace() throws Throwable |
| { |
| describeError("DESCRIBE TABLE foop", |
| "No keyspace specified and no current keyspace"); |
| describeError("DESCRIBE MATERIALIZED VIEW foop", |
| "No keyspace specified and no current keyspace"); |
| describeError("DESCRIBE INDEX foop", |
| "No keyspace specified and no current keyspace"); |
| describeError("DESCRIBE TYPE foop", |
| "No keyspace specified and no current keyspace"); |
| describeError("DESCRIBE FUNCTION foop", |
| "No keyspace specified and no current keyspace"); |
| describeError("DESCRIBE AGGREGATE foop", |
| "No keyspace specified and no current keyspace"); |
| } |
| |
| @Test |
| public void testDescribeNotFound() throws Throwable |
| { |
| describeError(format("DESCRIBE AGGREGATE %s.%s", KEYSPACE_PER_TEST, "aggr_foo"), |
| format("User defined aggregate '%s' not found in '%s'", "aggr_foo", KEYSPACE_PER_TEST)); |
| |
| describeError(format("DESCRIBE FUNCTION %s.%s", KEYSPACE_PER_TEST, "func_foo"), |
| format("User defined function '%s' not found in '%s'", "func_foo", KEYSPACE_PER_TEST)); |
| |
| describeError(format("DESCRIBE %s.%s", KEYSPACE_PER_TEST, "func_foo"), |
| format("'%s' not found in keyspace '%s'", "func_foo", KEYSPACE_PER_TEST)); |
| |
| describeError(format("DESCRIBE %s", "foo"), |
| format("'%s' not found in keyspaces", "foo")); |
| } |
| |
| @Test |
| public void testDescribeTypes() throws Throwable |
| { |
| String type1 = createType(KEYSPACE_PER_TEST, "CREATE TYPE %s (a int)"); |
| String type2 = createType(KEYSPACE_PER_TEST, "CREATE TYPE %s (x text, y text)"); |
| String type3 = createType(KEYSPACE_PER_TEST, "CREATE TYPE %s (a text, b frozen<" + type2 + ">)"); |
| execute("ALTER TYPE " + KEYSPACE_PER_TEST + "." + type1 + " ADD b frozen<" + type3 + ">"); |
| |
| try |
| { |
| assertRowsNet(executeDescribeNet(KEYSPACE_PER_TEST, "DESCRIBE TYPES"), |
| row(KEYSPACE_PER_TEST, "type", type1), |
| row(KEYSPACE_PER_TEST, "type", type2), |
| row(KEYSPACE_PER_TEST, "type", type3)); |
| |
| assertRowsNet(executeDescribeNet(KEYSPACE_PER_TEST, "DESCRIBE TYPE " + type2), |
| row(KEYSPACE_PER_TEST, "type", type2, "CREATE TYPE " + KEYSPACE_PER_TEST + "." + type2 + " (\n" + |
| " x text,\n" + |
| " y text\n" + |
| ");")); |
| assertRowsNet(executeDescribeNet(KEYSPACE_PER_TEST, "DESCRIBE TYPE " + type1), |
| row(KEYSPACE_PER_TEST, "type", type1, "CREATE TYPE " + KEYSPACE_PER_TEST + "." + type1 + " (\n" + |
| " a int,\n" + |
| " b frozen<" + type3 + ">\n" + |
| ");")); |
| |
| assertRowsNet(executeDescribeNet(KEYSPACE_PER_TEST, "DESCRIBE KEYSPACE " + KEYSPACE_PER_TEST), |
| row(KEYSPACE_PER_TEST, "keyspace", KEYSPACE_PER_TEST, "CREATE KEYSPACE " + KEYSPACE_PER_TEST + |
| " WITH replication = {'class': 'SimpleStrategy', 'replication_factor': '1'}" + |
| " AND durable_writes = true;"), |
| row(KEYSPACE_PER_TEST, "type", type2, "CREATE TYPE " + KEYSPACE_PER_TEST + "." + type2 + " (\n" + |
| " x text,\n" + |
| " y text\n" + |
| ");"), |
| row(KEYSPACE_PER_TEST, "type", type3, "CREATE TYPE " + KEYSPACE_PER_TEST + "." + type3 + " (\n" + |
| " a text,\n" + |
| " b frozen<" + type2 + ">\n" + |
| ");"), |
| row(KEYSPACE_PER_TEST, "type", type1, "CREATE TYPE " + KEYSPACE_PER_TEST + "." + type1 + " (\n" + |
| " a int,\n" + |
| " b frozen<" + type3 + ">\n" + |
| ");")); |
| } |
| finally |
| { |
| execute("DROP TYPE " + KEYSPACE_PER_TEST + "." + type1); |
| execute("DROP TYPE " + KEYSPACE_PER_TEST + "." + type3); |
| execute("DROP TYPE " + KEYSPACE_PER_TEST + "." + type2); |
| } |
| } |
| |
| /** |
| * Tests for the error reported in CASSANDRA-9064 by: |
| * |
| * - creating the table described in the bug report, using LCS, |
| * - DESCRIBE-ing that table via cqlsh, then DROPping it, |
| * - running the output of the DESCRIBE statement as a CREATE TABLE statement, and |
| * - inserting a value into the table. |
| * |
| * The final two steps of the test should not fall down. If one does, that |
| * indicates the output of DESCRIBE is not a correct CREATE TABLE statement. |
| */ |
| @Test |
| public void testDescribeRoundtrip() throws Throwable |
| { |
| for (String withInternals : new String[]{"", " WITH INTERNALS"}) |
| { |
| String table = createTable(KEYSPACE_PER_TEST, "CREATE TABLE %s (key int PRIMARY KEY) WITH compaction = {'class': 'LeveledCompactionStrategy'}"); |
| |
| String output = executeDescribeNet(KEYSPACE_PER_TEST, "DESCRIBE TABLE " + table + withInternals).all().get(0).getString("create_statement"); |
| |
| executeDescribeNet(KEYSPACE_PER_TEST, "CREATE MATERIALIZED VIEW " + table + "_view AS SELECT key FROM " + table |
| + " WHERE key IS NOT NULL PRIMARY KEY(key)"); |
| |
| String mvCreateView = executeDescribeNet(KEYSPACE_PER_TEST, "DESCRIBE MATERIALIZED VIEW " + table + "_view").all().get(0).getString("create_statement"); |
| |
| executeDescribeNet(KEYSPACE_PER_TEST, "DROP MATERIALIZED VIEW " + table + "_view"); |
| execute("DROP TABLE " + KEYSPACE_PER_TEST + "." + table); |
| |
| String aggregationFunctionName = KEYSPACE_PER_TEST + ".\"token\""; |
| String aggregationName = KEYSPACE_PER_TEST + ".\"aggregate\""; |
| createFunction(KEYSPACE_PER_TEST, |
| "int, int", |
| "CREATE FUNCTION " + aggregationFunctionName + " (\"token\" int, add_to int) " + |
| "CALLED ON NULL INPUT " + |
| "RETURNS int " + |
| "LANGUAGE java " + |
| "AS 'return token + add_to;'"); |
| |
| createAggregate(KEYSPACE_PER_TEST, |
| "int", |
| format("CREATE AGGREGATE " + aggregationName + "(int) " + |
| "SFUNC %s " + |
| "STYPE int " + |
| "INITCOND 42", |
| shortFunctionName(aggregationFunctionName))); |
| |
| String functionCreate = executeDescribeNet(KEYSPACE_PER_TEST, "DESCRIBE FUNCTION " + aggregationFunctionName).all().get(0).getString("create_statement"); |
| String aggregateCreate = executeDescribeNet(KEYSPACE_PER_TEST, "DESCRIBE AGGREGATE " + aggregationName).all().get(0).getString("create_statement"); |
| |
| execute("DROP AGGREGATE " + aggregationName); |
| execute("DROP FUNCTION " + aggregationFunctionName); |
| |
| executeNet(output); |
| executeNet(mvCreateView); |
| executeNet(functionCreate); |
| executeNet(aggregateCreate); |
| |
| String output2 = executeDescribeNet(KEYSPACE_PER_TEST, "DESCRIBE TABLE " + table + withInternals).all().get(0).getString("create_statement"); |
| String mvCreateView2 = executeDescribeNet(KEYSPACE_PER_TEST, "DESCRIBE MATERIALIZED VIEW " + table + "_view").all().get(0).getString("create_statement"); |
| String functionCreate2 = executeDescribeNet(KEYSPACE_PER_TEST, "DESCRIBE FUNCTION " + aggregationFunctionName).all().get(0).getString("create_statement"); |
| String aggregateCreate2 = executeDescribeNet(KEYSPACE_PER_TEST, "DESCRIBE AGGREGATE " + aggregationName).all().get(0).getString("create_statement"); |
| |
| assertEquals(output, output2); |
| assertEquals(mvCreateView, mvCreateView2); |
| assertEquals(functionCreate, functionCreate2); |
| assertEquals(aggregateCreate, aggregateCreate2); |
| |
| execute("INSERT INTO " + KEYSPACE_PER_TEST + "." + table + " (key) VALUES (1)"); |
| executeDescribeNet(KEYSPACE_PER_TEST, "DROP MATERIALIZED VIEW " + table + "_view"); |
| executeDescribeNet(KEYSPACE_PER_TEST, "DROP AGGREGATE " + aggregationName); |
| executeDescribeNet(KEYSPACE_PER_TEST, "DROP FUNCTION " + aggregationFunctionName); |
| } |
| } |
| |
| @Test |
| public void testDescribeWithCustomIndex() throws Throwable |
| { |
| String table = createTable(KEYSPACE_PER_TEST, "CREATE TABLE %s (id int PRIMARY KEY, value text);"); |
| String indexWithoutOptions = createIndex(KEYSPACE_PER_TEST, "CREATE CUSTOM INDEX ON %s(value) USING 'org.apache.cassandra.index.sasi.SASIIndex';"); |
| String indexWithOptions = createIndex(KEYSPACE_PER_TEST, "CREATE CUSTOM INDEX ON %s(value) USING 'org.apache.cassandra.index.sasi.SASIIndex' WITH OPTIONS = {'is_literal': 'false'};"); |
| |
| String expectedKeyspaceStmt = "CREATE KEYSPACE " + KEYSPACE_PER_TEST + |
| " WITH replication = {'class': 'SimpleStrategy', 'replication_factor': '1'}" + |
| " AND durable_writes = true;"; |
| |
| String expectedTableStmt = "CREATE TABLE " + KEYSPACE_PER_TEST + "." + table + " (\n" + |
| " id int PRIMARY KEY,\n" + |
| " value text\n" + |
| ") WITH " + tableParametersCql(); |
| |
| String expectedIndexStmtWithoutOptions = "CREATE CUSTOM INDEX " + indexWithoutOptions + " ON " + KEYSPACE_PER_TEST + "." + table + " (value) USING 'org.apache.cassandra.index.sasi.SASIIndex';"; |
| String expectedIndexStmtWithOptions = "CREATE CUSTOM INDEX " + indexWithOptions + " ON " + KEYSPACE_PER_TEST + "." + table + " (value) USING 'org.apache.cassandra.index.sasi.SASIIndex' WITH OPTIONS = {'is_literal': 'false'};"; |
| |
| assertRowsNet(executeDescribeNet("DESCRIBE KEYSPACE " + KEYSPACE_PER_TEST), |
| row(KEYSPACE_PER_TEST, "keyspace", KEYSPACE_PER_TEST, expectedKeyspaceStmt), |
| row(KEYSPACE_PER_TEST, "table", table, expectedTableStmt), |
| row(KEYSPACE_PER_TEST, "index", indexWithoutOptions, expectedIndexStmtWithoutOptions), |
| row(KEYSPACE_PER_TEST, "index", indexWithOptions, expectedIndexStmtWithOptions)); |
| |
| assertRowsNet(executeDescribeNet("DESCRIBE INDEX " + KEYSPACE_PER_TEST + "." + indexWithoutOptions), |
| row(KEYSPACE_PER_TEST, "index", indexWithoutOptions, expectedIndexStmtWithoutOptions)); |
| |
| assertRowsNet(executeDescribeNet("DESCRIBE INDEX " + KEYSPACE_PER_TEST + "." + indexWithOptions), |
| row(KEYSPACE_PER_TEST, "index", indexWithOptions, expectedIndexStmtWithOptions)); |
| } |
| |
| @Test |
| public void testUsingReservedInCreateType() throws Throwable |
| { |
| String type = createType(KEYSPACE_PER_TEST, "CREATE TYPE %s (\"token\" text, \"desc\" text);"); |
| assertRowsNet(executeDescribeNet(KEYSPACE_PER_TEST, "DESCRIBE TYPE " + type), |
| row(KEYSPACE_PER_TEST, "type", type, "CREATE TYPE " + KEYSPACE_PER_TEST + "." + type + " (\n" + |
| " \"token\" text,\n" + |
| " \"desc\" text\n" + |
| ");")); |
| } |
| |
| @Test |
| public void testDescMaterializedViewShouldNotOmitQuotations() throws Throwable |
| { |
| try{ |
| execute("CREATE KEYSPACE testWithKeywords WITH REPLICATION = {'class' : 'SimpleStrategy', 'replication_factor' : 1};"); |
| execute("CREATE TABLE testWithKeywords.users_mv (username varchar, password varchar, gender varchar, session_token varchar, " + |
| "state varchar, birth_year bigint, \"token\" text, PRIMARY KEY (\"token\"));"); |
| execute("CREATE MATERIALIZED VIEW testWithKeywords.users_by_state AS SELECT * FROM testWithKeywords.users_mv " + |
| "WHERE STATE IS NOT NULL AND \"token\" IS NOT NULL PRIMARY KEY (state, \"token\")"); |
| |
| final String expectedOutput = "CREATE MATERIALIZED VIEW testwithkeywords.users_by_state AS\n" + |
| " SELECT *\n" + |
| " FROM testwithkeywords.users_mv\n" + |
| " WHERE state IS NOT NULL AND \"token\" IS NOT NULL\n" + |
| " PRIMARY KEY (state, \"token\")\n" + |
| " WITH CLUSTERING ORDER BY (\"token\" ASC)\n" + |
| " AND " + mvParametersCql(); |
| |
| testDescribeMaterializedView("testWithKeywords", "users_by_state", row("testwithkeywords", "materialized_view", "users_by_state", expectedOutput)); |
| } |
| finally |
| { |
| execute("DROP KEYSPACE IF EXISTS testWithKeywords"); |
| } |
| } |
| |
| @Test |
| public void testDescFunctionAndAggregateShouldNotOmitQuotations() throws Throwable |
| { |
| |
| final String functionName = KEYSPACE_PER_TEST + ".\"token\""; |
| |
| createFunctionOverload(functionName, |
| "int, ascii", |
| "CREATE FUNCTION " + functionName + " (\"token\" int, other_in ascii) " + |
| "RETURNS NULL ON NULL INPUT " + |
| "RETURNS text " + |
| "LANGUAGE java " + |
| "AS 'return \"Hello World\";'"); |
| |
| for (String describeKeyword : new String[]{"DESCRIBE", "DESC"}) |
| { |
| |
| assertRowsNet(executeDescribeNet(describeKeyword + " FUNCTION " + functionName), |
| row(KEYSPACE_PER_TEST, |
| "function", |
| shortFunctionName(functionName) + "(int, ascii)", |
| "CREATE FUNCTION " + functionName + "(\"token\" int, other_in ascii)\n" + |
| " RETURNS NULL ON NULL INPUT\n" + |
| " RETURNS text\n" + |
| " LANGUAGE java\n" + |
| " AS $$return \"Hello World\";$$;")); |
| } |
| |
| final String aggregationFunctionName = KEYSPACE_PER_TEST + ".\"token\""; |
| final String aggregationName = KEYSPACE_PER_TEST + ".\"token\""; |
| createFunctionOverload(aggregationName, |
| "int, int", |
| "CREATE FUNCTION " + aggregationFunctionName + " (\"token\" int, add_to int) " + |
| "CALLED ON NULL INPUT " + |
| "RETURNS int " + |
| "LANGUAGE java " + |
| "AS 'return token + add_to;'"); |
| |
| |
| String aggregate = createAggregate(KEYSPACE_PER_TEST, |
| "int", |
| format("CREATE AGGREGATE %%s(int) " + |
| "SFUNC %s " + |
| "STYPE int " + |
| "INITCOND 42", |
| shortFunctionName(aggregationFunctionName))); |
| |
| |
| for (String describeKeyword : new String[]{"DESCRIBE", "DESC"}) |
| { |
| assertRowsNet(executeDescribeNet(describeKeyword + " AGGREGATE " + aggregate), |
| row(KEYSPACE_PER_TEST, |
| "aggregate", |
| shortFunctionName(aggregate) + "(int)", |
| "CREATE AGGREGATE " + aggregate + "(int)\n" + |
| " SFUNC " + shortFunctionName(aggregationName) + "\n" + |
| " STYPE int\n" + |
| " INITCOND 42;")); |
| } |
| } |
| |
| private static String allTypesTable() |
| { |
| return "CREATE TABLE test.has_all_types (\n" + |
| " num int PRIMARY KEY,\n" + |
| " asciicol ascii,\n" + |
| " bigintcol bigint,\n" + |
| " blobcol blob,\n" + |
| " booleancol boolean,\n" + |
| " decimalcol decimal,\n" + |
| " doublecol double,\n" + |
| " durationcol duration,\n" + |
| " floatcol float,\n" + |
| " frozenlistcol frozen<list<text>>,\n" + |
| " frozenmapcol frozen<map<timestamp, timeuuid>>,\n" + |
| " frozensetcol frozen<set<bigint>>,\n" + |
| " intcol int,\n" + |
| " smallintcol smallint,\n" + |
| " textcol text,\n" + |
| " timestampcol timestamp,\n" + |
| " tinyintcol tinyint,\n" + |
| " tuplecol frozen<tuple<text, int, frozen<tuple<timestamp>>>>,\n" + |
| " uuidcol uuid,\n" + |
| " varcharcol text,\n" + |
| " varintcol varint,\n" + |
| " listcol list<decimal>,\n" + |
| " mapcol map<timestamp, timeuuid>,\n" + |
| " setcol set<tinyint>\n" + |
| ") WITH " + tableParametersCql(); |
| } |
| |
| private static String usersByStateMvOutput() |
| { |
| return "CREATE MATERIALIZED VIEW test.users_by_state AS\n" + |
| " SELECT *\n" + |
| " FROM test.users_mv\n" + |
| " WHERE state IS NOT NULL AND username IS NOT NULL\n" + |
| " PRIMARY KEY (state, username)\n" + |
| " WITH CLUSTERING ORDER BY (username ASC)\n" + |
| " AND " + mvParametersCql(); |
| } |
| |
| private static String indexOutput(String index, String table, String col) |
| { |
| return format("CREATE INDEX %s ON %s.%s (%s);", index, "test", table, col); |
| } |
| |
| private static String usersMvTableOutput() |
| { |
| return "CREATE TABLE test.users_mv (\n" + |
| " username text PRIMARY KEY,\n" + |
| " birth_year bigint,\n" + |
| " gender text,\n" + |
| " password text,\n" + |
| " session_token text,\n" + |
| " state text\n" + |
| ") WITH " + tableParametersCql(); |
| } |
| |
| private static String userTableOutput() |
| { |
| return "CREATE TABLE test.users (\n" + |
| " userid text PRIMARY KEY,\n" + |
| " age int,\n" + |
| " firstname text,\n" + |
| " lastname text\n" + |
| ") WITH " + tableParametersCql(); |
| } |
| |
| private static String testTableOutput() |
| { |
| return "CREATE TABLE test.\"Test\" (\n" + |
| " id int,\n" + |
| " col int,\n" + |
| " val text,\n" + |
| " PRIMARY KEY (id, col)\n" + |
| ") WITH CLUSTERING ORDER BY (col ASC)\n" + |
| " AND " + tableParametersCql(); |
| } |
| |
| private static String tableParametersCql() |
| { |
| return "additional_write_policy = '99p'\n" + |
| " AND bloom_filter_fp_chance = 0.01\n" + |
| " AND caching = {'keys': 'ALL', 'rows_per_partition': 'NONE'}\n" + |
| " AND cdc = false\n" + |
| " AND comment = ''\n" + |
| " AND compaction = {'class': 'org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy', 'max_threshold': '32', 'min_threshold': '4'}\n" + |
| " AND compression = {'chunk_length_in_kb': '16', 'class': 'org.apache.cassandra.io.compress.LZ4Compressor'}\n" + |
| " AND memtable = 'default'\n" + |
| " AND crc_check_chance = 1.0\n" + |
| " AND default_time_to_live = 0\n" + |
| " AND extensions = {}\n" + |
| " AND gc_grace_seconds = 864000\n" + |
| " AND max_index_interval = 2048\n" + |
| " AND memtable_flush_period_in_ms = 0\n" + |
| " AND min_index_interval = 128\n" + |
| " AND read_repair = 'BLOCKING'\n" + |
| " AND speculative_retry = '99p';"; |
| } |
| |
| private static String mvParametersCql() |
| { |
| return "additional_write_policy = '99p'\n" + |
| " AND bloom_filter_fp_chance = 0.01\n" + |
| " AND caching = {'keys': 'ALL', 'rows_per_partition': 'NONE'}\n" + |
| " AND cdc = false\n" + |
| " AND comment = ''\n" + |
| " AND compaction = {'class': 'org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy', 'max_threshold': '32', 'min_threshold': '4'}\n" + |
| " AND compression = {'chunk_length_in_kb': '16', 'class': 'org.apache.cassandra.io.compress.LZ4Compressor'}\n" + |
| " AND memtable = 'default'\n" + |
| " AND crc_check_chance = 1.0\n" + |
| " AND extensions = {}\n" + |
| " AND gc_grace_seconds = 864000\n" + |
| " AND max_index_interval = 2048\n" + |
| " AND memtable_flush_period_in_ms = 0\n" + |
| " AND min_index_interval = 128\n" + |
| " AND read_repair = 'BLOCKING'\n" + |
| " AND speculative_retry = '99p';"; |
| } |
| |
| private static String keyspaceOutput() |
| { |
| return "CREATE KEYSPACE test WITH replication = {'class': 'SimpleStrategy', 'replication_factor': '1'} AND durable_writes = true;"; |
| } |
| |
| private void describeError(String cql, String msg) throws Throwable |
| { |
| describeError(null, cql, msg); |
| } |
| |
| private void describeError(String useKs, String cql, String msg) throws Throwable |
| { |
| assertInvalidThrowMessage(Optional.of(getProtocolVersion(useKs)), msg, InvalidQueryException.class, cql, ArrayUtils.EMPTY_OBJECT_ARRAY); |
| } |
| |
| private ResultSet executeDescribeNet(String cql) throws Throwable |
| { |
| return executeDescribeNet(null, cql); |
| } |
| |
| private ResultSet executeDescribeNet(String useKs, String cql) throws Throwable |
| { |
| return executeNetWithPaging(getProtocolVersion(useKs), cql, useKs, 3); |
| } |
| |
| private ProtocolVersion getProtocolVersion(String useKs) throws Throwable |
| { |
| // We're using a trick here to distinguish driver sessions with a "USE keyspace" and without: |
| // As different ProtocolVersions use different driver instances, we use different ProtocolVersions |
| // for the with and without "USE keyspace" cases. |
| |
| ProtocolVersion v = useKs != null ? ProtocolVersion.CURRENT : ProtocolVersion.V6; |
| |
| if (useKs != null) |
| executeNet(v, "USE " + useKs); |
| return v; |
| } |
| |
| private static Object[][] rows(Object[]... rows) |
| { |
| return rows; |
| } |
| } |