Commit Graph

44 Commits

Author SHA1 Message Date
Andrew Farries
f764993640
Implement 'drop column' migrations (#48)
Implement the **drop column**  migration operation.

A migration to drop a column looks like this:

```json
{
  "name": "09_drop_column",
  "operations": [
    {
      "drop_column": {
        "table": "fruits",
        "column": "price",
        "down": "0"
      }
    }
  ]
}
```

The migration takes the name of the table and column that should be
dropped along with (optionally) some `down` SQL to run to populate the
field in the underlying table when insertions are done via the new
schema version while the migration is in progress.

* On `Start`, the relevant view in the new version schema is created
without the dropped column. The column is not deleted from the
underlying table.
* If `down` SQL is specified, a trigger is created on the underlying
table to populate the column to be removed when inserts are made from
the new schema version.
* On `Rollback` any triggers on the underlying table are removed.
* On `Complete` the old version of the schema is removed and the column
is removed from the underlying table. Any triggers are also removed.
2023-08-17 07:37:48 +01:00
Andrew Farries
450e6db231
Implement the drop table operation (#45)
Add support for **drop table** migrations.

* On starting the migration the table is not dropped; but is not present
in the new version of the schema.
* The table is dropped on completion of the migration.
* Rollback is a no-op.
2023-08-17 06:43:42 +01:00
Andrew Farries
7d48a0099e
Remove up sql triggers on add column completion (#41)
https://github.com/xataio/pg-roll/pull/35 ensured that the triggers
added to run `up` SQL are removed on `Rollback`, but the same needs to
happen on `Complete`.

This PR does that and extends the test to check for it.
2023-07-21 08:45:46 +01:00
Andrew Farries
09a76c3603
Implement Complete for adding columns with NOT NULL and no DEFAULT (#39)
Implement `Complete` for **add column** operations that add a `NOT NULL`
column without a `DEFAULT`.

To add such a column without forcing a exclusive lock while a full table
scan is performed, these steps need to be followed:

On `Start`:
1. Add the new column
2. Add a `CHECK IS NOT NULL` constraint to the new column, but with `NOT
VALID`, to avoid the scan.
3. Backfill the new column with the provided `up` SQL.

On `Complete`
1. Validate the constraint (with `ALTER TABLE VALIDATE CONSTRAINT`).
2. Add the `NOT NULL` attribute to the column. The presence of a valid
`NOT NULL` constraint on the column means that adding `NOT NULL` to the
column does not perform a full table scan.

See [this
post](https://medium.com/paypal-tech/postgresql-at-scale-database-schema-changes-without-downtime-20d3749ed680#00dc)
for a summary of these steps.
2023-07-21 07:59:25 +01:00
Andrew Farries
34d24f088a
Implement Rollback for adding columns with NOT NULL and no DEFAULT (#38)
Implement `Rollback` for **add column** operations that add a `NOT NULL`
column without a `DEFAULT`.

Support for starting such an operation was added in
https://github.com/xataio/pg-roll/pull/37. See that PR for a description
of the steps involved.

In order to roll back, there is nothing to be done as the rollback for
the **add column** operation already removes the new column, which also
removes any constraints defined on the column.

This PR adds an `afterRollback` hook to the tests to verify that the
constraint has been dropped.
2023-07-21 07:52:56 +01:00
Andrew Farries
9a08b6cc77
Implement Start for adding columns with NOT NULL and no DEFAULT (#37)
Implement `Start` for **add column** operations that add a `NOT NULL`
column without a `DEFAULT`.

To add such a column without forcing a exclusive lock while a full table
scan is performed, these steps need to be followed:

On `Start`:
1. Add the new column
2. Add a `CHECK IS NOT NULL` constraint to the new column, but with `NOT
VALID`, to avoid the scan.
3. Backfill the new column with the provided `up` SQL.

On `Complete`
1. Validate the constraint (with `ALTER TABLE VALIDATE CONSTRAINT`).
2. Add the `NOT NULL` attribute to the column. The presence of a valid
`NOT NULL` constraint on the column means that adding `NOT NULL` to the
column does not perform a full table scan.

See [this
post](https://medium.com/paypal-tech/postgresql-at-scale-database-schema-changes-without-downtime-20d3749ed680#00dc)
for a summary of these steps.
2023-07-21 07:47:42 +01:00
Andrew Farries
7e209da2ea
Pin Go to 1.20.5 to work around testcontainers/Go breakage (#40)
Pin Go to version `1.20.5` to fix
[testcontainer](https://golang.testcontainers.org/) tests.

Go `1.20.6` introduced changes in `Host` header parsing
([issue](https://github.com/golang/go/issues/61431)) which breaks
`testcontainers-go`
([issue](https://github.com/testcontainers/testcontainers-go/issues/1359)).

Our tests started failing consistently yesterday due to this issue
([example
run](https://github.com/xataio/pg-roll/actions/runs/5612153506)).

The suggested workaround until this is resolved upstream is to pin to
`1.20.5`.
2023-07-21 07:44:35 +01:00
Andrew Farries
8fbfe0b988
Backfill existing rows with up SQL on add column migration start (#36)
When an **add column** migration is started on a table with existing
rows, backfill the values of the new column using the `up` SQL from the
migration.

The backfill implementation here is naive; for tables with many rows a
batched update is more appropriate.
2023-07-20 06:54:15 +01:00
Andrew Farries
4663091cc8
Delete trigger and trigger function on add column operation rollback (#35)
Support for `up` SQL in  **add column** operations was added in #34 

When such an **add column** operation runs, a trigger (and therefore a
trigger function) is created to implement running `up` SQL on insertions
to the old schema.

This PR ensures that the trigger and function are dropped when the
migration is rolled back:

* Extract two functions so that the rollback operations can name the
function to be dropped.
* Add necessary assertion functions to the common test infra.
* Add an `afterRollback` hook to the existing test for `up` SQL.
2023-07-20 06:50:11 +01:00
Andrew Farries
b4efd8ad50
Support up SQL on add column operations (#34)
Add a new field `Up` to **add column** migrations:

```json
{
  "name": "03_add_column_to_products",
  "operations": [
    {
      "add_column": {
        "table": "products",
        "up": "UPPER(name)",
        "column": {
          "name": "description",
          "type": "varchar(255)",
          "nullable": true
        }
      }
    }
  ]
}
```

The SQL specified by the `up` field will be run whenever an row is
inserted into the underlying table when the session's `search_path` is
not set to the latest version of the schema.

The `up` SQL snippet can refer to existing columns in the table by name
(as in the the above example, where the `description` field is set to
`UPPER(name)`).
2023-07-20 06:37:03 +01:00
Andrew Farries
37b75384a9
Add a --complete flag to to the start command (#33)
If set, complete the migration immediately after starting it.

For example:

```bash
go run start examples/02_create_another_table.json --complete
```

Completes the migration immediately, without the user having to run
`complete`.
2023-07-18 09:08:49 +01:00
Andrew Farries
11cbe3a2bd
Allow MustSelect to return arbitrary field types (#32)
Change the `MustSelect` function to allow it to return arbitrary types,
rather than assuming all values are of type `string`.

In particular, this change will allow tests to check for the presence of
`NULL`s in the returned values.

`MustSelect` casts all 64 bit integers back to 32 bit, in order to
reduce the noise in test code.

For example, with 64 bit ints we'd have to write:

```golang
{"id": int64(2), "name": "Bob", "age": int64(21)},
```

rather than:
```golang
{"id": 2, "name": "Bob", "age": 21},
```

The potential loss of precision in test code seems unlikely to affect
us, so favouring ease of reading of test code here.
2023-07-13 11:03:49 +01:00
Andrew Farries
a7bca53d16
Use common test infrastructure for the add column operation tests (#31)
Replace the tests for the **add column** operation with the more concise
`ExecuteTests` style introduced in #23.

To support this, some new assertion functions are added:

* `ColumnMustExist/ColumnMustNotExist`
* `TableMustHaveColumnCount`
2023-07-13 08:41:58 +01:00
Andrew Farries
dce42da85a
Support adding columns with UNIQUE, NOT NULL and DEFAULT constraints (#30)
Allow the **add column** operation to add columns with `NOT NULL`,
`UNIQUE` and `DEFAULT` constraints by re-using the SQL generation code
that adds columns to tables.
2023-07-13 08:38:43 +01:00
Carlos Pérez-Aradros Herce
87f0be5ea5
Add migrations validation before executing them (#27)
This will check that operations are valid (can actually be executed
against the given schema).

I'm pretty sure we can do way more validation, but wanted to have the
infra in place before we have many ops and this becomes a bigger change
2023-07-12 16:14:40 +01:00
Andrew Farries
c6a297a461
Sort keys before constructing INSERT statement in MustInsert (#29)
Sort the keys in the record map before constructing the `INSERT`
statement, to ensure a consistent ordering of the column names and
values in the `INSERT` statement.

For example inserting records into a `users` table could sometimes
generate these two `INSERT` statements depending how the map was
iterated:

```
INSERT INTO public_02_add_column.users (name, age) VALUES ('21', 'Bob')
INSERT INTO public_02_add_column.users (name, age) VALUES ('Bob', '21')
```

the first of which will fail (assuming the `age` field as type
`integer`).

This was causing flaky tests when inserting values into multiple
columns.
2023-07-12 09:14:00 +01:00
Andrew Farries
6389edf62d
Use table tests for create table operation (#28)
* Convert the tests for the **create table** operation to use the more
concise table driven style introduced in #23.
* Add a new `afterRollback` hook to the common test infra to allow the
**create table** op to test that the underlying table is removed on
rollback.
* Rename functions in the common test infra to make it clear where we
are checking for the existence of a table vs a view.
2023-07-11 15:34:31 +01:00
Andrew Farries
952b3598d8
Respect --schema flag (#26)
Make `pg-roll` respect the `--schema` flag by ensuring migrations are
run in the schema specified by the flag.
2023-07-11 14:57:54 +01:00
Andrew Farries
6cc22c5a63
Add status subcommand (#25)
Add a `status` command to show the status of each schema that `pg-roll`
knows about (ie ,those schema that have had >0 migrations run in them).

`go run . status`

**Example output**:
```json
[
  {
    "Schema": "public",
    "Version": "01_create_tables",
    "Status": "In Progress"
  }
]
```
or:

```json
[
  {
    "Schema": "public",
    "Version": "01_create_tables",
    "Status": "Complete"
  }
]
```

In future the `json` output of the command should be behind a `-o json`
switch and the default output should be human readable.
2023-07-11 11:07:18 +01:00
Carlos Pérez-Aradros Herce
28187f3cb3
Rename table op (#23)
Add rename table operation.

I worked a bit toward table-based testing with reusable code in
`op_common_test.go`

---------

Co-authored-by: Andrew Farries <andyrb@gmail.com>
2023-07-11 08:01:05 +00:00
Andrew Farries
99dd68815d
Reimplement analyze subcommand (#24)
The hidden `analyze` subcommand to dump the inferred database schema to
stdout was implemented in #1.

We've since changed how the schema is inferred (in #12).

This PR updates the `analyze` command to use the schema retrieval
implemented in #12.

Example

`go run . analyze public`:
```json
{
  "tables": {
    "bills": {
      "oid": "16417",
      "name": "bills",
      "comment": "",
      "columns": {
        "date": {
          "name": "date",
          "type": "time with time zone",
          "default": null,
          "nullable": false,
          "comment": ""
        },
        "id": {
          "name": "id",
          "type": "integer",
          "default": null,
          "nullable": false,
          "comment": ""
        },
        "quantity": {
          "name": "quantity",
          "type": "integer",
          "default": null,
          "nullable": false,
          "comment": ""
        }
      }
    },
    "customers": {
      "oid": "16408",
      "name": "customers",
      "comment": "",
      "columns": {
        "credit_card": {
          "name": "credit_card",
          "type": "text",
          "default": null,
          "nullable": true,
          "comment": ""
        },
        "id": {
          "name": "id",
          "type": "integer",
          "default": null,
          "nullable": false,
          "comment": ""
        },
        "name": {
          "name": "name",
          "type": "varchar(255)",
          "default": null,
          "nullable": false,
          "comment": ""
        }
      }
    }
  }
}
```
2023-07-11 08:13:23 +01:00
Andrew Farries
6430f05353
Implement 'add column' migrations for nullable columns (#20)
Add support for **add column** migrations in the simple case where the
new column is nullable.

Add tests for the new operation, covering start, rollback and complete,
in the cases where the add column operation is running against a table
created in an earlier migration and in the case where the the column is
added to a table created in an operation earlier in the migration.

Reshape [offers](https://github.com/fabianlindfors/reshape#add-column)
an `up` option when adding a column, to allow users to backfill the new
column. This PR does not implement this feature.
2023-07-07 11:23:19 +01:00
Andrew Farries
3108780fb5
Add json lint step to the pipeline (#22)
Add a step to the `lint` job in the build workflow to check that all the
example `.json` migration files are consistently formatted.

The step fails as of this PR. It will pass when rebased on to
https://github.com/xataio/pg-roll/pull/21.
2023-07-07 08:24:02 +01:00
Andrew Farries
1a7eb3271a
Format the examples with jq (#21) 2023-07-06 15:26:29 +01:00
Andrew Farries
cb5f191acf
Restructure tests (#17)
* Add tests for the `roll` package to ensure that the new versioned
schema is created on `start` and removed on `rollback`. We already had a
test there to ensure the previous versioned schema is dropped on
`complete`.
* Remove parts of tests for the create table operation that concerned
themselves with checking for the existence/non-existence of the
versioned schema. That is now tested in the `roll` package and we want
the tests for each operation to be focussed on the operation itself, not
schema creation.
* Add one more test for the create table operation to ensure that the
view for the new table is usable after `complete` (we already had a test
to ensure that it's usable on `start`).
2023-07-06 08:56:01 +01:00
dependabot[bot]
0139d75560
Bump google.golang.org/grpc from 1.47.0 to 1.53.0 (#18)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from
1.47.0 to 1.53.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/grpc/grpc-go/releases">google.golang.org/grpc's
releases</a>.</em></p>
<blockquote>
<h2>Release 1.53.0</h2>
<h1>API Changes</h1>
<ul>
<li>balancer: support injection of per-call metadata from LB policies
(<a
href="https://redirect.github.com/grpc/grpc-go/issues/5853">#5853</a>)</li>
<li>resolver: remove deprecated field
<code>resolver.Target.Endpoint</code> and replace with
<code>resolver.Target.Endpoint()</code> (<a
href="https://redirect.github.com/grpc/grpc-go/issues/5852">#5852</a>)
<ul>
<li>Special Thanks: <a
href="https://github.com/kylejb"><code>@​kylejb</code></a></li>
</ul>
</li>
</ul>
<h1>New Features</h1>
<ul>
<li>xds/ringhash: introduce <code>GRPC_RING_HASH_CAP</code> environment
variable to override the maximum ring size. (<a
href="https://redirect.github.com/grpc/grpc-go/issues/5884">#5884</a>)</li>
<li>rls: propagate headers received in RLS response to backends (<a
href="https://redirect.github.com/grpc/grpc-go/issues/5883">#5883</a>)</li>
</ul>
<h1>Bug Fixes</h1>
<ul>
<li>transport: drain client transport when streamID approaches
MaxStreamID (<a
href="https://redirect.github.com/grpc/grpc-go/issues/5889">#5889</a>)</li>
<li>server: after GracefulStop, ensure connections are closed when final
RPC completes (<a
href="https://redirect.github.com/grpc/grpc-go/issues/5968">#5968</a>)</li>
<li>server: fix a few issues where grpc server uses RST_STREAM for
non-HTTP/2 errors (<a
href="https://redirect.github.com/grpc/grpc-go/issues/5893">#5893</a>)</li>
<li>xdsclient: fix race which can happen when multiple load reporting
calls are made at the same time. (<a
href="https://redirect.github.com/grpc/grpc-go/issues/5927">#5927</a>)</li>
<li>rls: fix a data race involving the LRU cache (<a
href="https://redirect.github.com/grpc/grpc-go/issues/5925">#5925</a>)</li>
<li>xds: fix panic involving double close of channel in xDS transport
(<a
href="https://redirect.github.com/grpc/grpc-go/issues/5959">#5959</a>)</li>
<li>gcp/observability: update method name validation (<a
href="https://redirect.github.com/grpc/grpc-go/issues/5951">#5951</a>)</li>
</ul>
<h1>Documentation</h1>
<ul>
<li>credentials/oauth: mark <code>NewOauthAccess</code> as deprecated
(<a
href="https://redirect.github.com/grpc/grpc-go/issues/5882">#5882</a>)
<ul>
<li>Special Thanks: <a
href="https://github.com/buzzsurfr"><code>@​buzzsurfr</code></a></li>
</ul>
</li>
</ul>
<h2>Release 1.52.3</h2>
<h1>Bug Fixes</h1>
<ul>
<li>Fix user-agent version</li>
</ul>
<h2>Release 1.52.2</h2>
<h1>Bug Fixes</h1>
<ul>
<li>xds: fix panic involving double close of channel in xDS transport
(<a
href="https://redirect.github.com/grpc/grpc-go/issues/5959">#5959</a>)</li>
</ul>
<h2>Release 1.52.1</h2>
<h1>Bug Fixes</h1>
<ul>
<li>grpclb: rename grpclbstate package back to state (<a
href="https://redirect.github.com/grpc/grpc-go/issues/5963">#5963</a>)</li>
</ul>
<h2>Release 1.52.0</h2>
<h1>New Features</h1>
<ul>
<li>xdsclient: log node ID with verbosity INFO (<a
href="https://redirect.github.com/grpc/grpc-go/issues/5860">#5860</a>)</li>
<li>ringhash: impose cap on <code>max_ring_size</code> to reduce
possibility of OOMs (<a
href="https://redirect.github.com/grpc/grpc-go/issues/5801">#5801</a>)</li>
</ul>
<h1>Behavior Changes</h1>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="dba26e15a0"><code>dba26e1</code></a>
Change version to 1.53.0 (<a
href="https://redirect.github.com/grpc/grpc-go/issues/5983">#5983</a>)</li>
<li><a
href="2a1e9348ff"><code>2a1e934</code></a>
server: after GracefulStop, ensure connections are closed when final RPC
comp...</li>
<li><a
href="e2d69aa076"><code>e2d69aa</code></a>
tests: fix spelling of variable (<a
href="https://redirect.github.com/grpc/grpc-go/issues/5966">#5966</a>)</li>
<li><a
href="a6376c9893"><code>a6376c9</code></a>
xds/resolver: cleanup tests to use real xDS client 3/n (<a
href="https://redirect.github.com/grpc/grpc-go/issues/5953">#5953</a>)</li>
<li><a
href="bf8fc46fa6"><code>bf8fc46</code></a>
xds/resolver: cleanup tests to use real xDS client 5/n (<a
href="https://redirect.github.com/grpc/grpc-go/issues/5955">#5955</a>)</li>
<li><a
href="3930549b38"><code>3930549</code></a>
resolver: replace resolver.Target.Endpoint field with Endpoint() method
(<a
href="https://redirect.github.com/grpc/grpc-go/issues/5852">#5852</a>)</li>
<li><a
href="894816c487"><code>894816c</code></a>
grpclb: rename <code>grpclbstate</code> package back to
<code>state</code> (<a
href="https://redirect.github.com/grpc/grpc-go/issues/5962">#5962</a>)</li>
<li><a
href="e5a0237a46"><code>e5a0237</code></a>
encoding: fix duplicate compressor names (<a
href="https://redirect.github.com/grpc/grpc-go/issues/5958">#5958</a>)</li>
<li><a
href="4adb2a7a00"><code>4adb2a7</code></a>
xds/resolver: cleanup tests to use real xDS client 2/n (<a
href="https://redirect.github.com/grpc/grpc-go/issues/5952">#5952</a>)</li>
<li><a
href="52a8392f37"><code>52a8392</code></a>
gcp/observability: update method name validation (<a
href="https://redirect.github.com/grpc/grpc-go/issues/5951">#5951</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/grpc/grpc-go/compare/v1.47.0...v1.53.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=google.golang.org/grpc&package-manager=go_modules&previous-version=1.47.0&new-version=1.53.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/xataio/pg-roll/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-06 09:16:11 +02:00
Andrew Farries
ac7a3d0a82
Qualify versioned schema names (#16)
Close https://github.com/xataio/pg-roll/issues/15.

Qualify versioned schema with the name of the schema they represent.

For a migration called `01_create_table` running in the `public` schema,
the versioned schema is called `public_01_create_table`.
2023-07-05 16:56:24 +01:00
Andrew Farries
7bcbee1256
Remove old schema version on pg-roll complete (#13)
Ensure that the previous version of the schema is removed by `pg-roll
complete`.
2023-07-05 13:58:55 +01:00
Carlos Pérez-Aradros Herce
5e61b040e1
Make migrations schema aware (#12)
This change will retrieve and store the resulting schema after a
migration is completed. This schema will be used as the base to execute
the next migration, making it possible to create views that are aware of
the full schema, and not only the one created by the last migration.

We use a function to retrieve the schema directly from Postgres instead
of building it from the migration files. This allows for more features
in the future, like doing an initial sync on top of the existing schema
or automatically detecting and storing out of band migrations from
triggers.

Example JSON stored schema:

```
{
  "tables": {
    "bills": {
      "oid": "18272",
      "name": "bills",
      "columns": {
        "id": {
          "name": "id",
          "type": "integer",
          "comment": null,
          "default": null,
          "nullable": false
        },
        "date": {
          "name": "date",
          "type": "time with time zone",
          "comment": null,
          "default": null,
          "nullable": false
        },
        "quantity": {
          "name": "quantity",
          "type": "integer",
          "comment": null,
          "default": null,
          "nullable": false
        }
      },
      "comment": null
    },
    "products": {
      "oid": "18286",
      "name": "products",
      "columns": {
        "id": {
          "name": "id",
          "type": "integer",
          "comment": null,
          "default": "nextval(_pgroll_new_products_id_seq::regclass)",
          "nullable": false
        },
        "name": {
          "name": "name",
          "type": "varchar(255)",
          "comment": null,
          "default": null,
          "nullable": false
        },
        "price": {
          "name": "price",
          "type": "numeric(10,2)",
          "comment": null,
          "default": null,
          "nullable": false
        }
      },
      "comment": null
    },
    "customers": {
      "oid": "18263",
      "name": "customers",
      "columns": {
        "id": {
          "name": "id",
          "type": "integer",
          "comment": null,
          "default": null,
          "nullable": false
        },
        "name": {
          "name": "name",
          "type": "varchar(255)",
          "comment": null,
          "default": null,
          "nullable": false
        },
        "credit_card": {
          "name": "credit_card",
          "type": "text",
          "comment": null,
          "default": null,
          "nullable": true
        }
      },
      "comment": null
    }
  }
}
```


After this change, I believe that the `create_table` operation is
feature complete and can be used for many sequential migrations.
2023-07-05 13:20:59 +02:00
Andrew Farries
69ab631485
Add a sentinel error for no active migration (#11)
Add a sentinel error `ErrNoActiveMigration` for the case where there is
no active migration. This improves the error strings presented to users
by not mentioning SQL errors.

**`pg-roll start` when there is a migration in progess:**
```
Error: a migration for schema "public" is already in progress 
```

**`pg-roll rollback` when there is no migration in progress:**
```
Error: unable to get active migration: no active migration 
```

**`pg-complete` when there is no active migration:**
```
Error: unable to get active migration: no active migration
```
2023-07-03 14:18:31 +01:00
Carlos Pérez-Aradros Herce
a8c4fddd14
Add migrations state handling (#7)
This migrations introduces state handling by creating a dedicated
`pgroll` schema (name configurable). We will store migrations there, as
well as their state. So we keep some useful information, ie the
migration definition (so we don't need it for the `complete` state).

Schema includes the proper constraints to guarantee that:
* Only a migration is active at a time
* Migration history is linear (all migrations have a unique parent,
except the first one which is NULL)
* We now the current migration at all times

Some helper functions are included:

* `is_active_migration_period()` will return true if there is an active
migration.
* `latest_version()` will return the name of the latest version of the
schema.
2023-06-28 11:10:03 +02:00
Andrew Farries
f9a530c900
Add test cleanup of Migrations value (#10)
Call its `Close` method via `t.Cleanup`.
2023-06-28 07:36:11 +01:00
Carlos Pérez-Aradros Herce
6c4748916c
Add linter to tests (#9)
Found some lint warnings, let's have them in CI
2023-06-27 16:33:50 +01:00
Carlos Pérez-Aradros Herce
838f8d4c46
Fix tests referencing from GitHub branch protections (#8)
Settings file was incorrectly referencing a non existing job
2023-06-27 13:46:36 +01:00
Andrew Farries
5f3094822e
Add a rollback command to the CLI (#6)
Add a `rollback` command to the CLI.

Use the rollback functionality added to the `migrations` package in #5
to perform the rollback.

Example:

```bash
go run . start examples/01_create_tables.json 
go run . rollback examples/01_create_tables.json 
```
The schema for the `01_create_table` version is removed from the
database along with the underlying tables.

⚠️ We currently don't have a way to ensure that only uncompleted
migrations can be rolled back. Once we have some state in the db
recording with migrations have been applied, we can revisit this command
to ensure completed migrations can't be rolled back ⚠️
2023-06-27 13:45:13 +01:00
Andrew Farries
b209d8c283
Implement the Rollback method for the create table operation (#5)
Implement rollbacks for the create table operation.

* Delete the new version of the schema and any views it contains.
* Drop the tables created by the operations.

Add an integration test to check that these resources are successfully
dropped.

This PR adds the rollback operation to the `migrations` package;
supporting the operation through the CLI will be in a later PR.
2023-06-27 13:42:04 +01:00
Carlos Pérez-Aradros Herce
5ad868af01
Add GitHub settings (#4)
I followed the conventions we have across the baord
2023-06-27 14:14:42 +02:00
Andrew Farries
3baf4f9e58
Merge pull request #3 from xataio/add-ci-workflow
Add a simple CI workflow
2023-06-27 08:47:50 +01:00
Andrew Farries
3f24fe0e89 Add a simple CI workflow 2023-06-26 15:37:43 +01:00
Andrew Farries
51ec2204c6
Merge pull request #2 from xataio/integration-tests
Add integration tests for the  `migrations` package using Testcontainers
2023-06-26 14:44:55 +01:00
Andrew Farries
20c57553b6 Add tests for create table operation 2023-06-26 12:48:00 +01:00
Andrew Farries
0a1fe86e0d
Merge pull request #1 from xataio/add-analyze-command
Add `analyze` as a hidden subcommand
2023-06-26 12:19:21 +01:00
Andrew Farries
2c6a6631fa Add analyze as a hidden subcommand 2023-06-23 18:43:59 +01:00
Carlos Pérez-Aradros Herce
bdaf08f54c Initial commit
Basic skeleton and simple op
2023-06-22 17:30:40 +02:00