#3689 fix(targets): honor 'schema' setting as alias for default_target_schema
Pull request opened by
Rasaec5
What
When a SQL target sets a schema setting but does not set default_target_schema,
the SDK now uses the configured schema as the destination schema instead of deriving
one from the incoming stream ID.
Why
Closes
#2766.
Many SQL targets expose a schema connection setting (for example the MeltanoLabs
variant of target-snowflake). Today, if default_target_schema is unset,
SQLSink.schema_name derives the schema from the stream ID — e.g. a record on stream
TAP_SCHEMA-users is written to a schema named tap_schema. When the connecting
account has no privileges on that derived schema, schema/table/file-format creation
fails. Users reasonably expect the schema they configured to be honored.
How
SQLSink.schema_name now resolves in this order:
default_target_schema (unchanged — keeps precedence so existing setups are unaffected)
schema (new fallback)
stream-derived (-
/ --)
None
Implementation:
Added a SQLSink.schema_config cached property that reads the schema setting and
returns it verbatim (no name conforming), mirroring the existing
default_target_schema property.
schema_name falls back to schema_config before the stream-derived branch.
This is intentionally non-breaking: default_target_schema still wins when both are set,
and behavior is unchanged when neither is set.
Files changed
singer_sdk/sql/sink.py — add schema_config; update schema_name.
tests/sql/test_sink.py — add test_schema_name_schema_setting parametrized cases.
tests/sql/test_schema_alias.py — new dedicated test module for the alias behavior.
Testing
Unit tests run without external credentials using a dummy SQL connector/sink/target.
Resolution-order matrix: schema overrides stream-derived for 1-, 2-, and 3-part
stream names; default_target_schema takes precedence when both are set; only
default_target_schema set; neither set (stream-derived fallback, including None
for 1- and 4-part stream names).
Edge cases: empty-string schema falls through; schema returned verbatim;
table_name derivation unaffected.
Regression: existing default_target_schema / stream-derived cases still pass.
python -m pytest tests/sql/test_schema_alias.py tests/sql/test_sink.py -v
tests/sql/test_sink.py -> 13 passed
tests/sql/test_schema_alias.py -> 13 passed
Open question for reviewers
Should schema also be registered as a documented builtin setting on SQLTarget
(an explicit alias of default_target_schema), or is reading it from config enough?
This PR keeps it read-from-config to avoid colliding with targets that already define
their own schema setting.
Notes / checklist
X I have read the
Contributing Guide.
X pre-commit run --all, nox -s tests, and nox -t typing pass locally.
X This contribution was assisted by an AI coding agent (per Meltano's
Agentic Coding guidelines).
Summary by Sourcery
Honor the
schema
configuration as a fallback destination schema for SQL sinks when
default_target_schema
is not set, while preserving existing precedence and stream-derived behavior.
New Features:
• Support the
schema
config setting as an alias/fallback for
default_target_schema
in SQLSink schema resolution.
Enhancements:
• Clarify and expand SQLSink docstrings for connector, connection, schema, table, and key properties accessors.
Documentation:
• Add a contributor README documenting the chosen issue, reproduction steps, implementation plan, and testing strategy for the schema alias change.
Tests:
• Add dedicated tests validating schema resolution precedence between
default_target_schema
,
schema
, and stream-derived names, including edge cases and regression coverage.
meltano/sdk