-
Notifications
You must be signed in to change notification settings - Fork 48
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add SQL adapter #779
Draft
skarakuzu
wants to merge
8
commits into
bluesky:main
Choose a base branch
from
skarakuzu:add_sql_adapter
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
add SQL adapter #779
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
637a7c1
preliminary start of sql adapter. to be continued ...
d9d6509
hashed table names. to be continued...
6bada3b
modified hashing and added a test for sqlite database. to be continued
c857ef8
try TILED_TEST_POSTGRESQL_URI usage
26b9d47
fix postgreql uri
cfca6df
Automatically set SQL driver if unset.
danielballan 9714e86
Do not require env var to be set.
danielballan 8f676e8
Handle special SQLite URIs
danielballan File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
import os | ||
import tempfile | ||
|
||
import adbc_driver_sqlite | ||
import pyarrow as pa | ||
import pytest | ||
|
||
from tiled.adapters.sql import SQLAdapter | ||
from tiled.structures.table import TableStructure | ||
|
||
names = ["f0", "f1", "f2"] | ||
data0 = [ | ||
pa.array([1, 2, 3, 4, 5]), | ||
pa.array(["foo0", "bar0", "baz0", None, "goo0"]), | ||
pa.array([True, None, False, True, None]), | ||
] | ||
data1 = [ | ||
pa.array([6, 7, 8, 9, 10, 11, 12]), | ||
pa.array(["foo1", "bar1", None, "baz1", "biz", None, "goo"]), | ||
pa.array([None, True, True, False, False, None, True]), | ||
] | ||
data2 = [pa.array([13, 14]), pa.array(["foo2", "baz2"]), pa.array([False, None])] | ||
|
||
batch0 = pa.record_batch(data0, names=names) | ||
batch1 = pa.record_batch(data1, names=names) | ||
batch2 = pa.record_batch(data2, names=names) | ||
|
||
|
||
def test_invalid_uri() -> None: | ||
data_uri = "/some_random_uri/test.db" | ||
table = pa.Table.from_arrays(data0, names) | ||
structure = TableStructure.from_arrow_table(table, npartitions=1) | ||
asset = SQLAdapter.init_storage(data_uri, structure=structure) | ||
with pytest.raises( | ||
ValueError, | ||
match="The database uri must start with either `sqlite://` or `postgresql://` ", | ||
): | ||
SQLAdapter(asset.data_uri, structure=structure) | ||
|
||
|
||
def test_invalid_structure() -> None: | ||
data_uri = "/some_random_uri/test.db" | ||
table = pa.Table.from_arrays(data0, names) | ||
structure = TableStructure.from_arrow_table(table, npartitions=3) | ||
with pytest.raises(ValueError, match="The SQL adapter must have only 1 partition"): | ||
SQLAdapter.init_storage(data_uri, structure=structure) | ||
|
||
|
||
@pytest.fixture | ||
def adapter_sql() -> SQLAdapter: | ||
data_uri = "sqlite://file://localhost" + tempfile.gettempdir() + "/test.db" | ||
table = pa.Table.from_arrays(data0, names) | ||
structure = TableStructure.from_arrow_table(table, npartitions=1) | ||
asset = SQLAdapter.init_storage(data_uri, structure=structure) | ||
return SQLAdapter(asset.data_uri, structure=structure) | ||
|
||
|
||
def test_attributes(adapter_sql: SQLAdapter) -> None: | ||
assert adapter_sql.structure().columns == names | ||
assert adapter_sql.structure().npartitions == 1 | ||
assert isinstance(adapter_sql.conn, adbc_driver_sqlite.dbapi.AdbcSqliteConnection) | ||
|
||
|
||
def test_write_read(adapter_sql: SQLAdapter) -> None: | ||
# test writing and reading it | ||
adapter_sql.write(batch0) | ||
result = adapter_sql.read() | ||
# the pandas dataframe gives the last column of the data as 0 and 1 since SQL does not save boolean | ||
# so we explicitely convert the last column to boolean for testing purposes | ||
result["f2"] = result["f2"].astype("boolean") | ||
|
||
assert pa.Table.from_arrays(data0, names) == pa.Table.from_pandas(result) | ||
|
||
adapter_sql.write([batch0, batch1]) | ||
result = adapter_sql.read() | ||
# the pandas dataframe gives the last column of the data as 0 and 1 since SQL does not save boolean | ||
# so we explicitely convert the last column to boolean for testing purposes | ||
result["f2"] = result["f2"].astype("boolean") | ||
assert pa.Table.from_batches([batch0, batch1]) == pa.Table.from_pandas(result) | ||
|
||
adapter_sql.write([batch0, batch1, batch2]) | ||
result = adapter_sql.read() | ||
# the pandas dataframe gives the last column of the data as 0 and 1 since SQL does not save boolean | ||
# so we explicitely convert the last column to boolean for testing purposes | ||
result["f2"] = result["f2"].astype("boolean") | ||
assert pa.Table.from_batches([batch0, batch1, batch2]) == pa.Table.from_pandas( | ||
result | ||
) | ||
|
||
# test write , append and read all | ||
adapter_sql.write([batch0, batch1, batch2]) | ||
adapter_sql.append([batch2, batch0, batch1]) | ||
adapter_sql.append([batch1, batch2, batch0]) | ||
result = adapter_sql.read() | ||
# the pandas dataframe gives the last column of the data as 0 and 1 since SQL does not save boolean | ||
# so we explicitely convert the last column to boolean for testing purposes | ||
result["f2"] = result["f2"].astype("boolean") | ||
|
||
assert pa.Table.from_batches( | ||
[batch0, batch1, batch2, batch2, batch0, batch1, batch1, batch2, batch0] | ||
) == pa.Table.from_pandas(result) | ||
|
||
|
||
@pytest.fixture | ||
def postgres_uri() -> str: | ||
uri = os.getenv("TILED_TEST_POSTGRESQL_URI") | ||
if uri is not None: | ||
return uri | ||
pytest.skip("TILED_TEST_POSTGRESQL_URI is not set") | ||
return "" | ||
|
||
|
||
@pytest.fixture | ||
def adapter_psql(postgres_uri: str) -> SQLAdapter: | ||
table = pa.Table.from_arrays(data0, names) | ||
structure = TableStructure.from_arrow_table(table, npartitions=1) | ||
asset = SQLAdapter.init_storage(postgres_uri, structure=structure) | ||
return SQLAdapter(asset.data_uri, structure=structure) | ||
|
||
|
||
def test_psql(postgres_uri: str, adapter_psql: SQLAdapter) -> None: | ||
assert adapter_psql.structure().columns == names | ||
assert adapter_psql.structure().npartitions == 1 | ||
# assert isinstance( | ||
# adapter_psql.conn, adbc_driver_postgresql.dbapi.AdbcSqliteConnection | ||
# ) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
from ..utils import ensure_specified_sql_driver | ||
|
||
|
||
def test_ensure_specified_sql_driver(): | ||
# Postgres | ||
# Default driver is added if missing. | ||
assert ( | ||
ensure_specified_sql_driver( | ||
"postgresql://user:password@localhost:5432/database" | ||
) | ||
== "postgresql+asyncpg://user:password@localhost:5432/database" | ||
) | ||
# Default driver passes through if specified. | ||
assert ( | ||
ensure_specified_sql_driver( | ||
"postgresql+asyncpg://user:password@localhost:5432/database" | ||
) | ||
== "postgresql+asyncpg://user:password@localhost:5432/database" | ||
) | ||
# Do not override user-provided. | ||
assert ( | ||
ensure_specified_sql_driver( | ||
"postgresql+custom://user:password@localhost:5432/database" | ||
) | ||
== "postgresql+custom://user:password@localhost:5432/database" | ||
) | ||
|
||
# SQLite | ||
# Default driver is added if missing. | ||
assert ( | ||
ensure_specified_sql_driver("sqlite:////test.db") | ||
== "sqlite+aiosqlite:////test.db" | ||
) | ||
# Default driver passes through if specified. | ||
assert ( | ||
ensure_specified_sql_driver("sqlite+aiosqlite:////test.db") | ||
== "sqlite+aiosqlite:////test.db" | ||
) | ||
# Do not override user-provided. | ||
assert ( | ||
ensure_specified_sql_driver("sqlite+custom:////test.db") | ||
== "sqlite+custom:////test.db" | ||
) | ||
# Handle SQLite :memory: URIs | ||
assert ( | ||
ensure_specified_sql_driver("sqlite+aiosqlite://:memory:") | ||
== "sqlite+aiosqlite://:memory:" | ||
) | ||
assert ( | ||
ensure_specified_sql_driver("sqlite://:memory:") | ||
== "sqlite+aiosqlite://:memory:" | ||
) | ||
# Handle SQLite relative URIs | ||
assert ( | ||
ensure_specified_sql_driver("sqlite+aiosqlite:///test.db") | ||
== "sqlite+aiosqlite:///test.db" | ||
) | ||
assert ( | ||
ensure_specified_sql_driver("sqlite:///test.db") | ||
== "sqlite+aiosqlite:///test.db" | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This section is used when tiled is installed like
pip install "tiled[all]"
. These three should also be added to the sectionserver
, below, so that they are included when tiled is installed likepip install "tiled[server]" # server only
.