Skip to content

Preserve list-valued reference keys and contexts in SQLite - #87

Merged
xrotwang merged 1 commit into
cldf:masterfrom
antonsoo:fix/sqlite-reference-whitespace
Oct 28, 2026
Merged

xrotwang merged 1 commit into
cldf:masterfrom
antonsoo:fix/sqlite-reference-whitespace

Conversation

@antonsoo

Copy link
Copy Markdown
Contributor

Reading list-valued foreign keys from SQLite can change their values and drop references. For example:

from csvw import TableGroup
from csvw.db import Database

tg = TableGroup.fromvalue({'tables': [
    {'url': 'places', 'tableSchema': {
        'columns': [{'name': 'ID'}], 'primaryKey': 'ID'}},
    {'url': 'visits', 'tableSchema': {
        'columns': [{'name': 'ID'}, {'name': 'Places', 'separator': ';'}],
        'primaryKey': 'ID',
        'foreignKeys': [{'columnReference': 'Places', 'reference': {
            'resource': 'places', 'columnReference': 'ID'}}]}}
]})
db = Database(tg)
db.write(places=[{'ID': 'New York'}, {'ID': 'San Francisco'}],
         visits=[{'ID': 'trip', 'Places': ['New York', 'San Francisco']}])
print(db.read()['visits'][0]['Places'])

Before: ['New', 'York']. After: ['New York', 'San Francisco'].

The stored association rows are correct, but group_concat followed by whitespace splitting loses the key boundaries. The same aggregation can split a custom context containing ||. Read the individual rows and group them in Python, preserving each key/context value and repeated association. Add regressions for spaces, tabs, newlines, repeated keys, two foreign-key columns and opaque custom contexts.

Validation: the full suite passes on Python 3.12 (835 passed, 16 expected failures) and 3.9 (838 passed, 13 expected failures), with 100% configured coverage; changed-file Flake8 passes. A separate relational workflow uses published Concepticon labels in 128 multiword configurations across memory/file SQLite, CSV serialization and table/scalar-column translation. All fail before and pass after; all 128 complete single-word controls are unchanged. Raw SQLite association rows and foreign-key checks provide independent references. Source and an installed wheel reproduce the same results.

@xrotwang

Copy link
Copy Markdown
Contributor

For a bit of context: SQLite was always just meant as a format to allow performant analysis of CSVW data. So round-tripping data back from SQLite to CSVW was more of a proof-of-concept thing. And the "list-valued foreign keys" feature is something that isn't clearly spelt out in the CSVW spec. I implemented it because we explicitly allow this for CLDF datasets - where ID columns are typically very restricted, not allowing whitespace.

Anyway, making this functionality more robust is ceertainly welcome!

@xrotwang
xrotwang merged commit 6bb308e into cldf:master Oct 28, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants