Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,6 @@ Thumbs.db
*.test
*.out
coverage.html

# Local planning docs
PLAN.md
46 changes: 32 additions & 14 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,15 @@ import (

// FileConfig represents the YAML configuration file structure
type FileConfig struct {
Host string `yaml:"host"`
Port int `yaml:"port"`
DataDir string `yaml:"data_dir"`
TLS TLSConfig `yaml:"tls"`
Users map[string]string `yaml:"users"`
RateLimit RateLimitFileConfig `yaml:"rate_limit"`
Extensions []string `yaml:"extensions"`
DuckLake DuckLakeFileConfig `yaml:"ducklake"`
Host string `yaml:"host"`
Port int `yaml:"port"`
DataDir string `yaml:"data_dir"`
TLS TLSConfig `yaml:"tls"`
Users map[string]string `yaml:"users"`
RateLimit RateLimitFileConfig `yaml:"rate_limit"`
Extensions []string `yaml:"extensions"`
DuckLake DuckLakeFileConfig `yaml:"ducklake"`
QueryTimeout string `yaml:"query_timeout"` // e.g., "30s", "5m"
}

type TLSConfig struct {
Expand Down Expand Up @@ -109,12 +110,13 @@ func main() {
fmt.Fprintf(os.Stderr, "Options:\n")
flag.PrintDefaults()
fmt.Fprintf(os.Stderr, "\nEnvironment variables:\n")
fmt.Fprintf(os.Stderr, " DUCKGRES_CONFIG Path to YAML config file\n")
fmt.Fprintf(os.Stderr, " DUCKGRES_HOST Host to bind to (default: 0.0.0.0)\n")
fmt.Fprintf(os.Stderr, " DUCKGRES_PORT Port to listen on (default: 5432)\n")
fmt.Fprintf(os.Stderr, " DUCKGRES_DATA_DIR Directory for DuckDB files (default: ./data)\n")
fmt.Fprintf(os.Stderr, " DUCKGRES_CERT TLS certificate file (default: ./certs/server.crt)\n")
fmt.Fprintf(os.Stderr, " DUCKGRES_KEY TLS private key file (default: ./certs/server.key)\n")
fmt.Fprintf(os.Stderr, " DUCKGRES_CONFIG Path to YAML config file\n")
fmt.Fprintf(os.Stderr, " DUCKGRES_HOST Host to bind to (default: 0.0.0.0)\n")
fmt.Fprintf(os.Stderr, " DUCKGRES_PORT Port to listen on (default: 5432)\n")
fmt.Fprintf(os.Stderr, " DUCKGRES_DATA_DIR Directory for DuckDB files (default: ./data)\n")
fmt.Fprintf(os.Stderr, " DUCKGRES_CERT TLS certificate file (default: ./certs/server.crt)\n")
fmt.Fprintf(os.Stderr, " DUCKGRES_KEY TLS private key file (default: ./certs/server.key)\n")
fmt.Fprintf(os.Stderr, " DUCKGRES_QUERY_TIMEOUT Maximum query execution time (e.g., 30s, 5m)\n")
fmt.Fprintf(os.Stderr, "\nPrecedence: CLI flags > environment variables > config file > defaults\n")
}

Expand Down Expand Up @@ -194,6 +196,15 @@ func main() {
cfg.Extensions = fileCfg.Extensions
}

// Apply query timeout config
if fileCfg.QueryTimeout != "" {
if d, err := time.ParseDuration(fileCfg.QueryTimeout); err == nil {
cfg.QueryTimeout = d
} else {
slog.Warn("Invalid query_timeout duration: " + err.Error())
}
}

// Apply DuckLake config
if fileCfg.DuckLake.MetadataStore != "" {
cfg.DuckLake.MetadataStore = fileCfg.DuckLake.MetadataStore
Expand Down Expand Up @@ -282,6 +293,13 @@ func main() {
if v := os.Getenv("DUCKGRES_DUCKLAKE_S3_PROFILE"); v != "" {
cfg.DuckLake.S3Profile = v
}
if v := os.Getenv("DUCKGRES_QUERY_TIMEOUT"); v != "" {
if d, err := time.ParseDuration(v); err == nil {
cfg.QueryTimeout = d
} else {
slog.Warn("Invalid DUCKGRES_QUERY_TIMEOUT: " + err.Error())
}
}

// Apply CLI flags (highest priority)
if *host != "" {
Expand Down
Loading