Rea identiteet
Rea identiteet määrab, kuidas merql sobitab ridu eri hetktõmmiste vahel. Aluse võrdlemisel meie omaga peab see teadma, et aluse rida X on meie omas sama loogiline rida Y, isegi kui mõne veeru väärtus muutus. Identiteedireegel määrab, millistest veergudest reavõti moodustatakse.
use Merql\Identity\PrimaryKeyIdentity;
$identity = new PrimaryKeyIdentity(['id']);
$key = $identity->key(['id' => 42, 'title' => 'Hello']);
// "42"
RowIdentity liides
Kõik identiteedistrateegiad rakendavad kahte meetodit:
interface RowIdentity
{
public function key(array $row): string;
public function columns(): array;
}
key() loob rea andmetest kordumatu string-tunnuse. columns() tagastab identiteedi jaoks kasutatavate veergude nimed.
PrimaryKeyIdentity
Vaikimisi strateegia. Sobitab ridu nende primaarvõtme veergude järgi.
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)
Seda kasutab merql vaikimisi, kui tabeli skeemis on määratud primaarvõti.
NaturalKeyIdentity
Tabelite puhul, millel puudub automaatselt suurenev primaarvõti, sobitatakse read kordumatu piirangu veergude järgi. Kasulik, kui PK on UUID või kui tabeli loogiline identiteet põhineb liitkordumatul piirangul.
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
Varuvariant tabelitele, millel pole primaarvõtit ega kordumatuid piiranguid. Arvutab kõigi veeruväärtuste põhjal SHA-256 räsi. Kaks rida on samad, kui kõik nende veerud kattuvad.
use Merql\Identity\ContentHashIdentity;
$identity = new ContentHashIdentity(['name', 'value']);
$key = $identity->key(['name' => 'color', 'value' => 'blue']);
// "a3f2..." (SHA-256 hash)
Sisu räsil põhineval identiteedil on üks piirang: kui rea sisu muutub, muutub ka selle räsi. Seetõttu näib rida vana räsi kustutamise ja uue räsi lisamisena, mitte uuendusena. See on vältimatu kompromiss, kui püsivad identiteediveerud puuduvad.
IdentityRule
IdentityRule on serialiseeritav identiteedi konfiguratsioon, mida kasutavad hetktõmmise jäädvustamine ja ühendamisplaanid.
use Merql\Identity\IdentityRule;
$rule = IdentityRule::natural(['option_name']);
$key = $rule->key(['option_name' => 'siteurl']);
// "siteurl"
Reeglitüübid:
| Tüüp | Tähendus |
|---|---|
primary |
Andmebaasi primaarvõtme veerud |
natural |
Püsivad kordumatud äriveerud |
composite |
Liitloogilise identiteedi veerud |
content |
Sisu räsil põhinev varuvariant |
IdentityRule::forSchema($schema) lahendab vaike-reegli järgmiselt:
- Kui tabelil on primaarvõti, kasuta selle veerge.
- Kui tabelil on kordumatud võtmed, kasuta esimese sellise võtme veerge.
- Kui kumbagi pole, kasuta kõiki veerge (sisu räsil põhinev varuvariant).
IdentityRuleSet
Kasuta IdentityRuleSet, kui hostrakendus teab skeemi vaikeväärtusest paremat identiteedireeglit.
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 lahendab iga jäädvustatud tabeli jaoks IdentityRule. Valitud veerud salvestatakse asukohta TableSnapshot::identityColumns ning neid kasutatakse kõigis järgnevates erinevuste leidmise, ühendamise, plaani, SQL ja tagasipööramise toimingutes.
Merql::init() saab staatilise fassaadi kasutamisel sama reeglistiku:
use Merql\Merql;
Merql::init($connection, identityRules: $rules);
Merql::snapshot('live', ['wp_options']);
Reeglistikud serialiseeritakse stabiilse massiivina:
$payload = $rules->toArray();
$rules = IdentityRuleSet::fromArray($payload);
Mitmetähenduslik identiteet
Kui kaks jäädvustatud rida annavad sama identiteedivõtme, jäädvustamine nurjub, selle asemel et üks rida teisega üle kirjutada.
use Merql\Exceptions\SnapshotException;
try {
$snapshotter->capture('live', ['wp_postmeta']);
} catch (SnapshotException $e) {
// The configured identity rule matched multiple rows.
}
Hostrakendused saavad enne jäädvustamist kontrollida töötlemata ridu meetodiga IdentityRuleSet::conflictsFor(), et tuvastada mitmetähenduslikkus:
$conflicts = $rules->conflictsFor(
'wp_postmeta',
IdentityRule::natural(['post_id', 'meta_key']),
$rows,
);
WordPress meta-tabelite puhul on post_id + meta_key tavaliselt kasulik rühmitamiseks ja kuvamiseks, kuid rea identiteedina pole see ohutu, sest korduvad metavõtmed on lubatud. Kasuta rea identiteediks tabeli primaarvõtit, välja arvatud juhul, kui hostrakendus suudab tõestada loomuliku võtme kordumatust.
Reavõtme kodeerimine
Reavõtmed on kodeeritud stringid, mis ühendavad mitme veeru väärtused ühikueraldajaga (\x1F). Eraldajat või protsendimärki sisaldavad väärtused paokodeeritakse kokkupõrgete vältimiseks:
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']
Paokodeerimise reeglid:
| Algne | Paokodeeritud |
|---|---|
% |
%25 |
\x1F (ühikueraldaja) |
%1F |
See tagab, et \x1F sisaldav väärtus ei jagune mitmeks võtmeosaks. Kodeering on deterministlik ja pööratav.
Automaatse suurenemise lahknevus
Kui mõlemad harud lisavad uusi ridu, erinevad automaatselt suurenevad ID-d harude vahel. Rida #100 meie harus võib olla täiesti erinev kirje kui rida #100 nende harus.
merql lahendab selle primaarvõtme järgi sobitamisega. Kui mõlemad pooled lisavad sama automaatselt suureneva ID-ga rea, märgitakse see insert_insert konfliktina. Selle vältimiseks kasuta tabelites, kuhu eeldatavasti lisatakse kirjeid samal ajal, loomulikke võtmeid (kordumatuid veerge, mis püsivad harude vahel samad).
// A natural key on (slug) avoids auto-increment collisions.
$identity = new NaturalKeyIdentity(['slug']);
Identiteet hetktõmmistes
Jäädvustamisel valitud identiteediveerud salvestatakse iga TableSnapshot juurde:
$tableSnapshot = $snapshot->getTable('posts');
$tableSnapshot->identityColumns;
// ['id']
SqlGenerator kasutab neid veerge lausete UPDATE ja DELETE tingimuste WHERE koostamiseks; ühendamisplaanid kasutavad neid dekodeeritud identiteediväärtuste esitamiseks ülevaatuseks, valikuks, kaitstud rakendamiseks ja tagasipööramiseks.