Extensions
CREATE EXTENSION changes a database's catalogue in ways Besu does not model. It is
migration SQL, by design: the differ never installs, upgrades or removes an extension, and
push does not know one exists.
Not supported yet. An extension cannot be declared in Rust or diffed. That is the design rather than a gap: an extension installs code, and what it adds afterwards is what the differ should see.
A down file only succeeds once the columns that use these types are gone: DROP EXTENSION
fails while an object still depends on it. Drop the dependent table or column first, or add
CASCADE, which drops it for you.
PostgreSQL requires the privileges its own rules demand: some extensions are trusted and can be installed by a database owner, others need a superuser.
Functions
pgcrypto and uuid-ossp add functions, not column types. Use them where Besu already
allows an expression:
The default is inserted verbatim, so it is only valid once the extension exists.
gen_random_uuid() moved into PostgreSQL's core in version 13; uuid_generate_v4() is
uuid-ossp's spelling on every version.
Types
A type an extension adds arrives as TypeDef::Custom(name), and Besu renders that name
verbatim. It can be created, introspected and compared. citext and PostGIS's geometry and
geography all take this path.
What Besu does not have is a Decode implementation for them, so reading one into a Rust
value needs a cast:
Gotchas
- The extension must exist before the migration that uses it. On a fresh database the
extension migration has to run first;
pushwill not create it. - A
citextcolumn is not aStringcolumn to the driver.citexthas its own type OID, so reading it without a::textcast fails at decode time. Declaring one in Rust needs a customSqlTypemarker named with#[besu(sql_type = "...")]; a snapshot is the shorter path. - PostGIS loses its typmod. A
geometry(Point, 4326)column is reported asgeometry, and DDL generated for it writes baregeometry. Create the column in a migration. - An index with an operator class is not modelled.
USING gin (name gin_trgm_ops)is reported as a plain index overname, because the IR records no access method and no operator class. A snapshot frombesu pullround-trips it; a snapshot built from the derive does not contain it, andbesu generatewill write aDROP INDEXfor it. pushwill not drop an extension, and it will not remove one either. There is noDROP EXTENSIONin any generated plan.
