Skip to content

Commit

Permalink
Merge pull request #798 from Mause/register-docs
Browse files Browse the repository at this point in the history
docs: amend `register` docs
  • Loading branch information
Mause authored Oct 5, 2023
2 parents 9a0c5b7 + b782994 commit 8d7a9e8
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 16 deletions.
13 changes: 10 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,15 @@ The supported configuration parameters are listed in the [DuckDB docs](https://d
## How to register a pandas DataFrame

```python
eng = create_engine("duckdb:///:memory:")
eng.execute("register", ("dataframe_name", pd.DataFrame(...)))
conn = create_engine("duckdb:///:memory:").connect()

# with SQLAlchemy 1.3
conn.execute("register", ("dataframe_name", pd.DataFrame(...)))

eng.execute("select * from dataframe_name")
# with SQLAlchemy 1.4+
conn.execute(text("register(:name, :df)"), {"name": "test_df", "df": df})

conn.execute("select * from dataframe_name")
```

## Things to keep in mind
Expand Down Expand Up @@ -157,6 +162,8 @@ After loading this class with your program, Alembic will no longer raise an erro

## Preloading extensions (experimental)

> DuckDB 0.9.0+ includes builtin support for autoinstalling and autoloading of extensions, see [the extension documentation](http://duckdb.org/docs/archive/0.9.0/extensions/overview#autoloadable-extensions) for more information.
Until the DuckDB python client allows you to natively preload extensions, I've added experimental support via a `connect_args` parameter

```python
Expand Down
9 changes: 8 additions & 1 deletion duckdb_engine/tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import warnings
from functools import wraps
from typing import Any, Callable, TypeVar
from typing import Any, Callable, Generator, TypeVar

from pytest import fixture, raises
from sqlalchemy import create_engine
from sqlalchemy.dialects import registry # type: ignore
from sqlalchemy.engine import Engine
from sqlalchemy.engine.base import Connection
from sqlalchemy.orm import Session, sessionmaker
from typing_extensions import ParamSpec

Expand All @@ -26,6 +27,12 @@ def engine() -> Engine:
return create_engine("duckdb:///:memory:")


@fixture
def conn(engine: Engine) -> Generator[Connection, None, None]:
with engine.connect() as conn:
yield conn


@fixture
def session(engine: Engine) -> Session:
return sessionmaker(bind=engine)()
Expand Down
27 changes: 15 additions & 12 deletions duckdb_engine/tests/test_integration.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,26 @@
import duckdb
import pandas as pd
from pytest import importorskip, mark, raises
from sqlalchemy import text
from sqlalchemy.engine import Engine, create_engine
from sqlalchemy import __version__, text
from sqlalchemy.engine import create_engine
from sqlalchemy.engine.base import Connection
from sqlalchemy.exc import ProgrammingError

SEGFAULT = -6
SUCCESS = 0
df = pd.DataFrame([{"a": 1}])


def test_integration(engine: Engine) -> None:
with engine.connect() as conn:
execute = (
conn.exec_driver_sql if hasattr(conn, "exec_driver_sql") else conn.execute
)
params = ("test_df", pd.DataFrame([{"a": 1}]))
execute("register", params) # type: ignore[operator]
@mark.skipif(not hasattr(Connection, "exec_driver_sql"), reason="Needs exec_driver_sql")
def test_register_driver(conn: Connection) -> None:
conn.exec_driver_sql("register", ("test_df_driver", df)) # type: ignore[arg-type]
conn.execute(text("select * from test_df_driver"))

conn.execute(text("select * from test_df"))

def test_plain_register(conn: Connection) -> None:
if __version__.startswith("1.3"):
conn.execute(text("register"), {"name": "test_df", "df": df})
else:
conn.execute(text("register(:name, :df)"), {"name": "test_df", "df": df})
conn.execute(text("select * from test_df"))


@mark.remote_data
Expand Down

0 comments on commit 8d7a9e8

Please sign in to comment.