Visitar URL original
Load DataFrames and Arrow tables directly; to_polars() on results by tae898 · Pull Request #390 · humemai/arcadedb-embedded-python · GitHub
Skip to content

Load DataFrames and Arrow tables directly; to_polars() on results - #390

Merged
tae898 merged 5 commits into
mainfrom
dataframe-ingest-387
Oct 21, 2026
Merged

tae898 merged 5 commits into
mainfrom
dataframe-ingest-387

Conversation

@tae898

@tae898 tae898 commented Oct 21, 2026

Copy link
Copy Markdown

Closes #387.

A bulk data path is one of the things an embedded database's Python API owns (DuckDB reads DataFrames in place), so this adds one, built on the existing glue (no new Java): documents go through DocumentBatcher.insertColumns, vertices through GraphBatch; the Arrow-to-column conversion and the declared-type check are new Python in dataframe.py.

  • Database.insert_dataframe(type_name, df, *, batch_size=10_000, parallel=False) -> int: pandas, Polars, or any Arrow PyCapsule object. A separate function from insert_arrow because the frame libraries' missing values differ (pandas NaN becomes null, Polars NaN stays NaN).
  • Database.insert_arrow(type_name, table, *, batch_size=10_000, parallel=False) -> int: Table, RecordBatch, RecordBatchReader or capsule object.
  • ResultSet.to_polars(batch_size=25_000, columns=None) via to_arrow().
  • Type mapping (api/database.md): integers to LONG (uint64 above 2^63-1 refused), floats to DOUBLE, bool, strings, dictionary as its value type, binary, timestamps (no zone: wall clock kept; with zone: UTC; precision from the declared type, read from the integer epoch so nanoseconds survive), date, decimal, list (ARRAY_OF_* if declared), struct to MAP, null as no value; time, duration and map columns raise TypeError. A declared property converts along an allowlist and refuses the rest before any row is written. Each batch commits on its own; on a failure the batch in flight rolls back and the error says how many rows were committed before it.
  • Left out: edges (no column convention for both ends; the error points to graph_batch().new_edges()), parallel=True for vertex types.
  • Docs: api/database.md, api/results.md, guide/import.md, java-api-coverage.md, bridge.md, architecture.md, testing.md, docs/index.md; example 27 (script, page, README, nav). Packaging: a polars extra; polars in the test extra and in the CI test requirements.
  • Tests: test_dataframe_ingest.py, 68 cases (every mapping written and read back, nulls, declared-type conversions and refusals, a 100k-row frame across batches, Polars and Arrow inputs, the to_polars() round trip); no skips.

Checked locally against the 26.10.2 engine: the new tests with the insert_columns, resultset_arrow, columnar_readers and graph_batch tests (179 passed), bandit (low/low), pre-commit, the strict docs build.

🤖 Generated with Claude Code

tae898 and others added 4 commits October 21, 2026 13:09
…lars() on results (#387)

Database.insert_dataframe and insert_arrow load a DataFrame or Arrow table in batches: documents through the existing insert_columns typed-array path, vertices through GraphBatch, no new Java. The Arrow type mapping (ints, floats, bool, string, timestamps with and without zone, date, decimal, list, struct, nulls) is documented and tested, and a declared property converts or the load is refused before a row is written. ResultSet.to_polars() reads through Arrow. polars joins the test extras and the CI test requirements, and a polars extra is added. Docs, java-api-coverage, testing rows and example 27 are in the same change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… comes through the bindings' test extra and the CI test requirements (#387)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ataframe_arrow_ingest.py (#387)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…cs, whose leg is disabled; it breaks pyarrow on 3.14) (#387)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@tae898

tae898 commented Oct 21, 2026

Copy link
Copy Markdown
Author

Two CI changes added after review: the examples' environment now has pandas, polars and pyarrow (example 27 imports them), and the macOS numpy<2.0 cap of the examples is gone. That cap was for Intel Macs (PyTorch stops at 2.2 there, built against NumPy 1.x), whose leg is disabled; on Apple Silicon it broke example 27 on Python 3.14 (pyarrow requires NumPy 2.0 or newer, found 1.26.4). The requirement set resolves for every platform on 3.11 and 3.14 (NumPy 2.4 and 2.5); a comment beside the list says the cap comes back for darwin/amd64 only if that leg is re-enabled.

…our transaction, not committed' inside the caller's transaction; docs: undeclared nanosecond timestamps are stored, the readers return milliseconds and get() microseconds (#387)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@tae898
tae898 merged commit 643b80b into main Oct 21, 2026
42 of 44 checks passed
@tae898
tae898 deleted the dataframe-ingest-387 branch October 21, 2026 09:05
tae898 added a commit that referenced this pull request Oct 21, 2026
…r-call figure in the examples README (#386)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tae898 added a commit that referenced this pull request Oct 21, 2026
…allbacks (#391)

* Python functions callable from SQL and openCypher, and record event callbacks (#386)

Database.register_function() / unregister_function() register a Python callable as an engine SQLFunction
(bridge class PythonFunctions): SELECT and WHERE in SQL, and openCypher through a namespaced name such as
py.slugify (its validator rejects an unknown bare name). An exception in the function is an ArcadeDBError naming
the function, never a JVM crash. Database.on() / EventHandle.remove() run Python callbacks on before/after
create, update and delete (bridge class PythonRecordEvents), database-wide or per type; a before callback that
returns False vetoes the change, and an exception fails the operation. Tests, API and guide docs, coverage,
bridge and testing docs, and example 27 in the same change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Renumber the Python functions example to 28 (27 is the DataFrame ingest example of #387) (#386)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* callbacks: the function registry holds its Database weakly, so a Database is released with its last result (#386)

The registry, the function proxies and the event proxies hold the Database through a weak reference: the engine holds the proxies, so a strong reference would keep the Database alive until a gc pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs: no per-call figure for Python functions until it is measured with tools/ab.py; Example 28 prints the cost on the reader's machine (#386)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* callbacks: one JPype proxy class per interface (no per-registration leak), readable error for an unconvertible return, Ctrl-C always a KeyboardInterrupt, Document.save()/delete() raise ArcadeDBError; docs: read-only begin(), the ~30 bytes per numeric argument JPype note (#386)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* docs: examples 27 and 28 side by side after the rebase on #390; no per-call figure in the examples README (#386)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
tae898 added a commit to ArcadeData/arcadedb-python that referenced this pull request Oct 24, 2026
…ow on Apple Silicon)

The cap was for Intel Macs, whose leg (darwin/amd64) is disabled. pyarrow 26
requires NumPy 2, so example 27 failed on darwin/arm64 with 'pyarrow requires
NumPy 2.0 or newer, found 1.26.4'. Same change as humemai/arcadedb-embedded-python#390.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.

Load DataFrames and Arrow tables directly; to_polars() on results

1 participant