QuackDB's Ecto adapter is intentionally analytical and read-oriented. DuckDB's SQL surface is much larger than Ecto's native query AST, so coverage is tracked in three buckets:
- Ecto-native: expressible with normal
Ecto.Querymacros and generated by the adapter. - Helper/source: expressible through
QuackDB.Ecto.Analytics, Ectofragment/1, or QuackDB source helpers. - Raw SQL: DuckDB-native syntax that should be exercised through
Repo.query/3orQuackDB.query/4.
This file is a roadmap, not a claim of complete DuckDB support.
Coverage matrix
| Area | Feature | Path | SQL generation | Real server | Status |
|---|---|---|---|---|---|
| Basic reads | select/where/order/limit/offset | Ecto-native | yes | yes | covered |
| Parameters | pinned params and raw params | Ecto-native/raw | yes | yes | covered |
| Joins | inner/left/right/full/cross | Ecto-native | yes | yes | covered |
| Aggregates | count/sum/avg/min/max | Ecto-native | partial | yes | partial |
| Analytical aggregates | median/quantile/list/string_agg/arg_max/arg_min | Helper | yes | yes | covered |
| Aggregate filter | FILTER (WHERE ...) | Ecto-native | yes | partial | partial |
| Grouping | group by/having | Ecto-native | yes | yes | covered |
| CTEs | non-recursive CTEs | Ecto-native | yes | yes | covered |
| Windows | row_number/rank/dense_rank/percent_rank/cume_dist | Ecto-native | yes | partial | partial |
| Windows | lag/lead/first_value/last_value/nth_value | Fragment/raw | partial | no | missing |
| Windows | custom frame clauses | Fragment/raw | no | no | missing |
| Sources | CSV/Parquet helpers | Source helpers | yes | yes | covered |
| Sources | JSON/XLSX helpers | Source helpers | no | no | missing |
| Source analytics | source helper + aggregate/window | Ecto-native/source | yes | partial | partial |
| Nested analytics | list/struct/map functions | Fragment/raw | partial | no | missing |
| JSON analytics | json_extract/path queries | Helper/source/raw | yes | yes | partial |
| Time series | date_trunc/time_bucket/generate_series | Helper/raw | yes | yes | partial |
| Grouping extensions | grouping sets/rollup/cube | Raw SQL | no | yes | partial |
| QUALIFY | window filtering | Raw SQL | no | yes | partial |
| Pivoting | pivot/unpivot | Raw SQL | no | yes | partial |
| Sampling | using sample | Raw SQL | no | yes | partial |
| Set operations | union/intersect/except | Ecto combinations | explicit error | no | unsupported |
| Advanced joins | semi/anti/asof/positional | Raw SQL | no | no | missing |
| DuckDB select extensions | * EXCLUDE, * REPLACE, COLUMNS(*) | Raw SQL | no | no | missing |
| Introspection | summarize/describe/explain/pragma | Raw SQL | no | no | missing |
Test organization
Analytical coverage should stay split by expression path:
test/quack_db/ecto/sql_generation/
analytical_test.exs
aggregates_test.exs
fragments_test.exs
source_analytics_test.exs
sources_test.exs
window_functions_test.exs
test/quack_db/integration/
analytical_sql_test.exs
ecto_query_test.exs
ecto_source_analytics_test.exsUse SQL generation tests to pin what QuackDB emits for Ecto-native queries. Use real-server tests for DuckDB-native semantics and raw SQL pass-through.
Boundaries
QuackDB should not try to reimplement all DuckDB syntax as Ecto macros. For DuckDB-specific syntax that Ecto cannot represent cleanly, prefer:
- raw SQL through
Repo.query/3orQuackDB.query/4; QuackDB.Ecto.Analyticsfor common DuckDB analytical expressions;- source helpers for table functions such as CSV/Parquet/JSON;
fragment/1for expressions inside otherwise-normal Ecto queries;- explicit unsupported errors for Ecto AST shapes that would generate misleading SQL.
Future adapter-specific helpers may make sense for repeated patterns such as QUALIFY, lakehouse sources, staging, or Arrow handoff, but those should be added only after the protocol and result semantics are stable.