Gå til indhold

SQL-spejl

SqlMirror flytter storh-samlinger til SQLite- eller MySQL-tabeller, så du kan køre joins, sortere på tværs af tabeller, søge efter delstrenge og lave rapporter i SQL, mens filerne forbliver kanoniske. Tænk på det som et sekundært indeks, der tilfældigvis er en database: spejlet er afledt, kan kasseres og kan genopbygges når som helst. ext-pdo med driveren sqlite eller mysql kræves kun, når du bruger funktionen; kernepakken forbliver uden afhængigheder.

Opsætning

PHP
use Storh\DocStore;
use Storh\Schema;
use Storh\SqlMirror;

$schema = Schema::collection('pages')
    ->string('slug')->unique()
    ->string('kind')->index()
    ->int('publishedAt')->range();

$pages  = new DocStore($root, 'pages', schema: $schema);
$events = new Storh\SegmentedLog($root, 'events');

$mirror = new SqlMirror(new PDO('sqlite:' . $root . '/mirror.db'), 'app_');
$mirror->collection($pages, 'pages', $schema);
$mirror->collection($events, 'events');

$mirror->install();
$mirror->push();

Begge motorer kan spejles: DocStore-samlinger og SegmentedLog-streams (kun aktive poster flyttes). Det er valgfrit at angive en Schema og uafhængigt af lageret: erklærede felter af typen string/int/float/bool bliver typede, indekserede kolonner; alt andet kan fortsat forespørges i data-kolonnen JSON. Felter af typen mixed kan ikke markeres til indeksering.

Forbindelser

Konstruktøren accepterer et PDO-håndtag (driveren sqlite eller mysql, registreres automatisk), et mysqli-håndtag eller enhver implementering af SqlMirrorConnection:

PHP
$mirror = new SqlMirror(new PDO('sqlite:' . $root . '/mirror.db'));
$mirror = new SqlMirror(new PDO('mysql:host=127.0.0.1;dbname=app;charset=utf8mb4', $user, $password));
$mirror = new SqlMirror(new mysqli('127.0.0.1', $user, $password, 'app'), 'wp_storh_');

mysqli-stien fungerer med begge mysqli-fejlrapporteringsindstillinger, så et eksisterende håndtag fra et værtsprogram (for eksempel WordPresss $wpdb->dbh) kan genbruges direkte. Adfærden er identisk på tværs af drivere; fejl ved overførsel ruller samlingens transaktion tilbage på dem alle.

Hver tabel får id (primærnøgle), hash (styrer trinvise overførsler), de typede kolonner og data (hele posten i JSON).

Synkronisering

PHP
$mirror->push();                    // reconcile: insert, update, delete as needed
$mirror->push('pages');             // reconcile a single collection
$mirror->flush('pages', $ids);      // push or remove just these ids
$mirror->pull();                    // write mirror rows back into the store
$mirror->verify();                  // report missing, stale, and orphaned rows
$mirror->rebuild();                 // clear all rows and push from scratch
$mirror->uninstall();               // drop the mirror tables

push() sammenligner posternes hashes med spejlet og skriver hver samling i én transaktion, så en afbrudt eller mislykket overførsel aldrig efterlader en delvist anvendt batch. Uændrede poster koster én SELECT plus en gennemgang af posterne. En periodisk push() (for eksempel fra et cron-interval) holder spejlet synkroniseret; kald flush() med id'erne, du skrev under en forespørgsel, når læsere skal kunne læse deres egne ændringer fra spejlet.

Forespørgsler

Lav forespørgsler mod spejlet med almindelig SQL. table() returnerer det spejlede tabelnavn:

PHP
$pdo->query(
    'SELECT p.slug, COUNT(*) AS sales
     FROM ' . $mirror->table('purchases') . ' o
     INNER JOIN ' . $mirror->table('products') . ' p ON p.id = o.product_id
     GROUP BY p.slug
     ORDER BY sales DESC'
);

Tilbageførsel til filer

pull() læser rækker fra spejlet og skriver dem til det registrerede lager i id- rækkefølge. Det understøtter to forløb:

  • Gendannelse: filerne er væk, men spejlet findes stadig. Registrer et nyt lager med samme samlingsnavn, og hent rækkerne tilbage.
  • Klargøring: rækker, der indlæses i spejltabellen med eksterne værktøjer, bliver til storh- poster. Rækkerne skal indeholde gyldige UUIDv7-id'er og et objekt i kolonnen data; typede kolonner ignoreres ved hentning, fordi data er hele posten.
PHP
$restored = new Storh\DocStore($root, 'pages');
$mirror   = new SqlMirror($pdo);
$mirror->collection($restored, 'pages');
$mirror->pull();          // ['written' => n, 'unchanged' => m]

Skrivninger fra hentede rækker går gennem lagerets normale funktioner, så skemavalidering og unikke indekser gælder, og hver post skrives holdbart. pull() sletter aldrig lokale poster, og poster, hvis data allerede svarer til spejlrækken, springes over. Efter klargøring af manuelt indsatte rækker skal du køre push() én gang: det omskriver rækkerne i kanonisk form, så deres hashes stemmer overens.

Aftale og begrænsninger

  • Filerne er kanoniske. Spejlet er skrivebeskyttet output; alt, der skrives til det manuelt, overskrives eller slettes ved næste push().
  • Unikke kolonner i spejlet fungerer som et sikkerhedsnet, ikke som håndhævelse ved skrivning: en dublet, som filerne tillod, giver en mislykket (og fuldt tilbagerullet) overførsel. Brug unikke storh-indekser for at håndhæve unikhed ved skrivning.
  • Spejlet kan være op til ét overførselsinterval bag filerne, bortset fra de id'er, du udtrykkeligt flush().
  • Spejling tilføjer ikke transaktioner til storh. Atomiske skrivninger på tværs af flere poster kræver fortsat en rigtig database som autoritativt datasæt.
  • Skemaændringer anvendes ved at slette og geninstallere spejlet: uninstall(), install(), push().