You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

141 lines
3.8 KiB

package command
import (
"context"
"fmt"
"os"
"os/signal"
"syscall"
"time"
weed_server "github.com/seaweedfs/seaweedfs/weed/server"
"github.com/seaweedfs/seaweedfs/weed/util"
)
var (
jdbcOptions JdbcOptions
)
type JdbcOptions struct {
host *string
port *int
masterAddr *string
}
func init() {
cmdJdbc.Run = runJdbc // break init cycle
jdbcOptions.host = cmdJdbc.Flag.String("host", "localhost", "JDBC server host")
jdbcOptions.port = cmdJdbc.Flag.Int("port", 8089, "JDBC server port")
jdbcOptions.masterAddr = cmdJdbc.Flag.String("master", "localhost:9333", "SeaweedFS master server address")
}
var cmdJdbc = &Command{
UsageLine: "jdbc -port=8089 -master=<master_server>",
Short: "start a JDBC server for SQL queries",
Long: `Start a JDBC server that provides SQL query access to SeaweedFS.
This JDBC server allows standard JDBC clients and tools to connect to SeaweedFS
and execute SQL queries against MQ topics. It implements a subset of the JDBC
protocol for compatibility with most database tools and applications.
Examples:
# Start JDBC server on default port 8089
weed jdbc
# Start on custom port with specific master
weed jdbc -port=8090 -master=master1:9333
# Allow connections from any host
weed jdbc -host=0.0.0.0 -port=8089
Clients can then connect using JDBC URL:
jdbc:seaweedfs://hostname:port/database
Supported SQL operations:
- SELECT queries on MQ topics
- DESCRIBE/DESC commands
- SHOW DATABASES/TABLES commands
- Aggregation functions (COUNT, SUM, AVG, MIN, MAX)
- WHERE clauses with filtering
- System columns (_timestamp_ns, _key, _source)
Compatible with:
- Standard JDBC tools (DBeaver, IntelliJ DataGrip, etc.)
- Business Intelligence tools (Tableau, Power BI, etc.)
- Java applications using JDBC drivers
- SQL reporting tools
`,
}
func runJdbc(cmd *Command, args []string) bool {
util.LoadConfiguration("security", false)
// Validate options
if *jdbcOptions.masterAddr == "" {
fmt.Fprintf(os.Stderr, "Error: master address is required\n")
return false
}
// Create JDBC server
jdbcServer, err := weed_server.NewJDBCServer(*jdbcOptions.host, *jdbcOptions.port, *jdbcOptions.masterAddr)
if err != nil {
fmt.Fprintf(os.Stderr, "Error creating JDBC server: %v\n", err)
return false
}
// Start the server
fmt.Printf("Starting SeaweedFS JDBC Server...\n")
fmt.Printf("Host: %s\n", *jdbcOptions.host)
fmt.Printf("Port: %d\n", *jdbcOptions.port)
fmt.Printf("Master: %s\n", *jdbcOptions.masterAddr)
fmt.Printf("\nJDBC URL: jdbc:seaweedfs://%s:%d/default\n", *jdbcOptions.host, *jdbcOptions.port)
fmt.Printf("\nSupported operations:\n")
fmt.Printf(" - SELECT queries on MQ topics\n")
fmt.Printf(" - DESCRIBE/DESC table_name\n")
fmt.Printf(" - SHOW DATABASES\n")
fmt.Printf(" - SHOW TABLES\n")
fmt.Printf(" - Aggregations: COUNT, SUM, AVG, MIN, MAX\n")
fmt.Printf(" - System columns: _timestamp_ns, _key, _source\n")
fmt.Printf("\nReady for JDBC connections!\n\n")
err = jdbcServer.Start()
if err != nil {
fmt.Fprintf(os.Stderr, "Error starting JDBC server: %v\n", err)
return false
}
// Set up signal handling for graceful shutdown
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
// Wait for shutdown signal
<-sigChan
fmt.Printf("\nReceived shutdown signal, stopping JDBC server...\n")
// Create context with timeout for graceful shutdown
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
// Stop the server with timeout
done := make(chan error, 1)
go func() {
done <- jdbcServer.Stop()
}()
select {
case err := <-done:
if err != nil {
fmt.Fprintf(os.Stderr, "Error stopping JDBC server: %v\n", err)
return false
}
fmt.Printf("JDBC server stopped successfully\n")
case <-ctx.Done():
fmt.Fprintf(os.Stderr, "Timeout waiting for JDBC server to stop\n")
return false
}
return true
}