Skip to content

[FEATURE] resolve server variables from environment variables (x-stackQL-envVar), analogous to auth credentialsenvvar #706

Closed

Description

@jeffreyaven

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.Extensions is not read anywhere today, so the key is conflict-free. Both call chains (operation_store.go and the exported ObtainServerURLsFromServers used by public/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 under RequiredParams - 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 on reload_credentials) already delivers the env vars in CLI, server, and MCP deployments.
  • An alternative shape - a serverVariables block in x-stackQL-config mirroring the auth DTO - is workable but touches the public StackQLConfig interface; 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.

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions