How do I retrieve table names in Cassandra using Java? - cassandra

If is use this code in a CQL shell , I get all the names of table(s) in that keyspace.
DESCRIBE TABLES;
I want to retrieve the same data using ResulSet . Below is my code in Java.
String query = "DESCRIBE TABLES;";
ResultSet rs = session.execute(query);
for(Row row : rs) {
System.out.println(row);
}
While session and cluster has been initialized earlier as:
Cluster cluster = Cluster.builder().addContactPoint("127.0.0.1").build();
Session session = cluster.connect("keyspace_name");
Or I like to know Java code to retrieve table names in a keyspace.

The schema for the system tables change between versions quite a bit. It is best to rely on drivers Metadata that will have version specific parsing built in. From the Java Driver use
Cluster cluster = Cluster.builder().addContactPoint("127.0.0.1").build();
Collection<TableMetadata> tables = cluster.getMetadata()
.getKeyspace("keyspace_name")
.getTables(); // TableMetadata has name in getName(), along with lots of other info
// to convert to list of the names
List<String> tableNames = tables.stream()
.map(tm -> tm.getName())
.collect(Collectors.toList());

Cluster cluster = Cluster.builder().addContactPoint("127.0.0.1").build();
Metadata metadata = cluster.getMetadata();
Iterator<TableMetadata> tm = metadata.getKeyspace("Your Keyspace").getTables().iterator();
while(tm.hasNext()){
TableMetadata t = tm.next();
System.out.println(t.getName());
}
The above code will give you table names in the passed keyspace irrespective of the cassandra version used.

Related

Cassandra Java driver query ResultSet not stored in variable

//Read data from Cassandra
String query = "SELECT * FROM LABA_2.DATA LIMIT 5;";
//Creating Cluster object
Cluster cluster = Cluster.builder().addContactPoint("127.0.0.1").build();
//Creating Session object
Session session = cluster.connect();
//Getting the ResultSet
ResultSet result = session.execute(query);
System.out.println(result.all().size());
System.out.println("AJFGJKABGSDKGJS");
System.out.println(result.all().size());
System.out.println("AJFGJKABGSDKGJS");
Output:
22/04/02 23:11:56 INFO Cluster: New Cassandra host /127.0.0.1:9042 added
5
AJFGJKABGSDKGJS
0
AJFGJKABGSDKGJS
In the first case size = 5, in the second = 0.
cassandra-driver - 3.11.0
Why results are different?
Your test is invalid. Calling ResultSet.all() forces the driver to retrieve the whole result set in one go. The important thing to note here is that after calling all(), there is nothing left to retrieve.
When you call all() a second time, it returns nothing because you have already retrieved everything -- the list is exhausted and there's nothing left. Cheers!

Can't retrieve the comment for columns but not table when using SchemaCrawler

I am using SchemaCrawler to get the metadata for MySQL5.7 tables using the following code:
final Connection connection = ...;
final DatabaseSpecificOverrideOptions databaseSpecificOverrideOptions =
SchemaCrawlerUtility.matchDatabaseSpecificOverrideOptions(connection);
final SchemaCrawler schemaCrawler = new SchemaCrawler(connection, databaseSpecificOverrideOptions);
final SchemaCrawlerOptions options = new SchemaCrawlerOptions();
options.setSchemaInfoLevel(SchemaInfoLevelBuilder.maximum());
options.setTableInclusionRule(new IncludeAll());
options.setColumnInclusionRule(new IncludeAll());
final Catalog catalog = schemaCrawler.crawl(options);
final Collection<Table> tables = catalog.getTables();
for (Table t : tables) {
logger.info("Table comment: {}", t.getRemarks());
}
This is the test table:
create table testtable (
id bigint comment 'key level comment',
name varchar(32) comment 'column level comment'
) comment='table level comment';
I can get the column-level comments, but I never can get the table-level comment.
Is there anything that I mis-configured ?
Thanks!
This is an annoyance with the MySQL JDBC driver. You need to set useInformationSchema=true in your JDBC connection URL when creating a connection. For more information, please take a look at the StackOverflow question, Retrieve mysql table comment using DatabaseMetaData.
Sualeh Fatehi, SchemaCrawler

Example about how to use map cql type with DataStax java driver

I am trying to use the datastax java driver to update and query a column family that has a map field. Does anyone an example about how to use cql collections with the Datastax Java Driver?
Thanks
I will add some examples of using the CQL collections with both simple and prepared statements to the current Java driver doc.
You can use CQL collections with prepared statements. There's an example in the Java driver doc in the quick start section.
http://docs.datastax.com/en/developer/java-driver/2.0/java-driver/quick_start/qsSimpleClientBoundStatements_t.html
Step 4 binds a Java HashSet object to a CQL set column in the songs table.
Normally I'd ask what you've tried, but I know that this isn't in the DataStax documentation for the Java Driver. I'll go through what worked for me.
A couple of things to note:
The DataStax Cassandra Java class directed me to put my variables directly into the CQL text string (instead of binding the map). I'm guessing that binding collections wasn't working at the time of production (for the class videos).
Collections can't be queried using DevCenter, so you'll need to check their values via the command line with cqlsh if you want to see what they are outside your app.
To update an existing row (in the "users" table which has a Map<varchar,varchar> phone_numbers), try something like this:
String cqlQuery = "UPDATE users SET phone_numbers = phone_numbers + ";
cqlQuery += "{'" + phoneType + "':'" + phoneNumber+ "'} ";
cqlQuery += "WHERE username = ?";
PreparedStatement preparedStatement = getSession().prepare(cqlQuery);
BoundStatement boundStatement = preparedStatement.bind(user);
getSession().execute(boundStatement);
The better way to do this (assuming a Map<String,String> phoneNumbers), is to bind the collection to the prepared statement, like this:
String cqlQuery = "UPDATE users SET phone_numbers = ? ";
cqlQuery += "WHERE username = ?";
PreparedStatement preparedStatement = getSession().prepare(cqlQuery);
BoundStatement boundStatement = preparedStatement.bind(phoneNumbers,user);
getSession().execute(boundStatement);
Likewise, to read it back out:
String cqlQuery2 = "SELECT phone_numbers FROM users WHERE username = ?";
PreparedStatement preparedStatement2 = getSession().prepare(cqlQuery2);
BoundStatement boundStatement2 = preparedStatement2.bind(user);
ResultSet result2 = getSession().execute(boundStatement2);
Map<String,String> newMap = result2.one().getMap("phone_numbers", String.class, String.class);
They just covered this today in the (free) CAS101J class on DataStax Academy.
Here is how I did it; This has mapping for a tuple column in Cassandra as well as the map column in Cassandra. I was using Scala with the DataStax Cassandra Java Driver
Needed imports
import java.lang
import java.text.SimpleDateFormat
import com.datastax.driver.core._
import com.datastax.driver.core.querybuilder.QueryBuilder
import scala.collection.Map
import org.apache.spark.SparkContext
import org.apache.spark.SparkConf
import com.datastax.spark.connector.cql.CassandraConnector
import org.apache.spark.rdd.RDD
import scala.collection.JavaConversions._
Code snippet
val simpleDateFormat: SimpleDateFormat = new SimpleDateFormat("dd-MM-yyyy H:mm:ss")
val start_date: java.util.Date = simpleDateFormat.parse(val("StartTime").replaceAll(":(\\s+)", ":"))
val b_tuple= session.getCluster().getMetadata().newTupleType(DataType.cint(), DataType.cint(), DataType.text())
val time_tuple = session.getCluster().getMetadata().newTupleType(DataType.timestamp(), DataType.timestamp())
val time_tuple_value = time_tuple.newValue(start_date, end_date)
val b_tuple_value = bin_cell_tuple.newValue(b._1: lang.Integer, b._2: lang.Integer, val("xxx"))
val statement_2: Statement = QueryBuilder.insertInto("keyspace", "table_name")
.value("b_key", bin_cell_tuple_value)
.value("time_key", time_tuple_value)
.value("some_map", mapAsJavaMap(my_scala_map))
session.executeAsync(statement_2)

Get Cassandra partitioner [duplicate]

I'm developing a mechanism for Cassandra using Hector.
What I need at this moment is to know which are the hash values of the keys to look at which node is stored (looking at the tokens of each one), and ask directly this node for the value. What I understood is that depending on the partitioner Cassandra uses, the values are stored independently from one partitioner to other. So, are the hash values of all keys stored in any table? In case not, how could I implement a generic class that once I read from System Keyspace the partitioner that is using Cassandra this class could be an instance of it without the necessity of modifying the code depending on the partitioner? I would need it to call the getToken method to calculate the hash value for a given key.
Hector's CqlQuery is poorly supported and buggy. You should use the native Java CQL driver instead: https://github.com/datastax/java-driver
You could just reuse the partitioners defined in Cassandra: https://github.com/apache/cassandra/tree/trunk/src/java/org/apache/cassandra/dht and then using the token ranges you could do the routing.
The CQL driver offers token-aware routing out of the box. I would use that instead of trying to reinvent the wheel in Hector, especially since Hector uses the legacy Thrift API instead of CQL.
Finally after testing different implementations I found the way to get the partitioner using the next code:
CqlQuery<String, String, String> cqlQuery = new CqlQuery<String, String, String>(
ksp, StringSerializer.get(), StringSerializer.get(), StringSerializer.get());
cqlQuery.setQuery("select partitioner from local");
QueryResult<CqlRows<String, String, String>> result = cqlQuery.execute();
CqlRows rows = result.get();
for (int i = 0; i < rows.getCount(); i++) {
RowImpl<String, String, String> row = (RowImpl<String, String, String>) rows
.getList().get(i);
List<HColumn<String, String>> column = row.getColumnSlice().getColumns();
for (HColumn<String , String> c: column) {
System.out.println(c.getValue());
}
}

How to read schema of a keyspace using java.?

I want to read schema of a keyspace in cassandra.
I know that, in Cassandra-cli we can execute following command to get Schema
show schema keyspace1;
But i want to read schema from remote machine using java.
How i can solve this? Plzzz help me....
This one i solved by using thrift client
KsDef keyspaceDefinition = _client.describe_keyspace(_keyspace);
List<CfDef> columnDefinition = keyspaceDefinition.getCf_defs();
Here key space definition contains whole schema details, so from that KsDef we can read whatever we want. In my case i want to read metadata so i am reading column metadata from the above column definitions as shown below.
for(int i=0;i<columnDefinition.size();i++){
List<ColumnDef> columnMetadata = columnDefinition.get(i).getColumn_metadata();
for(int j=0;j<columnMetadata.size();j++){
columnfamilyNames.add(columnDefinition.get(i).getName());
columnNames.add(new String((columnMetadata.get(j).getName())));
validationClasses.add(columnMetadata.get(j).getValidation_class());
//ar.add(coldef.get(i).getName()+"\t"+bb_to_str(colmeta.get(j).getName())+"\t"+colmeta.get(j).getValidationClass());
}
}
here columnfamilyNames, columnNames and validationClasses are arraylists.

Resources