2424from ..schema import Schema
2525
2626
27+ def _verify_import_counts (payload : dict , expected : dict [str , tuple [str , int ]]) -> None :
28+ """Check IMPORT DATABASE's per-file report against the prepared row counts.
29+
30+ Since IssunDB 0.1.0a16 the import returns one `(target, kind, count)` row
31+ per COPY statement; a mismatch (for example an edge file misclassified as
32+ nodes) previously surfaced only as silently empty query results. Older
33+ versions return `{"imported": true}` and cannot be verified, so the check
34+ is skipped for them.
35+ """
36+ if payload .get ("columns" ) != ["target" , "kind" , "count" ]:
37+ return
38+ imported = {
39+ rec ["values" ][0 ]: (rec ["values" ][1 ], rec ["values" ][2 ])
40+ for rec in payload ["records" ]
41+ }
42+ for target , want in expected .items ():
43+ got = imported .get (target )
44+ if got != want :
45+ raise RuntimeError (
46+ f"IMPORT DATABASE ingested { got } for '{ target } ', expected { want } "
47+ )
48+
49+
2750class IssunDBEngine (Engine ):
2851 name = "issundb"
2952 kind = "embedded"
@@ -68,11 +91,13 @@ def build(self, data_dir: Path) -> BuildResult:
6891
6992 # 3. Process and write node Parquet files with _id column
7093 n_node_rows = 0
94+ expected_counts : dict [str , tuple [str , int ]] = {}
7195 for label in self .schema .nodes :
7296 parquet_path = data_dir / "nodes" / f"{ label .name } .parquet"
7397 dst_parquet = import_dir / f"{ label .name } .parquet"
7498 df = pl .read_parquet (parquet_path )
7599 n_node_rows += df .height
100+ expected_counts [label .name ] = ("nodes" , df .height )
76101 df = df .with_columns (
77102 (
78103 pl .col (self .schema .id_column ).cast (pl .Int64 ) + offsets [label .name ]
@@ -89,6 +114,7 @@ def build(self, data_dir: Path) -> BuildResult:
89114 jsonl_path = import_dir / f"{ rel .name } .jsonl"
90115 df = pl .read_parquet (parquet_path )
91116 n_edge_rows += df .height
117+ expected_counts [rel .name ] = ("relationships" , df .height )
92118 df = df .with_columns (
93119 [
94120 (
@@ -118,10 +144,11 @@ def build(self, data_dir: Path) -> BuildResult:
118144
119145 (import_dir / "copy.cypher" ).write_text ("\n " .join (copy_lines ))
120146
121- # 6. Execute IMPORT DATABASE
147+ # 6. Execute IMPORT DATABASE and verify the per-file report
122148 query_start = time .perf_counter ()
123- self ._db .query (f"IMPORT DATABASE '{ import_dir } '" )
149+ payload = json . loads ( self ._db .query (f"IMPORT DATABASE '{ import_dir } '" ) )
124150 query_time = time .perf_counter () - query_start
151+ _verify_import_counts (payload , expected_counts )
125152
126153 # Clean up import temp files
127154 shutil .rmtree (import_dir )
0 commit comments