Pāriet uz saturu

Rindu identitāte

Rindas identitāte nosaka, kā merql sasaista rindas dažādos momentuzņēmumos. Salīdzinot pamatmomentuzņēmumu ar mūsu momentuzņēmumu, tam jāzina, ka rinda X pamatmomentuzņēmumā ir tā pati loģiskā rinda, kas rinda Y mūsu momentuzņēmumā, pat ja dažas kolonnu vērtības ir mainījušās. Identitātes noteikums nosaka, kuras kolonnas veido rindas atslēgu.

PHP
use Merql\Identity\PrimaryKeyIdentity;

$identity = new PrimaryKeyIdentity(['id']);
$key = $identity->key(['id' => 42, 'title' => 'Hello']);
// "42"

RowIdentity saskarne

Katra identitātes stratēģija īsteno divas metodes:

PHP
interface RowIdentity
{
    public function key(array $row): string;
    public function columns(): array;
}

key() izveido unikālu virknes identifikatoru no rindas datiem. columns() atgriež identitātei izmantoto kolonnu nosaukumus.

PrimaryKeyIdentity

Noklusējuma stratēģija. Sasaista rindas pēc to primārās atslēgas kolonnām.

PHP
use Merql\Identity\PrimaryKeyIdentity;

// Single-column PK.
$identity = new PrimaryKeyIdentity(['id']);
$key = $identity->key(['id' => 42, 'title' => 'Hello']);
// "42"

// Composite PK.
$identity = new PrimaryKeyIdentity(['tenant_id', 'user_id']);
$key = $identity->key(['tenant_id' => 1, 'user_id' => 99, 'name' => 'Alice']);
// "1\x1F99" (unit separator between parts)

Šo stratēģiju merql izmanto pēc noklusējuma, ja tabulas shēmā ir definēta primārā atslēga.

NaturalKeyIdentity

Tabulām bez automātiski pieaugošas primārās atslēgas sasaista rindas pēc unikālo ierobežojumu kolonnām. Noder, ja PK ir UUID vai tabulas loģisko identitāti veido salikts unikālais ierobežojums.

PHP
use Merql\Identity\NaturalKeyIdentity;

$identity = new NaturalKeyIdentity(['email']);
$key = $identity->key(['id' => 1, 'email' => 'alice@example.com', 'name' => 'Alice']);
// "alice@example.com"

$identity = new NaturalKeyIdentity(['country', 'postal_code']);
$key = $identity->key(['country' => 'US', 'postal_code' => '90210', 'city' => 'Beverly Hills']);
// "US\x1F90210"

ContentHashIdentity

Rezerves variants tabulām bez primārās atslēgas un unikāliem ierobežojumiem. Aprēķina visu kolonnu vērtību SHA-256 jaucējkodu. Divas rindas ir vienādas, ja sakrīt visas kolonnas.

PHP
use Merql\Identity\ContentHashIdentity;

$identity = new ContentHashIdentity(['name', 'value']);
$key = $identity->key(['name' => 'color', 'value' => 'blue']);
// "a3f2..." (SHA-256 hash)

Satura jaucējkoda identitātei ir ierobežojums: ja mainās rindas saturs, mainās arī tās jaucējkods, tāpēc rinda tiek uzskatīta par vecā jaucējkoda ieraksta dzēšanu un jaunā jaucējkoda ieraksta pievienošanu, nevis atjaunināšanu. Tas ir neizbēgams kompromiss, ja nav stabilu identitātes kolonnu.

IdentityRule

IdentityRule ir serializējama identitātes konfigurācija, ko izmanto momentuzņēmumu uztveršana un apvienošanas plāni.

PHP
use Merql\Identity\IdentityRule;

$rule = IdentityRule::natural(['option_name']);
$key = $rule->key(['option_name' => 'siteurl']);
// "siteurl"

Noteikumu veidi:

Veids Nozīme
primary Datubāzes primārās atslēgas kolonnas
natural Stabilas unikālas biznesa kolonnas
composite Saliktas loģiskās identitātes kolonnas
content Satura jaucējkoda rezerves variants

IdentityRule::forSchema($schema) atrisina noklusējuma noteikumu:

  1. Ja tabulai ir primārā atslēga, izmantojiet tās kolonnas.
  2. Ja tabulai ir unikālās atslēgas, izmantojiet pirmās unikālās atslēgas kolonnas.
  3. Ja nav ne viena, ne otra, izmantojiet visas kolonnas (satura jaucējkoda rezerves variants).

IdentityRuleSet

Izmantojiet IdentityRuleSet, ja resursdatora lietotnei ir zināms labāks identitātes noteikums nekā shēmas noklusējuma iestatījumam.

PHP
use Merql\Identity\IdentityRule;
use Merql\Identity\IdentityRuleSet;
use Merql\Snapshot\Snapshotter;

$rules = new IdentityRuleSet([
    'wp_options' => IdentityRule::natural(['option_name']),
    'wp_term_relationships' => IdentityRule::composite(['object_id', 'term_taxonomy_id']),
]);

$snapshotter = new Snapshotter($connection, identityRules: $rules);
$snapshot = $snapshotter->capture('live', ['wp_options', 'wp_term_relationships']);

Snapshotter katrai tvertajai tabulai nosaka IdentityRule. Izvēlētās kolonnas tiek saglabātas TableSnapshot::identityColumns un izmantotas visās turpmākajās diff, merge, plan, SQL un rollback darbībās.

Izmantojot statisko fasādi, Merql::init() var saņemt to pašu noteikumu kopu:

PHP
use Merql\Merql;

Merql::init($connection, identityRules: $rules);
Merql::snapshot('live', ['wp_options']);

Noteikumu kopām ir stabila masīva serializācija:

PHP
$payload = $rules->toArray();
$rules = IdentityRuleSet::fromArray($payload);

Neskaidra identitāte

Ja divām tvertajām rindām ir viena un tā pati identitātes atslēga, tveršana neizdodas, nevis pārraksta vienu rindu ar otru.

PHP
use Merql\Exceptions\SnapshotException;

try {
    $snapshotter->capture('live', ['wp_postmeta']);
} catch (SnapshotException $e) {
    // The configured identity rule matched multiple rows.
}

Resursdatora lietotnes var iepriekš pārbaudīt neapstrādātas rindas ar IdentityRuleSet::conflictsFor(), ja vēlas ziņot par neskaidrību pirms tveršanas:

PHP
$conflicts = $rules->conflictsFor(
    'wp_postmeta',
    IdentityRule::natural(['post_id', 'meta_key']),
    $rows,
);

WordPress meta tabulām post_id + meta_key parasti noder grupēšanai un attēlošanai, bet nav droša rindas identitāte, jo dublētas meta atslēgas ir pieļaujamas. Rindas identitātei izmantojiet tabulas primāro atslēgu, ja vien resursdatora lietotne nevar pierādīt, ka dabiskā atslēga ir unikāla.

Rindas atslēgas kodējums

Rindu atslēgas ir kodētas virknes, kurās apvienotas vairāku kolonnu vērtības, izmantojot vienības atdalītāju (\x1F). Vērtības, kurās ir atdalītājs vai procenta zīme, tiek aizvietotas, lai novērstu sadursmes:

PHP
use Merql\Snapshot\Snapshotter;

// Encode.
$key = Snapshotter::buildRowKey(
    ['tenant_id' => '1', 'user_id' => '99'],
    ['tenant_id', 'user_id'],
);
// "1\x1F99"

// Decode.
$parts = Snapshotter::decodeRowKey($key);
// ['1', '99']

Aizvietošanas noteikumi:

Sākotnējā vērtība Aizvietotā vērtība
% %25
\x1F (vienības atdalītājs) %1F

Tas nodrošina, ka vērtība, kurā ir \x1F, netiek sadalīta vairākās atslēgas daļās. Kodējums ir deterministisks un atgriezenisks.

Automātiskās numerācijas atšķirības

Kad abas puses ievieto jaunas rindas, automātiski pieaugošie ID dažādos atzaros atšķirsies. Rinda #100 mūsu pusē var būt pavisam cits ieraksts nekā rinda #100 viņu pusē.

merql to risina, sasaistot rindas pēc primārās atslēgas. Ja abas puses ievietoja rindu ar vienādu automātiski pieaugošo ID, tā tiek atzīmēta kā insert_insert konflikts. Lai no tā izvairītos, tabulām, kurās gaidāma vienlaicīga ievietošana, izmantojiet dabiskās atslēgas (unikālas kolonnas, kas ir stabilas dažādos atzaros).

PHP
// A natural key on (slug) avoids auto-increment collisions.
$identity = new NaturalKeyIdentity(['slug']);

Identitāte momentuzņēmumos

Tveršanas laikā izvēlētās identitātes kolonnas tiek saglabātas kopā ar katru TableSnapshot:

PHP
$tableSnapshot = $snapshot->getTable('posts');
$tableSnapshot->identityColumns;
// ['id']

Šīs kolonnas SqlGenerator izmanto WHERE klauzulu veidošanai UPDATE un DELETE priekšrakstos, bet apvienošanas plāni — atkodēto identitātes vērtību parādīšanai pārskatīšanai, atlasei, kontrolētai piemērošanai un atcelšanai.