Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,17 @@ jobs:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: "1.25.x"
go-version: "1.26.x"
- name: golangci-lint
uses: golangci/golangci-lint-action@v9
with:
version: v2.6.2
version: v2.11.3

test:
runs-on: ubuntu-latest
strategy:
matrix:
go: ["1.24.x", "1.25.x"]
go: ["1.25.x", "1.26.x"]
steps:
- uses: actions/checkout@v4

Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
SOURCE ?= file go_bindata github github_ee bitbucket aws_s3 google_cloud_storage godoc_vfs gitlab
DATABASE ?= postgres mysql redshift cassandra spanner cockroachdb yugabytedb clickhouse mongodb sqlserver firebird neo4j pgx pgx5 rqlite
DATABASE ?= postgres mysql redshift cassandra spanner cockroachdb yugabytedb clickhouse mongodb sqlserver firebird neo4j pgx pgx5 rqlite hana
DATABASE_TEST ?= $(DATABASE) sqlite sqlite3 sqlcipher
VERSION ?= $(shell git describe --tags 2>/dev/null | cut -c 2-)
TEST_FLAGS ?=
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
[![Coverage Status](https://img.shields.io/coveralls/github/golang-migrate/migrate/master.svg)](https://coveralls.io/github/golang-migrate/migrate?branch=master)
[![packagecloud.io](https://img.shields.io/badge/deb-packagecloud.io-844fec.svg)](https://packagecloud.io/golang-migrate/migrate?filter=debs)
[![Docker Pulls](https://img.shields.io/docker/pulls/migrate/migrate.svg)](https://hub.docker.com/r/migrate/migrate/)
![Supported Go Versions](https://img.shields.io/badge/Go-1.24%2C%201.25-lightgrey.svg)
![Supported Go Versions](https://img.shields.io/badge/Go-1.25%2C%201.26-lightgrey.svg)
[![GitHub Release](https://img.shields.io/github/release/golang-migrate/migrate.svg)](https://github.com/golang-migrate/migrate/releases)
[![Go Report Card](https://goreportcard.com/badge/github.com/golang-migrate/migrate/v4)](https://goreportcard.com/report/github.com/golang-migrate/migrate/v4)

Expand Down
74 changes: 74 additions & 0 deletions database/hana/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# SAP HANA

`hdb://user:password@host:port?TLSServerName=host&x-migrations-schema=MYSCHEMA`

## URL Parameters

| URL Query | WithInstance Config | Description |
| ----------------------------- | ------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `x-migrations-schema` | `SchemaName` | **Required.** The schema in which the migrations table is created and migrations are applied. |
| `x-migrations-table` | `MigrationsTable` | Name of the migrations table (default: `schema_migrations`). |
| `x-statement-timeout` | `StatementTimeout` | Abort any statement that takes longer than this duration. Go duration format (e.g. `30s`, `1m`, `500ms`). Applied per-statement, not per-migration. |
| `x-isolation-level` | `IsolationLevel` | Transaction isolation level as integer corresponding to [`sql.IsolationLevel`](https://pkg.go.dev/database/sql#IsolationLevel) (default: `0` = driver default). |
| `x-lock-name` | `LockName` | Name of the distributed application lock used to prevent concurrent migrations (default: `migrate`). |
| `x-lock-timeout` | `LockTimeout` | How long to wait for the lock. Go duration format (e.g. `5s`, `30s`). `0` = no wait, error immediately if locked (default: `0`). |
| `x-multi-statement-delimiter` | `MultiStatementDelimiter` | Delimiter for splitting migration files into multiple statements (default: `;`). |

## Multi-Statement Migrations

Migration files are automatically split by the configured delimiter (default `;`) and each statement is executed separately within a single transaction. This means:

- All statements in a migration file are wrapped in a single transaction for atomicity.
- If any statement fails, all previous DML statements in the same migration are rolled back.
- DDL statements (e.g. `CREATE TABLE`) auto-commit in HANA regardless of transaction boundaries.
- Empty statements (e.g. trailing delimiters, multiple consecutive delimiters) are silently skipped.

### Example with default delimiter (`;`)

```sql
CREATE ROW TABLE users (id INTEGER PRIMARY KEY);
CREATE ROW TABLE orders (id INTEGER PRIMARY KEY, user_id INTEGER);
CREATE INDEX idx_orders_user ON orders (user_id);
```

### Example with custom delimiter (`--SPLIT--`)

Set `x-multi-statement-delimiter=--SPLIT--` in the URL:

```sql
CREATE ROW TABLE users (id INTEGER PRIMARY KEY)
--SPLIT--
CREATE ROW TABLE orders (id INTEGER PRIMARY KEY, user_id INTEGER)
--SPLIT--
CREATE INDEX idx_orders_user ON orders (user_id)
```

## Locking

This driver uses SAP HANA's `APPLICATION_LOCK` for distributed locking. This prevents multiple processes from running migrations simultaneously.

## Usage with `WithInstance`

```go
import "github.com/golang-migrate/migrate/v4/database/hana"

db := sql.OpenDB(connector) // your pre-configured *sql.DB

driver, err := hana.WithInstance(db, &hana.Config{
SchemaName: "MY_SCHEMA", // required
MigrationsTable: "schema_migrations",
StatementTimeout: 30 * time.Second,
IsolationLevel: sql.LevelReadCommitted,
LockName: "my-app-migrate",
LockTimeout: 5 * time.Second,
MultiStatementDelimiter: ";",
})
```

## Considerations for future improvements

### Configurable Transaction Timeouts

Transactions are used where applicable to wrap multiple statements.
Currently such transactions do not use timeouts.
If required we will consider supporting configurable transaction timeouts.
1 change: 1 addition & 0 deletions database/hana/examples/migrations/1_init.down.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DROP TABLE TEST;
4 changes: 4 additions & 0 deletions database/hana/examples/migrations/1_init.up.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
CREATE ROW TABLE TEST (
id INTEGER PRIMARY KEY,
name NVARCHAR(255) NOT NULL
);
8 changes: 8 additions & 0 deletions database/hana/examples/migrations_multi/1_multi.up.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@

CREATE ROW TABLE MULTI_A (id INTEGER PRIMARY KEY);CREATE ROW TABLE MULTI_B (id INTEGER PRIMARY KEY);;;;


CREATE ROW TABLE MULTI_C (id INTEGER PRIMARY KEY);



Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
CREATE ROW TABLE ROLLBACK_TEST (id INTEGER PRIMARY KEY);
3 changes: 3 additions & 0 deletions database/hana/examples/migrations_rollback/2_rollback.up.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
INSERT INTO ROLLBACK_TEST VALUES (1);
INSERT INTO ROLLBACK_TEST VALUES (2);
INSERT INTO ROLLBACK_TEST VALUES (1);
6 changes: 6 additions & 0 deletions database/hana/examples/migrations_split/1_split.up.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
CREATE ROW TABLE SPLIT_A (id INTEGER PRIMARY KEY);--SPLIT--
CREATE ROW TABLE SPLIT_B (id INTEGER PRIMARY KEY)
--SPLIT----SPLIT----SPLIT--


CREATE ROW TABLE SPLIT_C (id INTEGER PRIMARY KEY)
Loading
Loading