{"id":16592418,"url":"https://github.com/hauleth/ecto_function","last_synced_at":"2026-03-08T01:06:12.166Z","repository":{"id":49543358,"uuid":"107242637","full_name":"hauleth/ecto_function","owner":"hauleth","description":"Simple macro for generating SQL's functions macro wrappers","archived":false,"fork":false,"pushed_at":"2024-02-19T08:20:12.000Z","size":42,"stargazers_count":53,"open_issues_count":2,"forks_count":6,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-09-23T23:55:48.326Z","etag":null,"topics":["ecto","elixir","elixir-lang","functions","hacktoberfest","macros","postgresql","sql"],"latest_commit_sha":null,"homepage":"https://hex.pm/packages/ecto_function","language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hauleth.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2017-10-17T08:53:08.000Z","updated_at":"2025-06-26T11:37:58.000Z","dependencies_parsed_at":"2024-02-19T09:33:34.389Z","dependency_job_id":"c607a422-84ca-429b-9c22-853c121811d5","html_url":"https://github.com/hauleth/ecto_function","commit_stats":{"total_commits":21,"total_committers":2,"mean_commits":10.5,"dds":0.09523809523809523,"last_synced_commit":"9faee5016902c5eb6733c24db554c40f28179a45"},"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/hauleth/ecto_function","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hauleth%2Fecto_function","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hauleth%2Fecto_function/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hauleth%2Fecto_function/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hauleth%2Fecto_function/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hauleth","download_url":"https://codeload.github.com/hauleth/ecto_function/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hauleth%2Fecto_function/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30240345,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-08T00:58:18.660Z","status":"ssl_error","status_checked_at":"2026-03-08T00:55:48.608Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ecto","elixir","elixir-lang","functions","hacktoberfest","macros","postgresql","sql"],"created_at":"2024-10-11T23:20:51.473Z","updated_at":"2026-03-08T01:06:12.143Z","avatar_url":"https://github.com/hauleth.png","language":"Elixir","readme":"# Ecto.Function\n\n[![Hex.pm](https://img.shields.io/hexpm/dt/ecto_function.svg)](https://hex.pm/packages/ecto_function)\n[![Travis](https://img.shields.io/travis/hauleth/ecto_function.svg)](https://travis-ci.org/hauleth/ecto_function)\n\nHelper macro for defining macros that simplifies calling DB functions.\n\n## Installation\n\nThe package can be installed by adding `ecto_function` to your list of dependencies in `mix.exs`:\n\n```elixir\ndef deps do\n  [\n    {:ecto_function, \"~\u003e 1.0.1\"}\n  ]\nend\n```\n\nThe docs can be found at \u003chttps://hexdocs.pm/ecto_function\u003e.\n\n## Usage\n\nWhen you use a lot of DB functions inside your queries then this probably looks\nlike this:\n\n```elixir\nfrom item in \"items\",\n  where: fragment(\"date_trunc(?, ?)\", \"hour\", item.inserted_at) \u003c fragment(\"date_trunc(?, ?)\", \"hour\", fragment(\"now()\")),\n  select: %{regr: fragment(\"regr_sxy(?, ?)\", item.y, item.x)}\n```\n\nThere are a lot of `fragment` calls which makes code quite challenging to read.\nHowever there is way out for such code, you can write macros:\n\n```elixir\ndefmodule Foo do\n  defmacro date_trunc(part, field) do\n    quote do: fragment(\"date_trunc(?, ?)\", ^part, ^field)\n  end\n\n  defmacro now do\n    quote do: fragment(\"now()\")\n  end\n\n  defmacro regr_sxy(y, x) do\n    quote do: fragment(\"regr_sxy(y, x)\", ^y, ^x)\n  end\nend\n```\n\nAnd then cleanup your query to:\n\n```elixir\nimport Foo\nimport Ecto.Query\n\nfrom item in \"items\",\n  where: date_trunc(\"hour\", item.inserted_at) \u003c date_trunc(\"hour\", now()),\n  select: %{regr: regr_sxy(item.y, item.x)}\n```\n\nHowever there is still a lot of repetition in your new fancy helper module. You\nneed to repeat function name twice, name each argument, insert all that carets\nand stuff.\n\nWhat about little help?\n\n```elixir\ndefmodule Foo do\n  import Ecto.Function\n\n  defqueryfunc date_trunc(part, field)\n  defqueryfunc now\n  defqueryfunc regr_sxy/2\nend\n```\n\nMuch cleaner…\n\n## Reasoning\n\n[Your DB is powerful](http://modern-sql.com/slides). Really. A lot of\ncomputations can be done there. There is whole [chapter][chapter] dedicated to\ndescribing all PostgreSQL functions and Ecto supports only few of them:\n\n- `sum`\n- `avg`\n- `min`\n- `max`\n\nTo be exact. Saying that we have \"limited choice\" would be disrespectful to DB\nsystems like PostgreSQL or Oracle. Of course Ecto core team have walid reasoning\nto support only that much functions: these are available in probably any DB\nsystem ever, so supporting them directly in library is no brainer. However you\nas end-user shouldn't be limited to so small set. Let's be honest, you probably\nwill never change your DB engine, and if you do so, then you probably rewrite\nwhile system from the ground. So this is why this module was created. To provide\nyou access to all functions in your SQL DB (could work with NoSQL DB also, but I\ntest only against PostgreSQL).\n\nFor completeness you can also check [Ecto.OLAP][olap] which provide helpers for\nsome more complex functionalities like `GROUPING` (and in near future also\nwindow functions).\n\n### But why not introduce that directly to Ecto?\n\nBecause there is no need. Personally I would like to see Ecto splitted a little,\nlike changesets should be in separate library in my humble opinion. Also I\nbelieve that such PR would never be merged as \"non scope\" for the reasons I gave\nearlier.\n\n[chapter]: https://www.postgresql.org/docs/current/static/functions.html \"Chapter 9. Functions and Operators\"\n[olap]: https://github.com/hauleth/ecto_olap\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhauleth%2Fecto_function","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhauleth%2Fecto_function","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhauleth%2Fecto_function/lists"}