Skip to content

Commit

Permalink
Modifications to support JDBC connections
Browse files Browse the repository at this point in the history
  • Loading branch information
geoffxy committed Jan 31, 2025
1 parent 3b50202 commit d7606e2
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 5 deletions.
4 changes: 4 additions & 0 deletions cpp/server/brad_server_simple.cc
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,10 @@ void BradFlightSqlServer::InitWrapper(
auto location = arrow::flight::Location::ForGrpcTcp(host, port).ValueOrDie();
arrow::flight::FlightServerOptions options(location);

// NOTE: We bypass authentication for simplicity -- this is not recommended in
// a production setting.
options.auth_handler = std::make_shared<arrow::flight::NoOpAuthHandler>();

handle_query_ = handle_query;

const auto status = this->Init(options);
Expand Down
25 changes: 20 additions & 5 deletions src/brad/exec/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import brad
from brad.config.strings import SHELL_HISTORY_FILE
from brad.grpc_client import BradGrpcClient, BradClientError
from brad.flight_sql_client_odbc import BradFlightSqlClientOdbc


def register_command(subparsers):
Expand All @@ -21,6 +22,9 @@ def register_command(subparsers):
type=str,
help="Run a single SQL query (or internal command) and exit.",
)
parser.add_argument(
"--use-odbc", action="store_true", help="Use the ODBC endpoint instead of gRPC."
)
parser.add_argument(
"endpoint",
nargs="?",
Expand All @@ -39,11 +43,15 @@ def parse_endpoint(endpoint: str) -> Tuple[str, int]:

def run_command(args) -> None:
host, port = parse_endpoint(args.endpoint)
with BradGrpcClient(host, port) as client:
run_query(client, args.command)
if args.use_odbc:
with BradFlightSqlClientOdbc(host, port) as client:
run_query(client, args.command)
else:
with BradGrpcClient(host, port) as client:
run_query(client, args.command)


def run_query(client: BradGrpcClient, query: str) -> None:
def run_query(client: BradGrpcClient | BradFlightSqlClientOdbc, query: str) -> None:
try:
# Dispatch query and print results. We buffer the whole result
# set in memory to get a reasonable estimate of the query
Expand Down Expand Up @@ -79,7 +87,7 @@ class BradShell(cmd.Cmd):
MULTILINE_PROMPT = "--> "
TERM_STR = ";"

def __init__(self, client: BradGrpcClient) -> None:
def __init__(self, client: BradGrpcClient | BradFlightSqlClientOdbc) -> None:
super().__init__()
self.prompt = self.READY_PROMPT
self._client = client
Expand Down Expand Up @@ -139,7 +147,7 @@ def main(args) -> None:
print()
print("Connecting to BRAD VDBE at {}:{}...".format(host, port))

with BradGrpcClient(host, port) as client:
def run_shell(client: BradGrpcClient | BradFlightSqlClientOdbc) -> None:
print("Connected!")
print()
print("Terminate all SQL queries with a semicolon (;). Hit Ctrl-D to exit.")
Expand All @@ -148,3 +156,10 @@ def main(args) -> None:

shell = BradShell(client)
shell.cmdloop()

if args.use_odbc:
with BradFlightSqlClientOdbc(host, port) as client:
run_shell(client)
else:
with BradGrpcClient(host, port) as client:
run_shell(client)
14 changes: 14 additions & 0 deletions src/brad/flight_sql_client_odbc.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import pyodbc
from typing import Generator, Optional, Self, Tuple, List, Any
from brad.config.engine import Engine


class BradFlightSqlClientOdbc:
Expand Down Expand Up @@ -52,3 +53,16 @@ def run_query_generator(self, query: str) -> Generator[Tuple[Any, ...], None, No
def run_query(self, query: str) -> RowList:
assert self._cursor
return self._cursor.execute(query)

def run_query_json_cli(self, query: str) -> Tuple[RowList, Optional[Engine], bool]:
self.run_query(query)
assert self._cursor
results = self._cursor.fetchall()
all_rows = [tuple(row) for row in results]
return all_rows, None, False

def run_prepared(self, query: str, params: Tuple[Any, ...]) -> RowList:
assert self._cursor
self._cursor.execute(query, params)
results = self._cursor.fetchall()
return [tuple(row) for row in results]
64 changes: 64 additions & 0 deletions tools/flight_sql_jdbc/JdbcConnectionExample.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import java.sql.*;

// This example is used to test JDBC connections to BRAD VDBEs (using the Arrow
// Flight SQL JDBC driver).
public class JdbcConnectionExample {
public static void main(String[] args) throws SQLException {
try {
Class.forName("org.apache.arrow.driver.jdbc.ArrowFlightJdbcDriver"); // Example driver class
} catch (ClassNotFoundException e) {
System.err.println("Driver not found: " + e.getMessage());
return; // Exit if driver not found
}

String url = "jdbc:arrow-flight-sql://<host>:<port>/?useEncryption=false"; // Example URL
String user = "your_username";
String password = "your_password";

try (Connection connection = DriverManager.getConnection(url, user, password)) {
System.out.println("Connected to the database!");

// Regular statement.
try (Statement statement = connection.createStatement()) {
String sql = "SELECT 1, 2, 3 FROM homes LIMIT 5";

// 5. Execute the query
try (ResultSet resultSet = statement.executeQuery(sql)) {

// 6. Process the results
while (resultSet.next()) {
// Access columns by name or index
int val1 = resultSet.getInt(1);
int val2 = resultSet.getInt(2);
int val3 = resultSet.getInt(3);
System.out.println("val1: " + val1 + ", val2: " + val2 + ", val3: " + val3);
}
}
}

// Prepared statement.
String sql = "SELECT id, name FROM your_table WHERE status = ?"; // Example query
try (PreparedStatement statement = connection.prepareStatement(sql)) {

// 4. Set parameters for the PreparedStatement
String status = "active"; // Example parameter value
statement.setString(1, status); // Set the first parameter (index 1)

// 5. Execute the query
try (ResultSet resultSet = statement.executeQuery()) {

// 6. Process the results (if any)
while (resultSet.next()) {
int id = resultSet.getInt("id");
String name = resultSet.getString("name");
System.out.println("ID: " + id + ", Name: " + name);
}
}
}

} catch (SQLException e) {
System.err.println("Database error: " + e.getMessage());
}

}
}

0 comments on commit d7606e2

Please sign in to comment.