diff --git a/.github/demos/rename.gif b/.github/demos/rename.gif index dbafd7f81b..a374103aba 100644 Binary files a/.github/demos/rename.gif and b/.github/demos/rename.gif differ diff --git a/README.md b/README.md index 3dc9d8eb68..8b04b0cc7d 100644 --- a/README.md +++ b/README.md @@ -19,11 +19,11 @@ Python data pipelines, and it keeps its state in append-only tables in your own external state database, no manifest files and no paid tier.
-
+
- Declarations live next to the models that use them, and the compiler enforces who can see them. sqb scope shows what a move would break.
+ Declarations live next to the models that use them, and the compiler enforces who can see them. sqb scope shows what a move would break, and sqb mv moves the model's private macros, enums and constants with it.
models/marts/
@@ -322,15 +322,24 @@ See what the tests missed
Rename models without rebuilding history
- A renamed incremental model keeps its table instead of starting again. If the logic changed too, declare migrate_from.
+ sqb rename and sqb mv update every reference and keep the existing table, so an incremental model doesn't start again. The old name keeps working as a view. Renamed columns keep their history too.
-sqb plan
+sqb rename model:daily_activity_rollup daily_order_rollup
+Rename model daily_activity_rollup -> daily_order_rollup
+├── models/marts/daily_order_rollup.sql (moved from models/marts/daily_activity_rollup.sql)
+└── models/marts/hourly_activity_with_daily_context.sql
+ └── 36:19 reference __ref("daily_activity_rollup") -> __ref("daily_order_rollup")
+Compiled: ok, 2 files changed
+
+sqb plan
Migrations (1)
└── daily_order_rollup migrate dev.daily_activity_rollup -> dev.daily_order_rollup
├── compatibility compatible
├── transfer physical copy, promote by staged rename
- └── discovery automatic
+ └── old name dev.daily_activity_rollup
+ ├── view until 2026-11-05
+ └── old table archived
diff --git a/website/public/styles.css b/website/public/styles.css
index 179e19974f..64813f0145 100644
--- a/website/public/styles.css
+++ b/website/public/styles.css
@@ -742,7 +742,7 @@ footer a {
margin-top: 0;
}
-/* Hero visual: a model is moved and renamed, then sqb plan shows the migration. */
+/* Hero visual: sqb mv moves and renames a model, then sqb plan shows the migration. */
.hero {
display: grid;
grid-template-columns: minmax(0, 1fr) auto;
@@ -754,7 +754,7 @@ footer a {
border: 1px solid var(--panel-border);
border-left: 1px solid var(--inner-line);
border-radius: var(--radius);
- min-height: 236px;
+ min-height: 300px;
}
.hero-visual {
@@ -823,6 +823,27 @@ footer a {
}
}
+@keyframes hv-l0 {
+ 0%,
+ 6% {
+ opacity: 0;
+ transform: translateY(3px);
+ }
+ 9%,
+ 92% {
+ opacity: 1;
+ transform: none;
+ }
+ 96%,
+ 100% {
+ opacity: 0;
+ }
+}
+
+.hv-l0 {
+ animation-name: hv-l0;
+}
+
@keyframes hv-l1 {
0%,
24% {
@@ -949,6 +970,48 @@ footer a {
animation-name: hv-l6;
}
+@keyframes hv-l7 {
+ 0%,
+ 45% {
+ opacity: 0;
+ transform: translateY(3px);
+ }
+ 48%,
+ 92% {
+ opacity: 1;
+ transform: none;
+ }
+ 96%,
+ 100% {
+ opacity: 0;
+ }
+}
+
+.hv-l7 {
+ animation-name: hv-l7;
+}
+
+@keyframes hv-l8 {
+ 0%,
+ 48% {
+ opacity: 0;
+ transform: translateY(3px);
+ }
+ 51%,
+ 92% {
+ opacity: 1;
+ transform: none;
+ }
+ 96%,
+ 100% {
+ opacity: 0;
+ }
+}
+
+.hv-l8 {
+ animation-name: hv-l8;
+}
+
@media (prefers-reduced-motion: reduce) {
.hero-visual .hv-a,
.hero-visual .hv-b,
@@ -979,4 +1042,8 @@ footer a {
.hero-visual .hv-wide {
display: none;
}
+
+ .hero-visual .hv-break::after {
+ content: '\\\A ';
+ }
}
diff --git a/website/recordings/README.md b/website/recordings/README.md
index e1c0a64dca..0b3b5a8254 100644
--- a/website/recordings/README.md
+++ b/website/recordings/README.md
@@ -6,7 +6,7 @@ scripts are the source; the rendered GIF, MP4 and PNG files go to `out/`, which
| Demo | Shows |
|------|-------|
-| `rename` | A model is moved and renamed, and `sqb plan` migrates the existing table. |
+| `rename` | `sqb mv` moves and renames a model, and `sqb plan` migrates the existing table. |
| `contract` | A renamed column fails `sqb compile` against an enforced contract. |
| `rules` | A custom rule and a missing test mock fail `sqb compile`. |
| `scope` | `sqb scope --as-path` previews what a move would lose. |
diff --git a/website/recordings/prepare.sh b/website/recordings/prepare.sh
index f5a9ebdcdd..b3febac79a 100755
--- a/website/recordings/prepare.sh
+++ b/website/recordings/prepare.sh
@@ -9,11 +9,12 @@ rm -rf "$dir"
mkdir -p "$here/scratch"
case "$demo" in
rename)
- # Build the model under its old name, so the tape can move it back to models/finance.
+ # Build the model under its old name, so the tape can move it back to models/finance with sqb mv.
cp -r "$examples/hero-shop" "$dir"
cd "$dir"
mkdir -p models/marts
mv models/finance/daily_revenue.sql models/marts/revenue.sql
+ rmdir models/finance
sqb build >/dev/null ;;
contract)
# Give daily_revenue an enforced contract, then rename one of its columns in the SELECT.
diff --git a/website/recordings/tapes/rename.tape b/website/recordings/tapes/rename.tape
index e93740995c..f0a3cc0cc0 100644
--- a/website/recordings/tapes/rename.tape
+++ b/website/recordings/tapes/rename.tape
@@ -1,5 +1,5 @@
Source tapes/common.tape
-Set Height 800
+Set Height 1080
Output out/rename.gif
Output out/rename.mp4
Hide
@@ -10,10 +10,11 @@ Show
Type "tree --noreport models"
Enter
Sleep 1500ms
-Type "mv models/marts/revenue.sql models/finance/daily_revenue.sql"
+Type "sqb mv model:revenue models/finance/daily_revenue.sql"
Sleep 300ms
Enter
-Sleep 800ms
+Wait@60s /\$\s*$/
+Sleep 1500ms
Type "sqb plan"
Sleep 300ms
Enter