Siirry sisältöön

Rivi-identiteetti

Rivi-identiteetti määrittää, miten merql yhdistää rivit tilannevedosten välillä. Kun base-tilannetta verrataan ours-tilanteeseen, sen on tiedettävä, että basen rivi X vastaa samaa loogista riviä kuin rivi Y ours-tilanteessa, vaikka joidenkin sarakkeiden arvot olisivat muuttuneet. Identiteettisääntö määrittää, mitkä sarakkeet muodostavat rivitunnisteen.

PHP
use Merql\Identity\PrimaryKeyIdentity;

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

RowIdentity-rajapinta

Kaikki identiteettistrategiat toteuttavat kaksi metodia:

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

key() muodostaa rivin tiedoista yksilöllisen merkkijonotunnisteen. columns() palauttaa identiteetissä käytettävien sarakkeiden nimet.

PrimaryKeyIdentity

Oletusstrategia. Yhdistää rivit niiden pääavainsarakkeiden perusteella.

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)

Tätä merql käyttää oletusarvoisesti, kun taulun skeemassa on määritetty pääavain.

NaturalKeyIdentity

Tauluille, joilla ei ole automaattisesti kasvavaa pääavainta, yhdistää rivit yksilöllisen rajoitteen sarakkeiden perusteella. Hyödyllinen, kun PK on UUID tai kun taulu käyttää yhdistelmällistä yksilöllistä rajoitetta loogisena identiteettinään.

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

Vararatkaisu tauluille, joilla ei ole pääavainta eikä yksilöllisiä rajoitteita. Laskee SHA-256-tiivisteen kaikkien sarakkeiden arvoista. Kaksi riviä ovat samoja, jos kaikki sarakkeet täsmäävät.

PHP
use Merql\Identity\ContentHashIdentity;

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

Sisältötiivisteeseen perustuvalla identiteetillä on rajoitus: jos rivin sisältö muuttuu, myös sen tiiviste muuttuu. Siksi rivi näkyy vanhan tiivisteen poistona ja uuden tiivisteen lisäyksenä päivityksen sijaan. Tämä on väistämätön kompromissi, kun vakaita identiteettisarakkeita ei ole.

IdentityRule

IdentityRule on sarjoitettava identiteettimääritys, jota tilannevedosten tallennus ja yhdistämissuunnitelmat käyttävät.

PHP
use Merql\Identity\IdentityRule;

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

Sääntötyypit:

Tyyppi Merkitys
primary Tietokannan pääavainsarakkeet
natural Vakaat yksilölliset liiketoimintasarakkeet
composite Yhdistelmälliset loogisen identiteetin sarakkeet
content Sisältötiivisteeseen perustuva vararatkaisu

IdentityRule::forSchema($schema) ratkaisee oletussäännön:

  1. Jos taululla on pääavain, käytetään sen sarakkeita.
  2. Jos taululla on yksilöllisiä avaimia, käytetään ensimmäisen yksilöllisen avaimen sarakkeita.
  3. Jos kumpaakaan ei ole, käytetään kaikkia sarakkeita (sisältötiivisteeseen perustuva vararatkaisu).

IdentityRuleSet

Käytä metodia IdentityRuleSet, kun isäntäsovellus tuntee skeeman oletusta paremman identiteettisäännön.

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 ratkaisee jokaiselle tallennetulle taululle IdentityRule-arvon. Valitut sarakkeet tallennetaan kohteeseen TableSnapshot::identityColumns, ja niitä käytetään kaikissa myöhemmissä erovertailuissa, yhdistämisissä, suunnitelmissa, SQL-toiminnoissa ja palautuksissa.

Merql::init() voi saada saman sääntöjoukon, kun käytetään staattista julkisivua:

PHP
use Merql\Merql;

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

Sääntöjoukot sarjoitetaan vakaasti taulukkomuodossa:

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

Moniselitteinen identiteetti

Jos kahdella tallennetulla rivillä on sama identiteettiavain, tallennus epäonnistuu sen sijaan, että toinen rivi korvaisi toisen.

PHP
use Merql\Exceptions\SnapshotException;

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

Isäntäsovellukset voivat tarkistaa raakarivien moniselitteisyyden etukäteen metodilla IdentityRuleSet::conflictsFor(), jotta siitä voidaan ilmoittaa ennen tallennusta:

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

WordPress-metatauluissa ryhmittelyyn ja näyttämiseen on yleensä hyödyllistä käyttää arvoa post_id + meta_key, mutta se ei sovi rivin identiteetiksi, koska päällekkäiset meta-avaimet ovat sallittuja. Käytä rivin identiteettinä taulun pääavainta, ellei isäntäsovellus pysty varmistamaan, että luonnollinen avain on yksilöllinen.

Rivitunnisteen koodaus

Rivitunnisteet ovat koodattuja merkkijonoja, joissa useita sarakearvoja yhdistää yksikköerotin (\x1F). Erottimen tai prosenttimerkin sisältävät arvot suojataan yhteentörmäysten estämiseksi:

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']

Suojaussäännöt:

Alkuperäinen Suojattu
% %25
\x1F (yksikköerotin) %1F

Näin varmistetaan, ettei arvon \x1F sisältävä arvo jakaudu useaksi avaimen osaksi. Koodaus on deterministinen ja palautettavissa alkuperäiseen muotoon.

Automaattisesti kasvavien tunnisteiden eriytyminen

Kun molemmat puolet lisäävät uusia rivejä, automaattisesti kasvavat tunnisteet eroavat haarojen välillä. Ours-puolen rivi #100 voi olla täysin eri tietue kuin theirs-puolen rivi #100.

merql käsittelee tämän yhdistämällä rivit pääavaimen perusteella. Jos molemmat puolet lisäävät rivin samalla automaattisesti kasvavalla tunnisteella, se merkitään insert_insert-ristiriidaksi. Käytä tämän välttämiseksi luonnollisia avaimia (yksilöllisiä sarakkeita, jotka pysyvät samoina haarojen välillä) tauluissa, joihin odotetaan samanaikaisia lisäyksiä.

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

Identiteetti tilannevedoksissa

Tallennuksen aikana valitut identiteettisarakkeet tallennetaan kuhunkin TableSnapshot-kohteeseen:

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

SqlGenerator käyttää näitä sarakkeita UPDATE- ja DELETE-lauseiden WHERE-ehtojen muodostamiseen. Yhdistämissuunnitelmat puolestaan näyttävät niiden dekoodatut identiteettiarvot tarkastelua, valintaa, ehdollista käyttöönottoa ja palautusta varten.