On this page

Use MySQL and MariaDB

Use the exact mysql or mariadb dialect and the database/sql emitter. This example registers a boat once with INSERT IGNORE and checks whether a later registration was skipped.

Configure the connection and duplicate handling

Set dialect: mysql (or mariadb) and go.driver: database/sql in your database configuration. Open go-sql-driver/mysql with parseTime=true, for example app:secret@tcp(localhost:3306)/shop?parseTime=true, so temporal columns can scan into time.Time.

The migration makes the boat registration unique. Add the insert as execrows so the caller can distinguish insertion from skipping:

-- sgl.query(RegisterBoat, execrows)
INSERT IGNORE INTO boats (registration, name, kit) VALUES (?, ?, ?);

Check whether the registration was inserted

Run sgl generate, construct store.New(database), and inspect the affected-row count. Use the example caller for the surrounding registration loop and error handling:

	for _, boat := range boats {
		registered, err := queries.RegisterBoat(ctx, boat)
		if err != nil {
			return fmt.Errorf("registering %s: %w", boat.Name, err)
		}
		if registered == 0 {
			fmt.Fprintf(output, "INSERT IGNORE  %s is already registered, so %s was ignored\n", boat.Registration, boat.Name)
			continue
		}
		fmt.Fprintf(output, "INSERT IGNORE  registered %s as %s with kit %q\n", boat.Name, boat.Registration, boat.Kit)
	}

Use ON DUPLICATE KEY UPDATE when an existing row should change instead. MariaDB’s RETURNING support does not extend to MySQL; choose the command for your exact write form.

Check the MySQL write behaviour

From the Seagull repository root, run the dialect example:

cd examples/mysql/039_mysql_dialect_features
go test .

Set SGL_EXAMPLE_DSN to a disposable database before running this server-backed test; without it, the test skips. See running examples for connection setup.

The complete example produces:

INSERT IGNORE  registered Kittiwake as PZ1001 with kit "radar,radio,radar"
INSERT IGNORE  registered Salty Chip as PZ2002 with kit "liferaft"
INSERT IGNORE  PZ1001 is already registered, so Kittiwake II was ignored
INSERT IGNORE  registered Gull Wing as PZ3003 with kit "radio,sonar"
REPLACE INTO   berth 1 for PZ1001, rows affected: 1
REPLACE INTO   berth 2 for PZ2002, rows affected: 1
REPLACE INTO   berth 1 for PZ2002, rows affected: 3
  berth 1 (uint8): Salty Chip
FIND_IN_SET    Kittiwake has a radio among "radio,radar"
FIND_IN_SET    Gull Wing has a radio among "radio"
GROUP_CONCAT   PZ1001 Kittiwake  crossings 2 (uint32), crew: Morwenna the skipper, Jago the deckhand
GROUP_CONCAT   PZ2002 Salty Chip crossings 0 (uint32), crew: no crew
GROUP_CONCAT   PZ3003 Gull Wing  crossings 1 (uint32), crew: Kerensa the skipper

Match SQL mode and transaction semantics

In the default SQL mode, double quotes delimit strings and || is logical OR. Use CONCAT for concatenation. If the server enables ANSI_QUOTES, set dialect_options.ansi_quotes: true so generation and migration splitting agree with it.

MySQL and MariaDB DDL may commit implicitly. Keep migration recovery separate from transaction rollback, and preserve the dialect’s DELIMITER handling for procedural bodies.

See the dialects/mysql reference for the complete contract. The example browser exposes other engine variants; use their actual SQL rather than changing only the dialect name.

Examples for this page