sdmxlib 0.19.0__tar.gz → 0.19.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/PKG-INFO +1 -1
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/pyproject.toml +1 -1
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/storage/writers.py +141 -69
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/README.md +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/__init__.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/api/__init__.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/api/client.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/api/federated.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/api/filters.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/api/policy.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/api/providers.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/api/query.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/api/registry.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/api/session.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/catalog.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/data_store.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/formats/__init__.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/formats/sdmx_csv/__init__.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/formats/sdmx_csv/reader.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/formats/sdmx_csv/writer.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/formats/sdmx_json/__init__.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/formats/sdmx_json/metadata.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/formats/sdmx_json/reader.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/formats/sdmx_json/writer.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/formats/sdmx_ml21/__init__.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/formats/sdmx_ml21/namespaces.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/formats/sdmx_ml21/reader.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/formats/sdmx_ml21/writer.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/formats/sdmx_ml30/__init__.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/formats/sdmx_ml30/metadata.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/formats/sdmx_ml30/namespaces.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/formats/sdmx_ml30/reader.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/formats/sdmx_ml30/writer.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/local/__init__.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/local/_data_store.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/local/_registry.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/model/__init__.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/model/annotations.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/model/base.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/model/binding.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/model/category.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/model/code_query.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/model/codelist.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/model/collections.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/model/concept.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/model/constraint.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/model/convert.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/model/dataflow.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/model/dataset.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/model/datastructure.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/model/expr.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/model/hierarchy.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/model/in_memory_registry.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/model/istring.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/model/mapping.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/model/message.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/model/metadataflow.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/model/metadataset.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/model/metadatastructure.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/model/organisation.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/model/provision.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/model/ref.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/model/registry.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/model/representation.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/model/urn.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/model/validation.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/polars.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/py.typed +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/rest.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/storage/__init__.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/storage/lazy.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/storage/readers.py +0 -0
- {sdmxlib-0.19.0 → sdmxlib-0.19.2}/src/sdmxlib/storage/schema.py +0 -0
|
@@ -16,6 +16,7 @@ from collections.abc import Sequence
|
|
|
16
16
|
from typing import Any
|
|
17
17
|
|
|
18
18
|
import duckdb
|
|
19
|
+
import pyarrow as pa
|
|
19
20
|
|
|
20
21
|
from sdmxlib.model.annotations import Annotations
|
|
21
22
|
from sdmxlib.model.binding import DataflowBinding
|
|
@@ -69,27 +70,19 @@ def _istring_to_map(s: InternationalString | None) -> dict[str, str]:
|
|
|
69
70
|
return {lang: s[lang] for lang in s}
|
|
70
71
|
|
|
71
72
|
|
|
72
|
-
def
|
|
73
|
-
"""
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
return f"MAP([{keys}], [{vals}])"
|
|
86
|
-
if isinstance(v, list):
|
|
87
|
-
if not v:
|
|
88
|
-
return "[]"
|
|
89
|
-
items = ", ".join(f"'{str(x).replace(chr(39), chr(39) + chr(39))}'" for x in v)
|
|
90
|
-
return f"[{items}]"
|
|
91
|
-
s = str(v).replace("'", "''")
|
|
92
|
-
return f"'{s}'"
|
|
73
|
+
def _to_arrow_array(values: list[Any]) -> pa.Array:
|
|
74
|
+
"""Build a pyarrow Array from a column of Python values.
|
|
75
|
+
|
|
76
|
+
Dict values become MAP(VARCHAR, VARCHAR); other types use pyarrow's
|
|
77
|
+
default inference, which handles None, scalars, and list[str] fine.
|
|
78
|
+
"""
|
|
79
|
+
sample = next((v for v in values if v is not None), None)
|
|
80
|
+
if isinstance(sample, dict):
|
|
81
|
+
return pa.array(
|
|
82
|
+
[None if d is None else list(d.items()) for d in values],
|
|
83
|
+
type=pa.map_(pa.string(), pa.string()),
|
|
84
|
+
)
|
|
85
|
+
return pa.array(values)
|
|
93
86
|
|
|
94
87
|
|
|
95
88
|
def _execute_bulk_insert(
|
|
@@ -98,15 +91,22 @@ def _execute_bulk_insert(
|
|
|
98
91
|
cols: Sequence[str],
|
|
99
92
|
rows: Sequence[Sequence[Any]],
|
|
100
93
|
) -> None:
|
|
101
|
-
"""Insert many rows
|
|
94
|
+
"""Insert many rows via Arrow columnar ingestion.
|
|
95
|
+
|
|
96
|
+
Avoids the multi-GB SQL parser allocation that VALUES-with-literals
|
|
97
|
+
causes for large bulk inserts (issue #66).
|
|
98
|
+
"""
|
|
102
99
|
if not rows:
|
|
103
100
|
return
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
conn.
|
|
108
|
-
|
|
109
|
-
|
|
101
|
+
columns = list(zip(*rows, strict=True))
|
|
102
|
+
arrays = [_to_arrow_array(list(col)) for col in columns]
|
|
103
|
+
arrow_table = pa.Table.from_arrays(arrays, names=list(cols))
|
|
104
|
+
conn.register("__sdmx_bulk_insert", arrow_table)
|
|
105
|
+
try:
|
|
106
|
+
col_str = ", ".join(cols)
|
|
107
|
+
conn.execute(f"INSERT INTO {table} ({col_str}) SELECT * FROM __sdmx_bulk_insert")
|
|
108
|
+
finally:
|
|
109
|
+
conn.unregister("__sdmx_bulk_insert")
|
|
110
110
|
|
|
111
111
|
|
|
112
112
|
# ── Spine + text + annotations helpers ──────────────────────────────────
|
|
@@ -188,44 +188,96 @@ def _put_localized_text(
|
|
|
188
188
|
)
|
|
189
189
|
|
|
190
190
|
|
|
191
|
+
class _AnnotationBatch:
|
|
192
|
+
"""Accumulator for annotation + annotation_text rows.
|
|
193
|
+
|
|
194
|
+
Collects rows across an entire artefact write and flushes them with a
|
|
195
|
+
single bulk-allocated id batch. Replaces the per-annotation
|
|
196
|
+
``INSERT … RETURNING id`` roundtrip pattern that made persisting a
|
|
197
|
+
78k-code codelist take ~130 s (issue #66).
|
|
198
|
+
"""
|
|
199
|
+
|
|
200
|
+
__slots__ = ("ann_rows", "text_rows")
|
|
201
|
+
|
|
202
|
+
def __init__(self) -> None:
|
|
203
|
+
# Each row: [owner_urn, ordinal, annotation_id, title, annotation_type, url]
|
|
204
|
+
self.ann_rows: list[list[Any]] = []
|
|
205
|
+
# Each entry: (local_idx_into_ann_rows, lang, text). The local
|
|
206
|
+
# index is resolved to a real annotation.id at flush time.
|
|
207
|
+
self.text_rows: list[tuple[int, str, str]] = []
|
|
208
|
+
|
|
209
|
+
def add(self, owner_urn: str, annotations: Annotations | None) -> None:
|
|
210
|
+
if not annotations:
|
|
211
|
+
return
|
|
212
|
+
for ordinal, ann in enumerate(annotations):
|
|
213
|
+
local_idx = len(self.ann_rows)
|
|
214
|
+
self.ann_rows.append([owner_urn, ordinal, ann.id, ann.title, ann.type, ann.url])
|
|
215
|
+
if ann.text:
|
|
216
|
+
for lang in ann.text:
|
|
217
|
+
self.text_rows.append((local_idx, lang, ann.text[lang]))
|
|
218
|
+
|
|
219
|
+
def flush(self, conn: duckdb.DuckDBPyConnection) -> None:
|
|
220
|
+
if not self.ann_rows:
|
|
221
|
+
return
|
|
222
|
+
n = len(self.ann_rows)
|
|
223
|
+
id_rows = conn.execute("SELECT nextval('annotation_id_seq') FROM range(?)", [n]).fetchall()
|
|
224
|
+
ids = [r[0] for r in id_rows]
|
|
225
|
+
|
|
226
|
+
full_ann_rows = [[ids[i], *row] for i, row in enumerate(self.ann_rows)]
|
|
227
|
+
_execute_bulk_insert(
|
|
228
|
+
conn,
|
|
229
|
+
"annotation",
|
|
230
|
+
["id", "owner_urn", "ordinal", "annotation_id", "title", "annotation_type", "url"],
|
|
231
|
+
full_ann_rows,
|
|
232
|
+
)
|
|
233
|
+
|
|
234
|
+
if self.text_rows:
|
|
235
|
+
text_rows = [[ids[idx], lang, text] for idx, lang, text in self.text_rows]
|
|
236
|
+
_execute_bulk_insert(
|
|
237
|
+
conn,
|
|
238
|
+
"annotation_text",
|
|
239
|
+
["annotation_id", "lang", "text"],
|
|
240
|
+
text_rows,
|
|
241
|
+
)
|
|
242
|
+
|
|
243
|
+
self.ann_rows.clear()
|
|
244
|
+
self.text_rows.clear()
|
|
245
|
+
|
|
246
|
+
|
|
191
247
|
def _put_annotations(
|
|
192
248
|
conn: duckdb.DuckDBPyConnection,
|
|
193
249
|
owner_urn: str,
|
|
194
250
|
annotations: Annotations | None,
|
|
195
251
|
) -> None:
|
|
196
|
-
"""Insert annotation + annotation_text rows.
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
""",
|
|
206
|
-
[owner_urn, ordinal, ann.id, ann.title, ann.type, ann.url],
|
|
207
|
-
).fetchone()
|
|
208
|
-
ann_db_id = row[0] # type: ignore[index] # RETURNING always returns
|
|
209
|
-
if ann.text:
|
|
210
|
-
for lang in ann.text:
|
|
211
|
-
conn.execute(
|
|
212
|
-
"""
|
|
213
|
-
INSERT INTO annotation_text (annotation_id, lang, text)
|
|
214
|
-
VALUES (?, ?, ?)
|
|
215
|
-
""",
|
|
216
|
-
[ann_db_id, lang, ann.text[lang]],
|
|
217
|
-
)
|
|
252
|
+
"""Insert annotation + annotation_text rows for one owner.
|
|
253
|
+
|
|
254
|
+
For artefacts with many annotated child items (e.g. codelists), prefer
|
|
255
|
+
building an :class:`_AnnotationBatch` directly and calling ``flush``
|
|
256
|
+
once at the end of the write — that avoids per-owner roundtrips.
|
|
257
|
+
"""
|
|
258
|
+
batch = _AnnotationBatch()
|
|
259
|
+
batch.add(owner_urn, annotations)
|
|
260
|
+
batch.flush(conn)
|
|
218
261
|
|
|
219
262
|
|
|
220
263
|
def _put_artefact_text_and_annotations(
|
|
221
264
|
conn: duckdb.DuckDBPyConnection,
|
|
222
265
|
urn: str,
|
|
223
266
|
artefact: Any,
|
|
267
|
+
batch: _AnnotationBatch | None = None,
|
|
224
268
|
) -> None:
|
|
225
|
-
"""Write localized_text and annotations for an artefact.
|
|
269
|
+
"""Write localized_text and annotations for an artefact.
|
|
270
|
+
|
|
271
|
+
If ``batch`` is provided, annotations are queued on it (caller flushes);
|
|
272
|
+
otherwise they are flushed immediately.
|
|
273
|
+
"""
|
|
226
274
|
_put_localized_text(conn, urn, "name", getattr(artefact, "name", None))
|
|
227
275
|
_put_localized_text(conn, urn, "description", getattr(artefact, "description", None))
|
|
228
|
-
|
|
276
|
+
anns = getattr(artefact, "annotations", None)
|
|
277
|
+
if batch is not None:
|
|
278
|
+
batch.add(urn, anns)
|
|
279
|
+
else:
|
|
280
|
+
_put_annotations(conn, urn, anns)
|
|
229
281
|
|
|
230
282
|
|
|
231
283
|
# ── Reference graph ─────────────────────────────────────────────────────
|
|
@@ -330,6 +382,7 @@ def _delete_artefact_cascade(conn: duckdb.DuckDBPyConnection, urn: str) -> None:
|
|
|
330
382
|
conn.execute("DELETE FROM concept WHERE scheme_urn = ?", p)
|
|
331
383
|
conn.execute("DELETE FROM category WHERE scheme_urn = ?", p)
|
|
332
384
|
conn.execute("DELETE FROM hierarchy_node WHERE hierarchy_urn = ?", p)
|
|
385
|
+
conn.execute("DELETE FROM hierarchy_level WHERE hierarchy_urn = ?", p)
|
|
333
386
|
conn.execute("DELETE FROM agency WHERE scheme_urn = ?", p)
|
|
334
387
|
conn.execute("DELETE FROM data_provider WHERE scheme_urn = ?", p)
|
|
335
388
|
# Contact cleanup for agencies
|
|
@@ -393,7 +446,8 @@ def put_codelist(conn: duckdb.DuckDBPyConnection, cl: Codelist, *, source_regist
|
|
|
393
446
|
|
|
394
447
|
_delete_artefact_cascade(conn, urn)
|
|
395
448
|
_put_spine(conn, urn, "Codelist", cl, source_registry=source_registry)
|
|
396
|
-
|
|
449
|
+
ann_batch = _AnnotationBatch()
|
|
450
|
+
_put_artefact_text_and_annotations(conn, urn, cl, ann_batch)
|
|
397
451
|
|
|
398
452
|
refs: list[tuple[str, str, str, int | None]] = []
|
|
399
453
|
|
|
@@ -417,8 +471,7 @@ def put_codelist(conn: duckdb.DuckDBPyConnection, cl: Codelist, *, source_regist
|
|
|
417
471
|
ancestors,
|
|
418
472
|
]
|
|
419
473
|
all_rows.append(row)
|
|
420
|
-
|
|
421
|
-
_put_annotations(conn, code_urn, code.annotations)
|
|
474
|
+
ann_batch.add(code_urn, code.annotations)
|
|
422
475
|
|
|
423
476
|
_execute_bulk_insert(
|
|
424
477
|
conn,
|
|
@@ -437,6 +490,7 @@ def put_codelist(conn: duckdb.DuckDBPyConnection, cl: Codelist, *, source_regist
|
|
|
437
490
|
all_rows,
|
|
438
491
|
)
|
|
439
492
|
|
|
493
|
+
ann_batch.flush(conn)
|
|
440
494
|
_put_refs(conn, refs)
|
|
441
495
|
|
|
442
496
|
|
|
@@ -537,7 +591,8 @@ def put_data_structure(
|
|
|
537
591
|
|
|
538
592
|
_delete_artefact_cascade(conn, urn)
|
|
539
593
|
_put_spine(conn, urn, "DataStructure", dsd, source_registry=source_registry)
|
|
540
|
-
|
|
594
|
+
ann_batch = _AnnotationBatch()
|
|
595
|
+
_put_artefact_text_and_annotations(conn, urn, dsd, ann_batch)
|
|
541
596
|
|
|
542
597
|
components: list[tuple[str, Any]] = [("Dimension", dim) for dim in dsd.dimensions]
|
|
543
598
|
if dsd.time_dimension is not None:
|
|
@@ -554,10 +609,11 @@ def put_data_structure(
|
|
|
554
609
|
# Component owner URN follows the same item-URN convention as Codes
|
|
555
610
|
# and Concepts (`<dsd_urn-with-component-class>.<component_id>`).
|
|
556
611
|
comp_urn = _make_item_urn(dsd, urn, comp_type, comp.id)
|
|
557
|
-
|
|
612
|
+
ann_batch.add(comp_urn, getattr(comp, "annotations", None))
|
|
558
613
|
|
|
559
614
|
if comp_rows:
|
|
560
615
|
_execute_bulk_insert(conn, "dsd_component", _DSD_COMPONENT_COLS, comp_rows)
|
|
616
|
+
ann_batch.flush(conn)
|
|
561
617
|
|
|
562
618
|
if dsd.groups:
|
|
563
619
|
for group in dsd.groups:
|
|
@@ -602,7 +658,8 @@ def put_concept_scheme(
|
|
|
602
658
|
|
|
603
659
|
_delete_artefact_cascade(conn, urn)
|
|
604
660
|
_put_spine(conn, urn, "ConceptScheme", cs, source_registry=source_registry)
|
|
605
|
-
|
|
661
|
+
ann_batch = _AnnotationBatch()
|
|
662
|
+
_put_artefact_text_and_annotations(conn, urn, cs, ann_batch)
|
|
606
663
|
|
|
607
664
|
refs: list[tuple[str, str, str, int | None]] = []
|
|
608
665
|
|
|
@@ -643,7 +700,7 @@ def put_concept_scheme(
|
|
|
643
700
|
repr_max_length,
|
|
644
701
|
]
|
|
645
702
|
)
|
|
646
|
-
|
|
703
|
+
ann_batch.add(concept_urn_str, concept.annotations)
|
|
647
704
|
|
|
648
705
|
_execute_bulk_insert(
|
|
649
706
|
conn,
|
|
@@ -665,6 +722,7 @@ def put_concept_scheme(
|
|
|
665
722
|
all_rows,
|
|
666
723
|
)
|
|
667
724
|
|
|
725
|
+
ann_batch.flush(conn)
|
|
668
726
|
_put_refs(conn, refs)
|
|
669
727
|
|
|
670
728
|
|
|
@@ -674,7 +732,8 @@ def put_hierarchy(conn: duckdb.DuckDBPyConnection, h: Hierarchy, *, source_regis
|
|
|
674
732
|
|
|
675
733
|
_delete_artefact_cascade(conn, urn)
|
|
676
734
|
_put_spine(conn, urn, "Hierarchy", h, source_registry=source_registry)
|
|
677
|
-
|
|
735
|
+
ann_batch = _AnnotationBatch()
|
|
736
|
+
_put_artefact_text_and_annotations(conn, urn, h, ann_batch)
|
|
678
737
|
|
|
679
738
|
conn.execute(
|
|
680
739
|
"INSERT INTO hierarchy_meta (urn, is_leveled) VALUES (?, ?)",
|
|
@@ -740,7 +799,7 @@ def put_hierarchy(conn: duckdb.DuckDBPyConnection, h: Hierarchy, *, source_regis
|
|
|
740
799
|
if code_urn:
|
|
741
800
|
refs.append((urn, code_urn, "code", position))
|
|
742
801
|
|
|
743
|
-
|
|
802
|
+
ann_batch.add(node_urn, node.annotations)
|
|
744
803
|
|
|
745
804
|
_execute_bulk_insert(
|
|
746
805
|
conn,
|
|
@@ -763,6 +822,8 @@ def put_hierarchy(conn: duckdb.DuckDBPyConnection, h: Hierarchy, *, source_regis
|
|
|
763
822
|
)
|
|
764
823
|
_put_refs(conn, refs)
|
|
765
824
|
|
|
825
|
+
ann_batch.flush(conn)
|
|
826
|
+
|
|
766
827
|
|
|
767
828
|
def _flatten_hcodes(
|
|
768
829
|
nodes: Any,
|
|
@@ -825,7 +886,8 @@ def put_category_scheme(
|
|
|
825
886
|
|
|
826
887
|
_delete_artefact_cascade(conn, urn)
|
|
827
888
|
_put_spine(conn, urn, "CategoryScheme", cs, source_registry=source_registry)
|
|
828
|
-
|
|
889
|
+
ann_batch = _AnnotationBatch()
|
|
890
|
+
_put_artefact_text_and_annotations(conn, urn, cs, ann_batch)
|
|
829
891
|
|
|
830
892
|
# Flatten category tree
|
|
831
893
|
flat: list[tuple[str, str | None, Any]] = []
|
|
@@ -851,7 +913,7 @@ def put_category_scheme(
|
|
|
851
913
|
ancestors,
|
|
852
914
|
]
|
|
853
915
|
)
|
|
854
|
-
|
|
916
|
+
ann_batch.add(cat_urn, cat.annotations)
|
|
855
917
|
|
|
856
918
|
_execute_bulk_insert(
|
|
857
919
|
conn,
|
|
@@ -870,6 +932,8 @@ def put_category_scheme(
|
|
|
870
932
|
all_rows,
|
|
871
933
|
)
|
|
872
934
|
|
|
935
|
+
ann_batch.flush(conn)
|
|
936
|
+
|
|
873
937
|
|
|
874
938
|
def _flatten_categories(
|
|
875
939
|
categories: Any,
|
|
@@ -941,7 +1005,8 @@ def put_agency_scheme(
|
|
|
941
1005
|
|
|
942
1006
|
_delete_artefact_cascade(conn, urn)
|
|
943
1007
|
_put_spine(conn, urn, "AgencyScheme", ascheme, source_registry=source_registry)
|
|
944
|
-
|
|
1008
|
+
ann_batch = _AnnotationBatch()
|
|
1009
|
+
_put_artefact_text_and_annotations(conn, urn, ascheme, ann_batch)
|
|
945
1010
|
|
|
946
1011
|
if ascheme.agencies:
|
|
947
1012
|
all_rows: list[list[Any]] = []
|
|
@@ -979,7 +1044,7 @@ def put_agency_scheme(
|
|
|
979
1044
|
],
|
|
980
1045
|
)
|
|
981
1046
|
|
|
982
|
-
|
|
1047
|
+
ann_batch.add(ag_urn, ag.annotations)
|
|
983
1048
|
|
|
984
1049
|
_execute_bulk_insert(
|
|
985
1050
|
conn,
|
|
@@ -988,6 +1053,8 @@ def put_agency_scheme(
|
|
|
988
1053
|
all_rows,
|
|
989
1054
|
)
|
|
990
1055
|
|
|
1056
|
+
ann_batch.flush(conn)
|
|
1057
|
+
|
|
991
1058
|
|
|
992
1059
|
def put_data_provider_scheme(
|
|
993
1060
|
conn: duckdb.DuckDBPyConnection, dps: "DataProviderScheme", *, source_registry: str | None = None
|
|
@@ -997,7 +1064,8 @@ def put_data_provider_scheme(
|
|
|
997
1064
|
|
|
998
1065
|
_delete_artefact_cascade(conn, urn)
|
|
999
1066
|
_put_spine(conn, urn, "DataProviderScheme", dps, source_registry=source_registry)
|
|
1000
|
-
|
|
1067
|
+
ann_batch = _AnnotationBatch()
|
|
1068
|
+
_put_artefact_text_and_annotations(conn, urn, dps, ann_batch)
|
|
1001
1069
|
|
|
1002
1070
|
if dps.providers:
|
|
1003
1071
|
all_rows: list[list[Any]] = []
|
|
@@ -1012,7 +1080,7 @@ def put_data_provider_scheme(
|
|
|
1012
1080
|
_istring_to_map(provider.description),
|
|
1013
1081
|
]
|
|
1014
1082
|
)
|
|
1015
|
-
|
|
1083
|
+
ann_batch.add(p_urn, provider.annotations)
|
|
1016
1084
|
|
|
1017
1085
|
_execute_bulk_insert(
|
|
1018
1086
|
conn,
|
|
@@ -1021,6 +1089,8 @@ def put_data_provider_scheme(
|
|
|
1021
1089
|
all_rows,
|
|
1022
1090
|
)
|
|
1023
1091
|
|
|
1092
|
+
ann_batch.flush(conn)
|
|
1093
|
+
|
|
1024
1094
|
|
|
1025
1095
|
def put_structure_set(
|
|
1026
1096
|
conn: duckdb.DuckDBPyConnection, ss: "StructureSet", *, source_registry: str | None = None
|
|
@@ -1112,7 +1182,8 @@ def put_metadata_structure(
|
|
|
1112
1182
|
|
|
1113
1183
|
_delete_artefact_cascade(conn, urn)
|
|
1114
1184
|
_put_spine(conn, urn, "MetadataStructure", msd, source_registry=source_registry)
|
|
1115
|
-
|
|
1185
|
+
ann_batch = _AnnotationBatch()
|
|
1186
|
+
_put_artefact_text_and_annotations(conn, urn, msd, ann_batch)
|
|
1116
1187
|
|
|
1117
1188
|
conn.execute("INSERT INTO metadata_structure (urn) VALUES (?)", [urn])
|
|
1118
1189
|
|
|
@@ -1177,10 +1248,11 @@ def put_metadata_structure(
|
|
|
1177
1248
|
ancestors,
|
|
1178
1249
|
]
|
|
1179
1250
|
)
|
|
1180
|
-
|
|
1251
|
+
ann_batch.add(attr_urn, attr.annotations)
|
|
1181
1252
|
|
|
1182
1253
|
_execute_bulk_insert(conn, "metadata_attribute", _METADATA_ATTRIBUTE_COLS, rows)
|
|
1183
1254
|
|
|
1255
|
+
ann_batch.flush(conn)
|
|
1184
1256
|
_put_refs(conn, refs)
|
|
1185
1257
|
|
|
1186
1258
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|