Ecto analytical coverage

Copy Markdown View Source

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.Query macros and generated by the adapter.
  • Helper/source: expressible through QuackDB.Ecto.Analytics, Ecto fragment/1, or QuackDB source helpers.
  • Raw SQL: DuckDB-native syntax that should be exercised through Repo.query/3 or QuackDB.query/4.

This file is a roadmap, not a claim of complete DuckDB support.

Coverage matrix

AreaFeaturePathSQL generationReal serverStatus
Basic readsselect/where/order/limit/offsetEcto-nativeyesyescovered
Parameterspinned params and raw paramsEcto-native/rawyesyescovered
Joinsinner/left/right/full/crossEcto-nativeyesyescovered
Aggregatescount/sum/avg/min/maxEcto-nativepartialyespartial
Analytical aggregatesmedian/quantile/list/string_agg/arg_max/arg_minHelperyesyescovered
Aggregate filterFILTER (WHERE ...)Ecto-nativeyespartialpartial
Groupinggroup by/havingEcto-nativeyesyescovered
CTEsnon-recursive CTEsEcto-nativeyesyescovered
Windowsrow_number/rank/dense_rank/percent_rank/cume_distEcto-nativeyespartialpartial
Windowslag/lead/first_value/last_value/nth_valueFragment/rawpartialnomissing
Windowscustom frame clausesFragment/rawnonomissing
SourcesCSV/Parquet helpersSource helpersyesyescovered
SourcesJSON/XLSX helpersSource helpersnonomissing
Source analyticssource helper + aggregate/windowEcto-native/sourceyespartialpartial
Nested analyticslist/struct/map functionsFragment/rawpartialnomissing
JSON analyticsjson_extract/path queriesHelper/source/rawyesyespartial
Time seriesdate_trunc/time_bucket/generate_seriesHelper/rawyesyespartial
Grouping extensionsgrouping sets/rollup/cubeRaw SQLnoyespartial
QUALIFYwindow filteringRaw SQLnoyespartial
Pivotingpivot/unpivotRaw SQLnoyespartial
Samplingusing sampleRaw SQLnoyespartial
Set operationsunion/intersect/exceptEcto combinationsexplicit errornounsupported
Advanced joinssemi/anti/asof/positionalRaw SQLnonomissing
DuckDB select extensions* EXCLUDE, * REPLACE, COLUMNS(*)Raw SQLnonomissing
Introspectionsummarize/describe/explain/pragmaRaw SQLnonomissing

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.exs

Use 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:

  1. raw SQL through Repo.query/3 or QuackDB.query/4;
  2. QuackDB.Ecto.Analytics for common DuckDB analytical expressions;
  3. source helpers for table functions such as CSV/Parquet/JSON;
  4. fragment/1 for expressions inside otherwise-normal Ecto queries;
  5. 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.