SchemaSmith v2.6.0 — declare what you used to script, and a tool that refuses by name #414
drzacharysmith68
announced in
Announcements
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
v2.5.0 was about SchemaSmith seeing more of your database and saying so out loud when it couldn't. v2.6.0 is about two things it was doing quietly that it shouldn't have been: running scripts that did nothing, and moving data you never asked it to move. Both are now loud. One turned into a whole class of object you can declare instead of script; the other turned into a refusal with your object's name in it.
Your scripted
CREATE TYPEhas been doing nothing, and now you can stop writing it. PostgreSQL enum types, sequences and domain types, and MySQL and MariaDB scheduled events, are all declarable now — anEnum Types/,Sequences/,Domain Types/orEvents/folder of.jsonfiles, compared and converged the way tables always have been, and removable by absence. Here's why this one matters more than a new folder usually does: the scripted form was worse than doing it by hand. There's noCREATE OR REPLACEfor a domain or an enum, so the recipe everyone lands on is a guardedCREATE TYPE ... IF NOT EXISTS. That works exactly once. Every deploy after it skips the guard and does nothing, so editing the value list, theCHECK, or the event body changed nothing at all — forever — while the run reported success. Declared, an enum's ordering is preserved, and removing a value is reported rather than performed, because that one can't be done safely.Three new table shapes on SQL Server, and one of them is a genuinely different engine. Memory-optimized (Hekaton) tables declare
MemoryOptimized: truewith aDurability, and their indexes emit inline with aBucketCountwhere the shape calls for one. Ledger tables ("Ledger": "AppendOnly"or"Updatable") create tamper-evident tables that round-trip. Graph tables ("GraphType": "Node"or"Edge") createAS NODE/AS EDGE. FILESTREAM columns store aVARBINARY(MAX)on an NTFS filegroup instead of in-row. Table-level Change Tracking is declarable withTrackColumnsUpdated.Physical layout is declarable — and SchemaSmith refuses to change it rather than rewriting your table. SQL Server tables and indexes can name a
PartitionSchemeandPartitionColumn; MySQL and MariaDB tables carry aPartitioningobject withMethod(RANGE, LIST, HASH, KEY and the COLUMNS forms). PostgreSQL tables and indexes take aTablespace, MySQL a general tablespace, both engines aDataDirectory, and MySQL and MariaDB at-rest encryption.TextImageFileGroupplaces large-object data on SQL Server. Every one of these applies when the table is created and is refused by name when you change it later, because each change rewrites the table underneath you. That's deliberate. A state-based tool that quietly moved a terabyte because two strings differed would be a worse tool.A table can be rebuilt instead of altered column by column. A deploy that changes several columns emits one
ALTERper column today.RebuildPolicy—ModeofNEVER,ALWAYSorTHRESHOLD, with aThresholdandOnOrderMismatch, cascading nearest-level-wins — builds the table once, copies the rows and swaps. Reordering existing columns is only possible this way. The load-bearing half is the guard family that refuses a rebuild when the live table can't survive a copy: system versioning, CDC, replication, Change Tracking, inheritance and partitioning. And a column change blocked bySCHEMABINDINGcan now resolve itself, since SQL Server's error 4922 tells you only that "one or more objects access this column" and never which ones.MariaDB temporal tables round-trip. A table created
WITH SYSTEM VERSIONINGkeeps its own row history, and MariaDB reports it asSYSTEM VERSIONEDrather thanBASE TABLE— which is exactly why it used to go missing from every extracted package and then get created a second time. Application-time periods (PERIOD FOR validity(start, end)) round-trip too,DropPeriodsRemovedFromProductremoves one the package no longer declares, andSystemVersioningAlterHistorymakes you opt in before a column change rewrites recorded history.PostgreSQL row-level security is a finished feature now.
RowLevelSecuritycould turn RLS on — which returns no rows to anyone but the owner — with no declarative way to add the policy that lets anyone back in. APoliciesarray closes that.REPLICA IDENTITYis declarable too, which matters more than it sounds: a published table without a usable replica identity makes PostgreSQL refuse the application'sUPDATEandDELETE, so two schema-identical databases disagree about whether a write works.Nineteen fixes, and idempotency is the theme. A deploy that changes nothing should change nothing, and a round trip should give you your file back. Loading and saving a package no longer adds keys you never wrote — a property that defaults itself used to materialize on first save, so a hand-authored file gained settings the author never chose. Re-extracting no longer silently reverts eight deploy-behaviour settings. A new table is created with its columns in the order the package declares, and MySQL and MariaDB extraction now orders columns the way SQL Server and PostgreSQL do. Also fixed: a rebuild silently de-partitioning a table (#410), a
serialcolumn's sequence extracted as a standalone object (#409), a temporal history table extracted as its own table file (#403), a graph table extracting to an undeployable package (#402),EnableCDCsilently ignored when CDC was off at the database (#401), MariaDB period re-deploys failing outright and system-versioned tables missing from extraction (#399), a full-text index with a nullChangeTrackingsilently skipped, and one unparseable table file aborting an entire extraction.One fix worth calling out on its own. A credential inside a URL is now masked in logs. Scrubbing caught a
Password=orPwd=connection-string field but not the userinfo inscheme://user:pass@host, so?password=secretin a value was masked whileuser:pass@hosta few characters earlier in the same value was not — which put any URL-shaped setting under an unremarkable name, a webhook or a custom endpoint, at risk of carrying its password into a log. Your database connection strings were never exposed by this: SchemaSmith builds those from discrete fields, and a raw--ConnectionStringis masked whole by name before that stage runs. The username, host, port and path survive scrubbing, so a scrubbed line is still diagnosable.Two things to know before you upgrade. Both are small and both are visible in a
git diff. First, a package that carries a property which defaults itself will stop writing that key on save, so your first extract after upgrading may drop keys it had been adding. Second, a table created from that package now gets its columns in declared order rather than alphabetical, which affects new tables only — existing tables are never reordered, because that's a rebuild. Run--Validatebefore you upgrade if you want the state of your packages on the record first.Release notes: https://github.com/Schema-Smith/SchemaSmith/releases/tag/v2.6.0 · CHANGELOG: https://github.com/Schema-Smith/SchemaSmith/blob/main/CHANGELOG.md · install with the
install.shone-liner,choco upgrade schemasmith,yay -S schemasmith-bin, or pull the Docker image (Chocolatey lands once moderation clears).The question I want back from you this time: what has SchemaSmith refused to do for you? The refusals in this release are all deliberate — partitioning, filegroups, tablespaces, a rebuild on a replicated table — and every one of them is a place where I decided your data mattered more than convergence did. Tell me where that call was wrong for your setup, and what you did instead. Those are the ones worth arguing about.
Shape. Strengthen. Succeed.
— Forge
All reactions