\Drupal\strata\Restore\Plugin\Strata\Restore ShadowSwapStrategy

Builds the new contents in a shadow table and renames it into place.

The original stays readable and complete until the instant of the swap, so a site can restore one table without going into maintenance mode. That is the whole reason this exists next to the truncate strategy, which is simpler and works everywhere.

It is only atomic where the driver can rename two tables in one statement. MySQL's RENAME TABLE a TO a_old, b TO a is one operation with no window in which the name is unbound. PostgreSQL's ALTER TABLE ... RENAME is per-table, but two of them inside a transaction commit together, which gives the same guarantee. SQLite can rename a table and cannot do either atomically, so a reader can find the name missing between the two statements.

On SQLite it refuses rather than degrading. A strategy that quietly fell back to truncating would give an operator the swap's promise and the truncate's behaviour, and the one moment that matters is the moment they were relying on the promise.

Summary

Methods
Properties
Constants
id
label
describe
isSupported
unsupportedReason
restore
shadowName
retiredName
No public properties found
BATCH
SUPPORTED_DRIVERS
No protected methods found
No protected properties found
No protected constants found
fill
swap
drop
driver
No private properties found
No private constants found

Constant

BATCH

BATCH = 500

How many rows are inserted per statement.

SUPPORTED_DRIVERS

SUPPORTED_DRIVERS = ['mysql', 'pgsql']

Drivers whose rename is atomic enough for this.

Methods

id()

id() : string

A short lowercase identifier.

Returns

string —

For example "truncate" or "shadow_swap".

label()

label() : string

A human label for the confirm form.

Returns

string —

The label.

describe()

describe() : string

What this strategy costs the site while it runs.

Returns

string —

One sentence.

isSupported()

isSupported(\Drupal\Core\Database\Connection  $database) : bool

Whether this strategy can run on a connection.

Parameters

\Drupal\Core\Database\Connection $database

The connection.

Returns

bool —

TRUE when the driver supports what the strategy needs.

unsupportedReason()

unsupportedReason(\Drupal\Core\Database\Connection  $database) : string|null

Why the strategy cannot run here.

Parameters

\Drupal\Core\Database\Connection $database

The connection.

Returns

string|null —

The reason, or NULL when it is supported.

restore()

restore(\Drupal\Core\Database\Connection  $database, string  $table, array  $rows, array  $columns) : int

Replaces a table's contents.

Parameters

\Drupal\Core\Database\Connection $database

The connection.

string $table

The table to replace.

array $rows

The rows to leave in it. An empty list empties the table, which is a legitimate restore target and is why this does not treat it as a mistake.

array $columns

The columns to write, in order. Given explicitly so a row carrying a column the table no longer has is refused rather than silently dropped.

Returns

int —

How many rows the table now holds.

shadowName()

shadowName(string  $table) : string

The name the new contents are built under.

Parameters

string $table

The table being restored.

Returns

string —

The shadow name.

retiredName()

retiredName(string  $table) : string

The name the old contents are moved aside to.

Kept until the swap succeeds and dropped afterwards, so a failed swap has something to put back rather than nothing.

Parameters

string $table

The table being restored.

Returns

string —

The retired name.

fill()

fill(\Drupal\Core\Database\Connection  $database, string  $table, string  $shadow, list>  $rows, list  $columns) : int

Copies the table's structure and fills it with the new rows.

The structure is copied by the database rather than described by Strata, so every index, default and constraint comes across without this class having to understand the schema.

Parameters

\Drupal\Core\Database\Connection $database

The connection.

string $table

The original table.

string $shadow

The shadow table to create.

list> $rows

The rows to write.

list $columns

The columns to write.

Throws

\RuntimeException

When a row does not carry every column.

Returns

int —

How many rows were written.

swap()

swap(\Drupal\Core\Database\Connection  $database, string  $table, string  $shadow, string  $retired) : void

Moves the shadow into place.

Parameters

\Drupal\Core\Database\Connection $database

The connection.

string $table

The original name.

string $shadow

The shadow holding the new contents.

string $retired

Where the old contents go.

Returns

void —

drop()

drop(\Drupal\Core\Database\Connection  $database, string  $table) : void

Drops a table if it is there.

Parameters

\Drupal\Core\Database\Connection $database

The connection.

string $table

The table name.

Returns

void —

driver()

driver(\Drupal\Core\Database\Connection  $database) : string

The connection's driver name.

Parameters

\Drupal\Core\Database\Connection $database

The connection.

Returns

string —

The driver, lowercased.