Pinot provides a native Java client to execute queries on the cluster. The client is tenant-aware, and able to direct queries to the correct broker.
Prerequisite
You can use the client by installing and including Maven
or Gradle
.
For information on how to install Maven, visit Installing Apache Maven.
Example of how to including the Maven dependency to use the client:
<dependency>
<groupId>org.apache.pinot</groupId>
<artifactId>pinot-java-client</artifactId>
<version>1.0.0</version>
</dependency>
For information on how to install Gradle, visit Gradle Build Tool Installation.
Example of how to including the Gradle dependency to use the client:
include 'org.apache.pinot:pinot-java-client:0.5.0'
Usage
Here’s an example of how to use the pinot-java-client
to query Pinot.
import org.apache.pinot.client.Connection;
import org.apache.pinot.client.ConnectionFactory;
import org.apache.pinot.client.Request;
import org.apache.pinot.client.ResultSetGroup;
import org.apache.pinot.client.ResultSet;
/**
* Demonstrates the use of the pinot-client to query Pinot from Java
*/
public class PinotClientExample {
public static void main(String[] args) {
// pinot connection
String brokerURL = "https://pinot.<random-string>.cp.s7e.startree.cloud"; // this URL should be available with you
String pinotClusterName = "PinotCluster";
JsonAsyncHttpPinotClientTransportFactory factory = new JsonAsyncHttpPinotClientTransportFactory();
Connection pinotConnection = ConnectionFactory.fromHostList(Collections.singletonList(brokerURL), factory.buildTransport());
String query = "SELECT COUNT(*) FROM myTable GROUP BY foo";
// set queryType=sql for querying the sql endpoint
Request pinotClientRequest = new Request("sql", query);
ResultSetGroup pinotResultSetGroup = pinotConnection.execute(pinotClientRequest);
ResultSet resultTableResultSet = pinotResultSetGroup.getResultSet(0);
int numRows = resultTableResultSet.getRowCount();
int numColumns = resultTableResultSet.getColumnCount();
String columnValue = resultTableResultSet.getString(0, 1);
String columnName = resultTableResultSet.getColumnName(1);
System.out.println("ColumnName: " + columnName + ", ColumnValue: " + columnValue);
}
}
Connection Factory
The client provides a ConnectionFactory
class to create connections to a Pinot cluster. To create a connection, include a comma-separated list of the brokers in the cluster. For example, ("broker-1:1234", "broker-2:1234", ...);
Connection connection = ConnectionFactory.fromZookeeper
("some-zookeeper-server:2191/zookeeperPath");
Connection connection = ConnectionFactory.fromProperties("demo.properties");
Connection connection = ConnectionFactory.fromHostList(Collections.singletonList("https://pinot.<random-string>.cp.s7e.startree.cloud"), factory.buildTransport());
Query methods
Query using one of the following methods:
- For blocking queries, use the following request format:
Connection.execute(org.apache.pinot.client.Request)
- For asynchronous queries that return a future object, use the following request format:
Connection.executeAsync(org.apache.pinot.client.Request)
ResultSetGroup resultSetGroup =
connection.execute(new Request("sql", "select * from foo..."));
// OR
Future<ResultSetGroup> futureResultSetGroup =
connection.executeAsync(new Request("sql", "select * from foo..."));
To escape query parameters, you can use the PreparedStatement
(which isn’t stored, so won’t decrease the subsequent query performance).
PreparedStatement statement =
connection.prepareStatement(new Request("sql", "select * from foo where a = ?"));
statement.setString(1, "bar");
ResultSetGroup resultSetGroup = statement.execute();
// OR
Future<ResultSetGroup> futureResultSetGroup = statement.executeAsync();
Result set
Access results using various get
methods on the first ResultSet
with the getResultSet(int)
method.
Request request = new Request("sql", "select foo, bar from baz where quux = 'quuux'");
ResultSetGroup resultSetGroup = connection.execute(request);
ResultSet resultSet = resultSetGroup.getResultSet(0);
for (int i = 0; i < resultSet.getRowCount(); ++i) {
System.out.println("foo: " + resultSet.getString(i, 0));
System.out.println("bar: " + resultSet.getInt(i, 1));
}
Authentication
Pinot supports basic HTTP authorization, which can be enabled for your
cluster using configuration. To support basic HTTP authorization in your client-side Java applications, make sure you are using
Pinot Java Client 0.10.0+ or building from the latest Pinot snapshot.
The following code snippet shows you how to connect to and query a Pinot cluster that has basic HTTP authorization enabled when using the Java client.
final String username = "admin";
final String password = "verysecret";
// Concatenate username and password and use base64 to encode the concatenated string
String plainCredentials = username + ":" + password;
String base64Credentials = new String(
Base64.getEncoder().encode(plainCredentials.getBytes()));
String authorizationHeader = "Basic " + base64Credentials;
Map<String, String> headers = new HashMap();
headers.put("Authorization", authorizationHeader);
JsonAsyncHttpPinotClientTransportFactory factory =
new JsonAsyncHttpPinotClientTransportFactory();
factory.setHeaders(headers);
PinotClientTransport clientTransport = factory
.buildTransport();
Connection connection = ConnectionFactory.fromProperties(
Collections.singletonList("localhost:8000"), clientTransport);
String query = "select count(*) FROM baseballStats limit 1";
ResultSetGroup rs = connection.execute(query);
System.out.println(rs);
connection.close();
Configuring client time-out
The following timeouts can be set:
- brokerConnectTimeoutMs (default 2000)
- brokerReadTimeoutMs (default 60000)
- brokerHandshakeTimeoutMs (default 2000)
- controllerConnectTimeoutMs (default 2000)
- controllerReadTimeoutMs (default 60000)
- controllerHandshakeTimeoutMs (default 2000)
Timeouts for the Java connector can be added as a connection properties. The following example configures a very low timeout of 10ms:
Properties connectionProperties = new Properties();
connectionProperties.setProperty("controllerReadTimeoutMs", "10");
connectionProperties.setProperty("controllerHandshakeTimeoutMs", "10");
connectionProperties.setProperty("controllerConnectTimeoutMs", "10");
connectionProperties.setProperty("brokerReadTimeoutMs", "10");
connectionProperties.setProperty("brokerHandshakeTimeoutMs", "10");
connectionProperties.setProperty("brokerConnectTimeoutMs", "10");
// Register new Pinot JDBC driver
DriverManager.registerDriver(new PinotDriver());
// Get a client connection and set the connection timeouts
Connection connection = DriverManager.getConnection(DB_URL, connectionProperties);
// Test that your query successfully times out
Statement statement = connection.createStatement();
ResultSet rs = statement.executeQuery("SELECT count(*) FROM baseballStats LIMIT 1;");
while (rs.next()) {
String result = rs.getString("count(*)");
System.out.println(result);
}
Obtaining Username and Password
You can cenerate an API token in the Data Portal or using the REST API. Then, obtain the username and password from the service token
Th username and password are used to authorize your API requests.
Finding Your Broker URL
To find the correct Broker URL for your table in StarTree Cloud:
- Access the Data Portal.
- Click on Tables.
- Select the specific table you want to query.
- From the browser address bar, copy the URL to your Pinot cluster. For example, if the URL shown is
https://dp.1abcde6.cp.s7e.startree.cloud/tables
, then the Broker URL for the table will be broker.pinot.1abcde6.cp.s7e.startree.cloud
.