[FEATURE] resolve server variables from environment variables (x-stackQL-envVar), analogous to auth credentialsenvvar #706
Description
Problem
Providers with templated server URLs force the same value into every WHERE clause. Eight registry providers are affected today:
| Provider | Server variables |
|---|---|
snowflake |
endpoint |
k8s |
protocol, cluster_addr |
okta |
subdomain |
databricks_workspace |
deployment_name |
aws / awscc |
region |
kafka |
kafka_endpoint_id, region, cloud_provider |
sumologic |
region |
-- today: endpoint repeated on every statement
SELECT name FROM snowflake.databases.databases WHERE endpoint = 'myorg-myaccount';Auth already solves the equivalent problem declaratively (credentialsenvvar: SNOWFLAKE_PAT); server variables have no such mechanism. There is currently no code path by which an environment variable influences URL construction: env vars reach only credential material (pkg/dto/auth_ctx.go), the SQL backend DSN, and MCP client config.
Today's fallback behaviour makes this worse than a missing-parameter error: when the WHERE omits the variable, generateServerURL (internal/anysdk/server.go) silently substitutes the spec default (e.g. orgname-accountname), so the request goes to a nonsense host and fails with an opaque DNS/HTTP error.
Proposal
A new extension key on the OpenAPI server variable, read during URL generation, with the resolution ladder: explicit WHERE/query value -> named env var -> spec default.
servers:
- url: https://{endpoint}.snowflakecomputing.com
variables:
endpoint:
default: orgname-accountname
x-stackQL-envVar: SNOWFLAKE_ENDPOINT-- with SNOWFLAKE_ENDPOINT set in the environment
SELECT name FROM snowflake.databases.databases;An explicit WHERE value always wins, so per-statement override (multi-account queries) keeps working unchanged.
Implementation notes (from code review of the current tree)
- Resolution point:
generateServerURL/selectServer(internal/anysdk/server.go:44-66, operation_store.go:1545-1558). The variable object is already in hand at the substitution site;openapi3.ServerVariable.Extensionsis not read anywhere today, so the key is conflict-free. Both call chains (operation_store.goand the exportedObtainServerURLsFromServersused bypublic/radix_tree_address_space) route through the same function. - Required-parameter semantics: server variables are enforced as required only on body-carrying methods (early return in
getRequiredParameters, operation_store.go:1227-1245, means SELECTs never enforce them). An env-resolvable variable should be dropped from the required set so INSERT/PUT statements also work without the explicit value. ToPresentationMap(operation_store.go:1442-1456) unconditionally lists server variables underRequiredParams-SHOW METHODS/ docgen should reflect env-resolvable variables as optional for consistency.- stackql core requires no changes: dotenv sourcing (
internal/stackql/envfile, sourced at startup and onreload_credentials) already delivers the env vars in CLI, server, and MCP deployments. - An alternative shape - a
serverVariablesblock inx-stackQL-configmirroring theauthDTO - is workable but touches the publicStackQLConfiginterface; the per-variable extension key needs no interface changes and is opt-in per provider doc.
Alternatives considered
- CLI
--var/jsonnet templating: substitutes into query text only, reads no env vars, and is bypassed in pgwire-server and MCP modes - unavailable exactly where this is most needed. - Injecting defaults at query planning in stackql core: the parameter map doubles as the symbol/column source and cache key input, so synthetic injection perturbs plan shape; and it duplicates knowledge any-sdk owns.
Activity
build: consume any-sdk v0.5.4-alpha01 - OCI signing, server variable …