Skip to content

Commit b0e3654

Browse files
committed
Add how-to-add-data-source.md
1 parent ae1d2be commit b0e3654

File tree

3 files changed

+107
-0
lines changed

3 files changed

+107
-0
lines changed

ibis-server/docs/CONTRIBUTING.md

+3
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,6 @@ Congratulations :tada::tada: The Canner team thanks you :sparkles:.
4545
Once your PR is merged, your contributions will be worked on the next release.
4646

4747
Now that you are part of the Canner community.
48+
49+
## How to add new data source
50+
Please see [How to Add a New Data Source](how-to-add-data-source.md) for more information.

ibis-server/docs/development.md

+4
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@ To run the tests:
4949
- Run the container: `just docker-run`
5050

5151

52+
## How to add new data source
53+
Please see [How to Add a New Data Source](how-to-add-data-source.md) for more information.
54+
55+
5256
## Troubleshooting
5357
### MS SQL Server Tests
5458
If you're having trouble running tests related to MS SQL Server, you may need to install the appropriate driver. For Linux or macOS, we recommend installing the `unixodbc` and `freetds` packages.
+100
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
# How to Add a New Data Source
2+
3+
4+
## Implementation
5+
6+
We have a file named `data_source.py` located in the `app/model`. This file contains an enum class called `DataSource`.
7+
8+
Your task is to add a new data source to this `DataSource` enum class.
9+
```python
10+
class DataSource(StrEnum):
11+
postgres = auto()
12+
```
13+
Additionally, you need to add the corresponding data source and DTO mapping in the enum class `DataSourceExtension`.
14+
```python
15+
class DataSourceExtension(Enum):
16+
postgres = QueryPostgresDTO
17+
```
18+
Create a new DTO (Data Transfer Object) class in the `model` directory. The `model` directory is located at `app/model` and its contents are defined in the `__init__.py` file.
19+
```python
20+
class QueryPostgresDTO(QueryDTO):
21+
connection_info: ConnectionUrl | PostgresConnectionInfo = connection_info_field
22+
```
23+
The connection info depends on [ibis](https://ibis-project.org/backends/postgresql#ibis.postgres.connect).
24+
```python
25+
class PostgresConnectionInfo(BaseModel):
26+
host: SecretStr = Field(examples=["localhost"])
27+
port: SecretStr = Field(examples=[5432])
28+
database: SecretStr
29+
user: SecretStr
30+
password: SecretStr
31+
```
32+
We use bass model of [Pydantic](https://docs.pydantic.dev/latest/api/base_model/) to support our class definitions.
33+
Pydantic provides a convenient field type called [Secret Types](https://docs.pydantic.dev/2.0/usage/types/secrets/) that can protect the sensitive information.
34+
35+
Return to the `DataSourceExtension` enum class to implement the `get_{data_source}_connection` function.
36+
This function should be specific to your new data source. For example, if you've added a PostgreSQL data source, you might implement a `get_postgres_connection` function.
37+
```python
38+
@staticmethod
39+
def get_postgres_connection(
40+
info: ConnectionUrl | PostgresConnectionInfo,
41+
) -> BaseBackend:
42+
if hasattr(info, "connection_url"):
43+
return ibis.connect(info.connection_url.get_secret_value())
44+
return ibis.postgres.connect(
45+
host=info.host.get_secret_value(),
46+
port=int(info.port.get_secret_value()),
47+
database=info.database.get_secret_value(),
48+
user=info.user.get_secret_value(),
49+
password=info.password.get_secret_value(),
50+
)
51+
```
52+
53+
## Test
54+
55+
After implementing the new data source, you should add a test case to ensure it's working correctly.
56+
57+
Create a new test file `test_postgres.py` in the `tests/routers/v2/connector` directory.
58+
59+
Set up the basic test structure:
60+
```python
61+
import pytest
62+
from fastapi.testclient import TestClient
63+
from app.main import app
64+
65+
pytestmark = pytest.mark.postgres
66+
client = TestClient(app)
67+
```
68+
We use [pytest](https://github.com/pytest-dev/pytest) as our test framework.
69+
You can learn more about the pytest [marker](https://docs.pytest.org/en/stable/example/markers.html) and [fixtures](https://docs.pytest.org/en/stable/explanation/fixtures.html).
70+
71+
If the data source has a Docker image available, you can use [testcontainers-python](https://testcontainers-python.readthedocs.io/en/latest/modules/index.html) to simplify your testing setup:
72+
```python
73+
import pytest
74+
from testcontainers.postgres import PostgresContainer
75+
76+
@pytest.fixture(scope="module")
77+
def postgres(request) -> PostgresContainer:
78+
pg = PostgresContainer("postgres:16-alpine").start()
79+
request.addfinalizer(pg.stop)
80+
return pg
81+
```
82+
83+
Execute the following command to run the test cases and ensure your new feature is working correctly:
84+
```shell
85+
poetry run pytest -m postgres
86+
```
87+
This command runs tests marked with the `postgres` marker.
88+
89+
90+
## Submitting Your Work
91+
92+
After confirming that all tests pass, you can create a Pull Request (PR) to add the new data source to the project.
93+
94+
When creating the PR:
95+
- If you are solving an existing issue, remember to link the PR to that issue.
96+
- If this is a new feature, provide detailed information about the feature in the PR description.
97+
98+
Congratulations! You have successfully added a new data source to the project and created tests to verify its functionality.
99+
100+
Kudos to you, you can create a PR to add a new data source to the project. Reminder to link the PR to the issue if you are solving one or fill the detail information about this feature.

0 commit comments

Comments
 (0)