`-- atlas:renamed_from` is silently ignored when the desired state comes from `data "external_schema"` — renames plan as DROP COLUMN + ADD COLUMN
Atlas version: v1.3.0 (reproduced on Linux CI via ariga/setup-atlas and on Windows locally)
Driver: PostgreSQL 17
Summary
The -- atlas:renamed_from <prev> SQL directive (Declarative Schema Renames) produces ALTER TABLE … RENAME COLUMN when the SQL desired state is passed as file://. When the same SQL bytes reach Atlas through data "external_schema", the directive is ignored and atlas migrate diff plans DROP COLUMN + ADD COLUMN — at exit 0, with no warning. The generated migration would destroy the column's data.
Reproduction
Prior state (the migration directory's baseline), pre.sql:
CREATE SCHEMA IF NOT EXISTS crm;
CREATE TABLE "crm"."probe_col" ("id" uuid PRIMARY KEY, "tenant_id" uuid NOT NULL, "ai_confidence" numeric);
CREATE INDEX "idx_probe_col_conf" ON "crm"."probe_col" ("ai_confidence");Desired state, f.sql:
CREATE SCHEMA IF NOT EXISTS crm;
CREATE TABLE IF NOT EXISTS crm.probe_col (
id uuid NOT NULL,
tenant_id uuid NOT NULL,
-- atlas:renamed_from ai_confidence
confidence_ai numeric,
CONSTRAINT probe_col_pkey PRIMARY KEY (id)
);
CREATE INDEX IF NOT EXISTS idx_probe_col_conf ON crm.probe_col (confidence_ai);atlas.hcl:
data "external_schema" "p" {
program = ["cat", "f.sql"]
}
env "ext" {
src = data.external_schema.p.url
dev = "postgres://…/dev?sslmode=disable" # an empty database
migration { dir = "file://migrations" }
}Each case uses a fresh migration directory seeded with the same baseline:
atlas migrate diff baseline --dir file://migrations --to file://pre.sql --dev-url <dev>
atlas migrate diff rename_probe --env ext # A
atlas migrate diff rename_probe --env ext --to file://f.sql # B
atlas migrate diff rename_probe --dir file://migrations --to file://f.sql --dev-url <dev> # CObserved
| case | desired state via | plan |
|---|---|---|
| A | data "external_schema" |
DROP INDEX …; ALTER TABLE "crm"."probe_col" DROP COLUMN "ai_confidence", ADD COLUMN "confidence_ai" numeric NULL; CREATE INDEX … — exit 0, no warning |
| B | same env, --to file://f.sql |
ALTER TABLE "crm"."probe_col" RENAME COLUMN "ai_confidence" TO "confidence_ai"; |
| C | file://f.sql |
ALTER TABLE "crm"."probe_col" RENAME COLUMN "ai_confidence" TO "confidence_ai"; |
Controls: with the directive removed, both the data "external_schema" input (A) and the file:// input (C, also used by B) plan DROP + ADD. So the directive is what differs, and on identical bytes only the external_schema input discards it.
atlas migrate lint does flag a column drop (DS103) in the same environment, so the gap is in planning, not analysis. The silence is what makes it dangerous: migrate diff exits 0 with a destructive plan and gives no indication that a directive in the input was not applied.
Expected
Either the directive is honoured for SQL loaded through data "external_schema", or Atlas reports that directives are not supported on that input rather than silently producing a destructive plan. The rename documentation covers HCL and SQL schemas and does not say external schemas are excluded.
Workaround
Write the program's output to a file and pass --to file://<file> (case B).
Source: ariga/atlas