Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
75 commits
Select commit Hold shift + click to select a range
8810072
Checkpoint: Initial adapter bootstrapping and e2e tests with Docker C…
mdrakiburrahman Mar 30, 2026
04438af
Fixed catalog gen and add some steps for accessing dbt UI
mdrakiburrahman Mar 30, 2026
44448ab
Materialize Adventureworks as Delta Table and use DuckDB to assert ro…
mdrakiburrahman Mar 30, 2026
6635196
Adding a Kafka sales table and ensuring it fires IVM
mdrakiburrahman Mar 30, 2026
e5af63c
Materialize the Kafka topic as Delta table and use that instead in th…
mdrakiburrahman Mar 30, 2026
709b25a
Use sqlglot instead of brittle RegEx to parse Feldera SQL dialect
mdrakiburrahman Mar 31, 2026
04b7b38
Break apart contributing and customer facing README
mdrakiburrahman Mar 31, 2026
a06c699
Update changelog
mdrakiburrahman Mar 31, 2026
d8afa71
Merge branch 'main' into dev/mdrrahman/dbt-feldera
mdrakiburrahman Mar 31, 2026
0283a3d
Proofread
mdrakiburrahman Mar 31, 2026
34d0e35
Remove test_string_size override to implement the base behavior
mdrakiburrahman Mar 31, 2026
7ceaa8f
Differentiate between float vs numeric
mdrakiburrahman Apr 1, 2026
3fb8dcc
Update docstring to mention Feldera transactions
mdrakiburrahman Apr 1, 2026
56de322
Use NOW and add a test for it
mdrakiburrahman Apr 1, 2026
a870d0b
Update docstring for the expand column types
mdrakiburrahman Apr 1, 2026
22fd48e
Use better type inference in seed via _infer_column_types.
mdrakiburrahman Apr 1, 2026
c10e3d0
Add an idempotent seed uploader and downloader
mdrakiburrahman Apr 1, 2026
dc4df22
Remove seeds from git in origin
mdrakiburrahman Apr 1, 2026
24c7b86
Remove the models and macros as well
mdrakiburrahman Apr 1, 2026
ec8cf4c
Add a gitkeep to the seed folders so they are visible in git tree
mdrakiburrahman Apr 1, 2026
044063c
Merge branch 'main' into dev/mdrrahman/dbt-feldera
mdrakiburrahman Apr 1, 2026
3f6809b
Remove GitHub action changes - no tests in publish and remove CI test…
mdrakiburrahman Apr 1, 2026
0c70a30
Use the ci-post-release.yml sed to change the version
mdrakiburrahman Apr 1, 2026
2f2dcb9
Update changelog
mdrakiburrahman Apr 1, 2026
ec20ba2
Use Pipeline client instead of FelderaClient.get_pipeline and a few o…
mdrakiburrahman Apr 1, 2026
8046bf6
compiling_states needs to be a tuple in PipelineStateManager due to P…
mdrakiburrahman Apr 1, 2026
a07217d
Attempt to lint for CI pipeline
mdrakiburrahman Apr 1, 2026
2cafef7
Merge branch 'main' into dev/mdrrahman/dbt-feldera
mdrakiburrahman Apr 1, 2026
fd88b16
Merge branch 'main' into dev/mdrrahman/dbt-feldera
mdrakiburrahman Apr 2, 2026
8700b56
fix(py): fix ruff isort import ordering in dbt-feldera
mdrakiburrahman Apr 3, 2026
7e05d2f
Merge branch 'main' into dev/mdrrahman/dbt-feldera
mdrakiburrahman Apr 5, 2026
0280c4d
fix(py): pin ruff==0.9.10 in dbt-feldera to match CI pre-commit
mdrakiburrahman Apr 5, 2026
f698020
Update docstring to make it clear that this adapter uses continuous q…
mdrakiburrahman Apr 5, 2026
d94f0c8
Add documentation for TYPE_LABELS
mdrakiburrahman Apr 5, 2026
b5fb950
Update param docstring for auto_begin
mdrakiburrahman Apr 5, 2026
9ecf1b2
Turn positional tuples into a ColumnDescription NamedTuple
mdrakiburrahman Apr 5, 2026
8413b74
Add a docstring to connection.execute that it delegates to the cursor…
mdrakiburrahman Apr 5, 2026
018cd38
Update docstring for cursor.execute
mdrakiburrahman Apr 5, 2026
64afc65
Add a docstring to SqlIntent to make it clear which enum is supported…
mdrakiburrahman Apr 5, 2026
5c3dd4e
Add a small docstring to DATA_INGRESS
mdrakiburrahman Apr 5, 2026
de5b06f
Merge branch 'main' into dev/mdrrahman/dbt-feldera
mdrakiburrahman Apr 7, 2026
1859709
Merge branch 'main' into dev/mdrrahman/dbt-feldera
mdrakiburrahman Apr 8, 2026
4d43b45
Clean .temp dir
mdrakiburrahman Apr 8, 2026
2687e25
Merge branch 'main' into dev/mdrrahman/dbt-feldera
mdrakiburrahman Apr 11, 2026
95a54f7
Merge branch 'main' into dev/mdrrahman/dbt-feldera
mdrakiburrahman Apr 11, 2026
b859260
Merge branch 'main' into dev/mdrrahman/dbt-feldera
mdrakiburrahman Apr 12, 2026
6f68d81
Merge branch 'feldera:main' into dev/mdrrahman/dbt-feldera
mdrakiburrahman Apr 13, 2026
0a45510
Merge branch 'main' into dev/mdrrahman/dbt-feldera
mdrakiburrahman Apr 14, 2026
1d8fdcd
Move DuckDB into a container for tests so we don't need host mount
mdrakiburrahman Apr 14, 2026
749e793
Add adventureworks SQL scripts to git, remove .gitkeep files
mdrakiburrahman Apr 15, 2026
9aa8846
Pass 1 through PR review comments
mdrakiburrahman Apr 15, 2026
37f077e
Implement Generator in sqlglot to override FLOAT and map it to REAL
mdrakiburrahman Apr 15, 2026
edf302b
Merge branch 'main' into dev/mdrrahman/dbt-feldera
mdrakiburrahman Apr 15, 2026
a64ae10
Bump version to 0.288.0
mdrakiburrahman Apr 15, 2026
da6aa5e
Map FLOAT to REAL in dbt macro
mdrakiburrahman Apr 15, 2026
ca62160
Update README
mdrakiburrahman Apr 15, 2026
29c6c7c
Remove incremental materialization support, it's not required in Feldera
mdrakiburrahman Apr 15, 2026
da853cb
Changed Jinja macro to stored = true
mdrakiburrahman Apr 15, 2026
28fa16f
Remove ambiguous "registered" reference
mdrakiburrahman Apr 15, 2026
ac59e4d
Make TestFelderaColumn dynamic
mdrakiburrahman Apr 15, 2026
b5482d3
Remove external from FelderaRelationType
mdrakiburrahman Apr 15, 2026
7465e32
Remove test for no columns
mdrakiburrahman Apr 15, 2026
a6f2801
Factor out CATALOG_COLUMNS
mdrakiburrahman Apr 15, 2026
e4c50f7
Remove INTERVAL mapping in agate and run integration tests green
mdrakiburrahman Apr 15, 2026
dc3416c
Add a _wait_for_pipeline_idle to deterministically poll pipeline to p…
mdrakiburrahman Apr 15, 2026
b0150a6
Add lattice tests that are data driven
mdrakiburrahman Apr 15, 2026
3f04fb6
Rename test to test_remove_nonexistent_does_not_throw
mdrakiburrahman Apr 15, 2026
393d5cd
Crash test if Kafka topic isn't up and dump logs
mdrakiburrahman Apr 15, 2026
2d8c874
Update docstring for update_with_views
mdrakiburrahman Apr 15, 2026
ab70529
Lint
mdrakiburrahman Apr 15, 2026
61123e3
Dupe line
mdrakiburrahman Apr 16, 2026
05e7eb5
Remove NOW and use MD5 hash
mdrakiburrahman Apr 16, 2026
e4e07b6
There is no relationship between connectors and views being stored
mdrakiburrahman Apr 16, 2026
e1ce519
Add DBT_THREADS for faster integration tests
mdrakiburrahman Apr 16, 2026
b0dca82
Ruff the integration test folder
mdrakiburrahman Apr 16, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Fixed catalog gen and add some steps for accessing dbt UI
  • Loading branch information
mdrakiburrahman committed Mar 30, 2026
commit 04438aff438bbd7f7509e1a665748ecd914cc18f
28 changes: 20 additions & 8 deletions python/dbt-feldera/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,13 @@ my_project:

## Materializations

| Materialization | Feldera object |
| -------------------- | ---------------------------- |
| `view` | `CREATE VIEW` |
| `table` | `CREATE TABLE` (input) |
| `incremental` | `CREATE MATERIALIZED VIEW` |
| `streaming_pipeline` | Full pipeline program |
| `seed` | Table + HTTP ingress push |
| Materialization | Feldera object |
| -------------------- | -------------------------- |
| `view` | `CREATE VIEW` |
| `table` | `CREATE TABLE` (input) |
| `incremental` | `CREATE MATERIALIZED VIEW` |
| `streaming_pipeline` | Full pipeline program |
| `seed` | Table + HTTP ingress push |

## Development
Comment thread
mdrakiburrahman marked this conversation as resolved.
Outdated

Expand All @@ -55,4 +55,16 @@ cd python/dbt-feldera
.scripts/run.sh unit-test # pytest unit tests
.scripts/run.sh integration-test # pytest integration
.scripts/run.sh e2e # dbt CLI end-to-end test
```
```

### Environment variables

| Variable | Default | Used by | Description |
| --------------------- | ---------------------------------------------------- | ------------------------- | ----------------------------------------------------------------------- |
| `FELDERA_URL` | `http://localhost:8080` | `run.sh`, e2e | Feldera API base URL |
| `FELDERA_SKIP_DOCKER` | _(unset)_ | `run.sh integration-test` | Set to `1` to skip Docker start/stop (use an external Feldera instance) |
| `FELDERA_IMAGE` | `images.feldera.com/feldera/pipeline-manager:latest` | docker-compose | Docker image for the Feldera container |
| `FELDERA_PORT` | `8080` | docker-compose | Host port mapped to the Feldera container |
| `RUST_LOG` | `info` | docker-compose | Log level inside the Feldera container |
| `SKIP_TEARDOWN` | _(unset)_ | e2e (`run-dbt-local.sh`) | Set to `1` to keep Feldera running after the e2e test and print UI URLs |
| `DBT_DOCS_PORT` | `18081` | e2e (`run-dbt-local.sh`) | Host port suggested for `dbt docs serve` |
24 changes: 12 additions & 12 deletions python/dbt-feldera/dbt/adapters/feldera/impl.py
Original file line number Diff line number Diff line change
Expand Up @@ -348,18 +348,18 @@ def _get_one_catalog(
columns = self.get_columns_in_relation(relation)
for idx, col in enumerate(columns, start=1):
rows.append(
[
relation.database,
relation.schema,
relation.identifier,
str(relation.type),
None,
None,
col.name,
idx,
col.dtype,
None,
]
{
"table_database": relation.database,
"table_schema": relation.schema,
"table_name": relation.identifier,
"table_type": str(relation.type),
"table_comment": None,
"table_owner": None,
"column_name": col.name,
"column_index": idx,
"column_type": col.dtype,
"column_comment": None,
}
)

table = table_from_data(rows, catalog_columns)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ version: 2
sources:
- name: adventureworks_seed
description: "Seed data for the AdventureWorks project (loaded via dbt seed)"
schema: dbt_adventureworks
schema: adventureworks
tables:
# Date
- name: calendar_date
Expand Down
47 changes: 46 additions & 1 deletion python/dbt-feldera/integration_tests/scripts/run-dbt-local.sh
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ _teardown() {
_compose down -v --remove-orphans 2>/dev/null || true
}

trap _teardown EXIT
if [[ "${SKIP_TEARDOWN:-}" != "1" ]]; then
trap _teardown EXIT
fi

echo "============================================"
echo " dbt-feldera end-to-end test"
Expand Down Expand Up @@ -82,9 +84,52 @@ echo ""
echo "[5/5] Generating docs..."
dbt docs generate --target "${TARGET}"

DBT_DOCS_PORT="${DBT_DOCS_PORT:-18081}"
FELDERA_HOST_PORT="${FELDERA_PORT:-8080}"

echo ""
echo "============================================"
echo " All dbt commands completed successfully."
echo "============================================"
echo ""
echo " To browse the dbt documentation:"
echo ""
echo " # 1. Create & activate a virtual environment"
echo " uv venv /tmp/dbt-docs-venv"
echo " source /tmp/dbt-docs-venv/bin/activate"
echo ""
echo " # 2. Install dbt-feldera"
echo " uv pip install dbt-core $(ls "${ADAPTER_DIR}"/dist/*.whl | head -1)"
echo ""
echo " # 3. Serve the docs"
echo " cd ${PROJECT_DIR}"
echo " export DBT_PROFILES_DIR=${PROJECT_DIR}"
echo " dbt docs serve --port ${DBT_DOCS_PORT}"
echo ""
echo " # 4. Open in your browser"
echo " # http://localhost:${DBT_DOCS_PORT}"
echo ""

if [[ "${SKIP_TEARDOWN:-}" == "1" ]]; then
echo " ┌──────────────────────────────────────────┐"
echo " │ SKIP_TEARDOWN=1 — Feldera is still up │"
echo " └──────────────────────────────────────────┘"
echo ""
echo " ┌──────────┬──────────────────────────────────┐"
echo " │ UI │ URL │"
echo " ├──────────┼──────────────────────────────────┤"
printf " │ Feldera │ %-32s │\n" "http://localhost:${FELDERA_HOST_PORT}"
printf " │ dbt docs │ %-32s │\n" "http://localhost:${DBT_DOCS_PORT}"
echo " └──────────┴──────────────────────────────────┘"
echo ""
echo " NOTE: If you are running inside WSL, make sure the ports"
echo " (${FELDERA_HOST_PORT}, ${DBT_DOCS_PORT}) are forwarded to your"
echo " Windows host. In VS Code this happens automatically via the"
echo " Ports tab."
echo ""
echo " When done, tear down Feldera manually:"
echo " docker compose -f ${COMPOSE_FILE} -p ${PROJECT_NAME} down -v --remove-orphans"
echo ""
fi

deactivate
121 changes: 121 additions & 0 deletions python/dbt-feldera/tests/unit/test_catalog.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import unittest
from unittest.mock import MagicMock

from dbt.adapters.feldera.column import FelderaColumn
from dbt.adapters.feldera.impl import FelderaAdapter
from dbt.adapters.feldera.relation import FelderaRelation

CATALOG_COLUMNS = [
"table_database",
"table_schema",
"table_name",
"table_type",
"table_comment",
"table_owner",
"column_name",
"column_index",
"column_type",
"column_comment",
]


class TestGetOneCatalog(unittest.TestCase):
"""Tests for FelderaAdapter._get_one_catalog."""

def _build_adapter_mock(self, relations, columns_by_relation):
"""Return a mock that looks enough like a FelderaAdapter."""
adapter = MagicMock(spec=FelderaAdapter)
adapter.Relation = FelderaRelation
adapter.list_relations_without_caching = MagicMock(return_value=relations)
adapter.get_columns_in_relation = MagicMock(side_effect=lambda r: columns_by_relation.get(r.identifier, []))
adapter._catalog_filter_table = MagicMock(side_effect=lambda table, _: table)
# Bind the real method so we can call it
adapter._get_one_catalog = FelderaAdapter._get_one_catalog.__get__(adapter)
return adapter

def _make_info_schema(self, database="default"):
info = MagicMock()
info.database = database
return info

def test_empty_schemas(self):
"""No schemas → empty catalog."""
adapter = self._build_adapter_mock([], {})
info = self._make_info_schema()
table = adapter._get_one_catalog(info, set(), frozenset())
self.assertEqual(len(table), 0)
self.assertEqual(list(table.column_names), CATALOG_COLUMNS)

def test_schema_with_no_relations(self):
"""A schema exists but has no relations → empty catalog."""
adapter = self._build_adapter_mock([], {})
info = self._make_info_schema()
table = adapter._get_one_catalog(info, {"my_pipeline"}, frozenset())
self.assertEqual(len(table), 0)

def test_single_relation_with_columns(self):
"""One relation with two columns → two catalog rows with correct data."""
rel = FelderaRelation.create(database="default", schema="my_pipeline", identifier="users")
cols = [
FelderaColumn(column="id", dtype="INTEGER"),
Comment thread
mdrakiburrahman marked this conversation as resolved.
FelderaColumn(column="name", dtype="VARCHAR"),
]
adapter = self._build_adapter_mock([rel], {"users": cols})
info = self._make_info_schema()

table = adapter._get_one_catalog(
info,
{"my_pipeline"},
frozenset(),
)

self.assertEqual(len(table), 2)
self.assertEqual(list(table.column_names), CATALOG_COLUMNS)

row0 = dict(zip(table.column_names, table.rows[0].values()))
self.assertEqual(row0["table_database"], "default")
self.assertEqual(row0["table_schema"], "my_pipeline")
self.assertEqual(row0["table_name"], "users")
self.assertEqual(row0["column_name"], "id")
self.assertEqual(row0["column_index"], 1)
self.assertEqual(row0["column_type"], "INTEGER")

row1 = dict(zip(table.column_names, table.rows[1].values()))
self.assertEqual(row1["column_name"], "name")
self.assertEqual(row1["column_index"], 2)
self.assertEqual(row1["column_type"], "VARCHAR")

def test_multiple_relations(self):
"""Two relations → catalog contains rows for both."""
rel_users = FelderaRelation.create(database="default", schema="pipe", identifier="users")
rel_orders = FelderaRelation.create(database="default", schema="pipe", identifier="orders")
cols_users = [FelderaColumn(column="id", dtype="INTEGER")]
cols_orders = [
FelderaColumn(column="order_id", dtype="BIGINT"),
FelderaColumn(column="total", dtype="DECIMAL"),
]
adapter = self._build_adapter_mock(
[rel_users, rel_orders],
{"users": cols_users, "orders": cols_orders},
)
info = self._make_info_schema()

table = adapter._get_one_catalog(info, {"pipe"}, frozenset())

self.assertEqual(len(table), 3)
names = [row["table_name"] for row in table]
self.assertIn("users", names)
self.assertIn("orders", names)

def test_relation_with_no_columns(self):
"""Relation with no columns → no rows for that relation."""
Comment thread
mdrakiburrahman marked this conversation as resolved.
Outdated
rel = FelderaRelation.create(database="default", schema="pipe", identifier="empty_table")
adapter = self._build_adapter_mock([rel], {"empty_table": []})
info = self._make_info_schema()

table = adapter._get_one_catalog(info, {"pipe"}, frozenset())
self.assertEqual(len(table), 0)


if __name__ == "__main__":
unittest.main()