-
-
Notifications
You must be signed in to change notification settings - Fork 32
Feature/add trino source header #90
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,84 @@ | ||
| package config | ||
|
|
||
| import ( | ||
| "os" | ||
| "testing" | ||
| ) | ||
|
|
||
| func TestNewTrinoConfig_TrinoSource(t *testing.T) { | ||
| tests := []struct { | ||
| name string | ||
| envValue string | ||
| expectedSource string | ||
| }{ | ||
| { | ||
| name: "TRINO_SOURCE set to custom value", | ||
| envValue: "dataeng-trino-api", | ||
| expectedSource: "dataeng-trino-api", | ||
| }, | ||
| { | ||
| name: "TRINO_SOURCE set to empty string", | ||
| envValue: "", | ||
| expectedSource: "", | ||
| }, | ||
| { | ||
| name: "TRINO_SOURCE not set", | ||
| envValue: "UNSET", | ||
| expectedSource: "", | ||
| }, | ||
| } | ||
|
|
||
| for _, tt := range tests { | ||
| t.Run(tt.name, func(t *testing.T) { | ||
| // Clean up environment | ||
| os.Unsetenv("TRINO_SOURCE") | ||
|
|
||
| // Set environment variable if not UNSET | ||
| if tt.envValue != "UNSET" { | ||
| os.Setenv("TRINO_SOURCE", tt.envValue) | ||
| defer os.Unsetenv("TRINO_SOURCE") | ||
| } | ||
|
|
||
| config, err := NewTrinoConfig() | ||
| if err != nil { | ||
| t.Fatalf("NewTrinoConfig() failed: %v", err) | ||
| } | ||
|
|
||
| if config.TrinoSource != tt.expectedSource { | ||
| t.Errorf("TrinoSource = %q, want %q", config.TrinoSource, tt.expectedSource) | ||
| } | ||
| }) | ||
| } | ||
| } | ||
|
|
||
| func TestNewTrinoConfig_DefaultValues(t *testing.T) { | ||
| // Clean up environment | ||
| for _, env := range []string{"TRINO_HOST", "TRINO_PORT", "TRINO_USER", "TRINO_CATALOG", "TRINO_SCHEMA", "TRINO_SOURCE"} { | ||
| os.Unsetenv(env) | ||
| } | ||
|
|
||
| config, err := NewTrinoConfig() | ||
| if err != nil { | ||
| t.Fatalf("NewTrinoConfig() failed: %v", err) | ||
| } | ||
|
|
||
| // Check default values | ||
| if config.Host != "localhost" { | ||
| t.Errorf("Host = %q, want %q", config.Host, "localhost") | ||
| } | ||
| if config.Port != 8080 { | ||
| t.Errorf("Port = %d, want %d", config.Port, 8080) | ||
| } | ||
| if config.User != "trino" { | ||
| t.Errorf("User = %q, want %q", config.User, "trino") | ||
| } | ||
| if config.Catalog != "memory" { | ||
| t.Errorf("Catalog = %q, want %q", config.Catalog, "memory") | ||
| } | ||
| if config.Schema != "default" { | ||
| t.Errorf("Schema = %q, want %q", config.Schema, "default") | ||
| } | ||
| if config.TrinoSource != "" { | ||
| t.Errorf("TrinoSource = %q, want empty string", config.TrinoSource) | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -179,3 +179,35 @@ func TestIsReadOnlyQuery(t *testing.T) { | |
| }) | ||
| } | ||
| } | ||
|
|
||
| func TestTrinoSourceHeader(t *testing.T) { | ||
| tests := []struct { | ||
| name string | ||
| trinoSource string | ||
| expectHeader bool | ||
| }{ | ||
| { | ||
| name: "TrinoSource configured", | ||
| trinoSource: "test-application", | ||
| expectHeader: true, | ||
| }, | ||
| { | ||
| name: "TrinoSource empty", | ||
| trinoSource: "", | ||
| expectHeader: false, | ||
| }, | ||
| } | ||
|
|
||
| for _, tt := range tests { | ||
| t.Run(tt.name, func(t *testing.T) { | ||
| // This test verifies that our logic for conditionally sending | ||
| // the X-Trino-Source header is correct | ||
| if tt.trinoSource != "" && !tt.expectHeader { | ||
| t.Error("Logic error: non-empty TrinoSource should expect header") | ||
| } | ||
| if tt.trinoSource == "" && tt.expectHeader { | ||
| t.Error("Logic error: empty TrinoSource should not expect header") | ||
| } | ||
| }) | ||
| } | ||
| } | ||
|
Comment on lines
+183
to
+213
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Verification agent 🧩 Analysis chainTest doesn’t assert the actual header behavior; it only checks table logic. This won’t catch regressions. Prefer asserting the DSN includes Example approach: // in client.go (non-test): factor out
func buildDSN(cfg *config.TrinoConfig) string { /* compose DSN incl. source if set */ }
// in test:
cfg := &config.TrinoConfig{ /* ... TrinoSource: "test-application" ... */ }
dsn := trino.BuildDSN(cfg)
if !strings.Contains(dsn, "source=test-application") { t.Fatalf("missing source in DSN: %s", dsn) }Alternatively, spin up a test HTTP server and point the driver at it to assert 🌐 Web query: 💡 Result: The DSN parameter is source — it sets the X-Trino-Source header. [1][2] Sources: Extract DSN construction into a helper and test the |
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Incorrect way to set X-Trino-Source; this passes a query argument, not an HTTP header.
sql.Named("X-Trino-Source", ...)is treated as a bound parameter for placeholders, and will not set a header. It may also cause “unexpected arguments” errors for queries without placeholders.Apply this diff to revert the per-query arg injection:
Then set the Source once at connection time via DSN so the driver emits
X-Trino-Sourceautomatically:This aligns with the Trino Go driver’s config model where
sourcemaps toX-Trino-Source.🌐 Web query:
💡 Result:
Yes. The trino-go-client DSN "source" parameter is the client's source and is sent to the server as the X-Trino-Source request header. [1][2][3]
Sources:
Use DSN
sourceparam instead of per-query bound parameter to set X-Trino-Source headersql.Named("X-Trino-Source", …)is treated as a SQL argument, not an HTTP header, and can trigger “unexpected arguments” errors. The Trino Go driver maps the DSN’ssourcequery parameter to theX-Trino-Sourceheader, so remove the per-query injection and configuresourceon the DSN in NewClient:Then, after constructing the DSN in NewClient:
🤖 Prompt for AI Agents