Milestone: 0.4.0 — Datenimport und inkrementelle Datenpfade
Phase: E (CLI-Integration)
Schritte: 24 + 26 + 27
Status: Abgeschlossen (per Docker verifiziert, 2026-04-12)
Referenz:implementation-plan-0.4.0.md§3.7, §6.11
data importvollständig in den CLI/Runner-Layer heben, inklusive aller Optionen aus §3.7.1.NamedConnectionResolverfür Import/Export umdatabase.default_sourceunddatabase.default_targetergänzen.- CLI-Fehlermodi für
data importauf die Exit-Codes in §6.11 mappen. - Die drei Punkte als zusammenhängenden Implementierungsblock liefern, damit Parsing, Verbindungsauflösung und Exit-Verhalten konsistent sind.
- Fokus der drei Schritte:
DataImportCommand,NamedConnectionResolver, Exit-Code-Mapping fürdata import. - Ist-Stand:
DataExportRunnerist vorhanden und dient als Architekturvorlage;data importist in CLI und Hexagon noch nicht implementiert.
| Abhängigkeit | Schritt | Status |
|---|---|---|
docs/planning/implementation-plan-0.4.0.md §3.7 / §6.11 |
Basis | ✅ Referenziert |
Hexagon / Streaming-Kontrakte (ImportInput, StreamingImporter) |
Phase D (19–23) | ✅ Vorhanden |
Bestehender CLI-Bootstrap (DataCommand, DataExportCommand) |
0.3.0 / bestehend | ✅ Vorhanden |
Bestehender NamedConnectionResolver-Skeleton |
0.3.0 | ✅ Vorhanden |
DataImportRunner / DataImportRequest in Hexagon (application) |
0.4.0 | ❌ Neu zu implementieren |
DataImportCommand im CLI |
0.4.0 | ❌ Neu zu implementieren |
Exit-Mapping im bestehenden CLI-Stil (ProgramResult) |
0.3.0 | ✅ Vorhanden |
DataImportCommand+DataImportRunnerbilden die Trennung CLI-Parsing/Domain-Logik analog zuDataExportCommandundDataExportRunner.ImportInput-Auflösung und Exit-Mapping bleiben in CLI-Command plus Runner, nicht im Streaming-/Writer-Layer.- Resolver-Defaults (
default_source/default_target) werden zentral inNamedConnectionResolverabgebildet; kein zusätzlicher lokaler Resolver inDataImportCommand. - Exit-Mapping wird im Runner erzeugt und im Command über
ProgramResult(exitCode)in den Prozess-Exit umgesetzt. - Rückwärtskompatibilität im Resolver bleibt gewahrt: bestehende
resolve(..)-Overloads delegieren auf neueresolveSource(null)/resolveTarget(null)-Signaturen.
- Nicht Teil von Schritt 24/26/27
--incremental/--since-columnauf der Import-Seite.- Phase-F-E2E-Tests gegen Container.
- Vollständige Docs-Überarbeitung in
spec/cli-spec.md. - Reader-/Writer-Implementierungen außerhalb des CLI-Wrappers.
- Neuer Exit-Dispatcher wie
ErrorMapper.kt; es wird der bestehendeProgramResult-Pfad verwendet.
adapters/driving/cli/src/main/kotlin/dev/dmigrate/cli/config/NamedConnectionResolver.ktadapters/driving/cli/src/main/kotlin/dev/dmigrate/cli/commands/DataCommand.kt(Subcommand-Registrierung)adapters/driving/cli/src/main/kotlin/dev/dmigrate/cli/commands/DataImportCommand.kt(neu)adapters/driving/cli/src/main/kotlin/dev/dmigrate/cli/commands/DataCommands.kt(falls Strukturentscheidung dort zentral weitergeführt wird)hexagon/application/src/main/kotlin/dev/dmigrate/cli/commands/DataImportRunner.kt(neu)hexagon/application/src/main/kotlin/dev/dmigrate/cli/commands/DataImportRequest.kt(neu; optional als separates Datenobjekt oder in Runner-Datei)
adapters/driving/cli/src/test/kotlin/dev/dmigrate/cli/config/NamedConnectionResolverTest.ktadapters/driving/cli/src/test/kotlin/dev/dmigrate/cli/commands/DataImportCommandTest.ktadapters/driving/cli/src/test/kotlin/dev/dmigrate/cli/commands/DataImportCommandParserTest.kt(wenn Parser-Tests für Clikt-Fälle beibehalten werden)hexagon/application/src/test/kotlin/dev/dmigrate/cli/commands/DataImportRunnerTest.ktadapters/driving/cli/src/test/kotlin/dev/dmigrate/cli/CliDataImportTest.kt(optionaler CLI-Smoke)
DataImportRunner+DataImportRequestinhexagon/applicationimplementieren (parallele VorlageDataExportRunner).DataImportCommandmit allen Flags aus §3.7.1 ergänzen:--target,--source(required in CLI-Definition),--format,--table,--tables,--schema,--on-error,--on-conflict,--trigger-mode,--truncate,--disable-fk-checks,--reseed-sequences(inkl.--no-reseed-sequences),--encoding,--csv-no-header,--csv-null-string,--chunk-size.--formatstrikt aufjson|yaml|csveinschränken, kein Content-Sniffing; bei fehlendem/unknown Format bei Datei-Source oder stdin -> Exit 2.--table/--tables-Matrix finalisieren:-+ Datei benötigt--table, Verzeichnis nutzt--tables, inkompatible Mischformen liefern deterministische Exit-2-Fehler.ImportInput-Ableitung klar trennen:ImportInput.Stdin(table, System.in)für-ImportInput.SingleFile(table, path)für DateiImportInput.Directory(path, tables, tableOrder?)für Verzeichnis
DataCommandumdata importergänzen.- Source-Pfadprüfung im Runner/Command: nicht existierende Datei -> Exit 2; nicht lesbare Quelle/Typfehler -> deterministischer Exit-2 mit präziser Meldung.
resolveSource(source: String?)umdatabase.default_sourceerweitern.resolveTarget(target: String?)ergänzen fürdatabase.default_target.- Resolver-Regelwerk aus §3.7.3 vollständig abbilden:
resolveTargetnutzt beinullund gesetztem Default direkt URL oderdatabase.connections-Auflösung.- Default-Name wird über
database.connectionsaufgelöst. - fehlt der Default bei zwingendem Ziel (z. B. zwingender Laufkontext) -> Exit 2 über Command/Runner.
- Resolver-Fehler in zwei Klassen modellieren:
- Config-/Parse-/Template-Fehler -> Exit 7
- CLI-missverständlich / Pflichtbruch -> Exit 2
- Bestehende Wrapper-Signaturen beibehalten (
resolve(String)etc.), intern delegieren auf neue nullable Varianten. NamedConnectionResolver-KDoc aktualisieren (Default-Quelle, Default-Ziel, Resolve-Tabelle).
- Fehlerpfad im
DataImportRunneran Exit-Matrix §6.11 binden. - Wichtigste Abbildungen:
- CLI-Fehler und ungültige Optionenkombinationen -> Exit 2
UnsupportedTriggerModeExceptionbei MySQL/SQLite im--trigger-mode disable-> Exit 2--disable-fk-checksauf PG -> Exit 2
- Pre-Flight-Fehler (Header/Schema/Schema-Validierung, strict-trigger pre-flight, etc.) -> Exit 3.
- Streaming-Fehler-Matrix:
--on-error abort-> Exit 5--on-error skip|log-> Chunk-Write-/Read-Fehler verlieren nur Zeilenstatistik; Lauf endet Exit 0 mitrowsFailed/chunkFailures.--truncate+ explizit gesetztes--on-conflict abort-> Exit 2
failedFinish-Fehler (z. B. reseed/trigger-reenable nach erfolgreichem Schreiben) -> Exit 5.- Verbindungsfehler -> Exit 4.
- Unerwartete interne Ausnahmen -> Exit 1.
-
data importist als CLI-Entry mit allen Flags aus §3.7.1 nutzbar. -
DataImportCommandlöstImportInputfür stdin/file/directory korrekt auf. -
DataImportRunnerexistiert und kapselt die Exit-Entscheidung fürdata import. -
--targetist in Clikt optional; Pflicht wird über Resolver-Logik entschieden. -
database.default_sourceunddatabase.default_targetsind aktiv und konsistent auflösbar. -
NamedConnectionResolver-Wrapper bleiben kompatibel. -
UnsupportedTriggerModeExceptionbei unsupporteddisableführt deterministisch zu Exit 2. -
--disable-fk-checksauf PG liefert Exit 2. -
--on-error skip|logmit Chunk-Write/Read-Fehlern bleibt Exit 0. -
--source -erfordert zwingend--format(sonst Exit 2). - Dateiquelle ohne erkennbare Endung ohne
--formatliefert Exit 2. -
--truncate --on-conflict abortliefert Exit 2. -
failedFinish-Pfad liefert Exit 5. - Exit-Mapping entspricht im Scope Tabelle §6.11.
- KDoc von
NamedConnectionResolverbeschreibt die reale Resolve-Logik.
-
NamedConnectionResolverTest -
DataImportRunnerTest(Parsing-Fälle, Resolver-Defaultpfade, Pre-Flight, Exit-Matrix) -
DataImportCommandTest/DataImportCommandParserTest-Scope überCliDataImportSmokeTest,DataImportRunnerTestunddocker run ... data import --helpverifiziert - Optionaler CLI-Smoke per Docker-Image
d-migrate:dev: -
data importmit Directory +--table[s] -
data importmit--trigger-mode disableauf SQLite/MySQL -> Exit 2 -
data importmit--disable-fk-checksauf PG -> Exit 2 -
data importmit--source -ohne--format-> Exit 2 -
data importmit--source-Datei ohne Endung und ohne--format-> Exit 2 -
data importmit--truncate --on-conflict abort-> Exit 2 - Keine Standard-CI-Umgebungsänderung für die neuen Tests nötig; keine neuen externen Dependencies.
- Lokal verifiziert via
docker build -t d-migrate:dev .als Build-Smoke gemäß README.