{"id":21346875,"url":"https://github.com/queer/lethe","last_synced_at":"2025-07-12T17:31:23.668Z","repository":{"id":57515649,"uuid":"326272320","full_name":"queer/lethe","owner":"queer","description":"A vaguely-friendly query DSL for Mnesia","archived":false,"fork":false,"pushed_at":"2021-01-12T08:13:07.000Z","size":56,"stargazers_count":12,"open_issues_count":1,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-04-24T02:02:38.454Z","etag":null,"topics":["elixir","erlang","matchspecs","mnesia","query-dsl","query-language"],"latest_commit_sha":null,"homepage":"","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/queer.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}},"created_at":"2021-01-02T21:15:40.000Z","updated_at":"2022-09-11T16:19:14.000Z","dependencies_parsed_at":"2022-08-30T04:20:50.893Z","dependency_job_id":null,"html_url":"https://github.com/queer/lethe","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/queer%2Flethe","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/queer%2Flethe/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/queer%2Flethe/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/queer%2Flethe/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/queer","download_url":"https://codeload.github.com/queer/lethe/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225829064,"owners_count":17530666,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["elixir","erlang","matchspecs","mnesia","query-dsl","query-language"],"created_at":"2024-11-22T02:11:49.399Z","updated_at":"2024-11-22T02:11:49.985Z","avatar_url":"https://github.com/queer.png","language":"Elixir","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Lethe\n\n\u003e Lethe\n\u003e /ˈli θi/ • *noun* \u003csup\u003e\u003csup\u003e(try it with [IPA Reader](http://ipa-reader.xyz))\u003c/sup\u003e\u003c/sup\u003e\n\u003e 1. *Classical Mythology.* A river in Hades whose water caused forgetfulness of the past in those who drank of it.\n\nA marginally-better (WIP) query DSL for Mnesia. Originally implemented for\n[신경](https://singyeong.org).\n\nMatchspecs suck, so this is a sorta-better alternative.\n\n**WARNING:** Currently, only read operations are supported. This may or may not\nchange in the future.\n\n### Things that may trip you up\n\n- The map functions `is_map_key` and `map_get` take arguments in the order\n  `(key, map)`, NOT `(map, key)`!\n\n## Roadmap\n\n- [x] Select all fields of a record\n- [x] Select some fields of a record\n- [x] Limit number of records returned\n- [x] Query operators\n  - [x] `+`, `-`, `*`, `div`, `rem`, `\u003e`, `\u003e=`, `\u003c`, `\u003c=`, `!=`\n  - [x] Bitwise operators\n  - [x] Tuple, list, and map operators (`map_size`, `hd`, `tl`, `element`, etc.)\n  - [x] Misc. math functions (`abs`, `trunc`, etc.)\n  - [x] Boolean operators\n    - [x] Logical AND/OR/etc.\n    - [x] `is_pid`/`is_binary`/etc.\n- [ ] Write DSL\n\n## Installation\n\n[Get it on Hex.](https://hex.pm/packages/lethe)\n\n[Read the docs.](https://hexdocs.pm/lethe)\n\n## Usage\n\n```Elixir\n# Create a table...\ntable = :table\n:mnesia.create_schema []\n:mnesia.start()\n:mnesia.create_table table, [attributes: [:integer, :string, :map]]\n\n# ...and add some indexes...\n:mnesia.add_table_index table, :integer\n:mnesia.add_table_index table, :string\n:mnesia.add_table_index table, :map\n\n# ...and some test data.\nn = fn -\u003e :rand.uniform 1_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000 end\nfor i \u003c- 1..10_000, do: :mnesia.dirty_write {table, i, \"#{n.()}\", %{i =\u003e \"#{n.()}\"}}\n\n# Now let's run some queries!\n# Lethe's query DSL allows you to use the names of your table attributes,\n# rather than forcing you to think about what their index in the record is, or\n# anything else like that.\n# Currently, Lethe requires that you compile your queries before running them.\n# This is primarily done to aid in debugging, and a `Lethe.compile_and_run/1`\n# is likely to happen in the future.\n\n# Select one record and all its fields\n{:ok, [{integer, string, map}]} =\n  table\n  |\u003e Lethe.new\n  |\u003e Lethe.limit(1)\n  |\u003e Lethe.select_all\n  |\u003e Lethe.compile\n  |\u003e Lethe.run\n\n# Select all fields from all records\n# `Lethe.select_all` and `Lethe.limit(:all)` are the default settings.\n{:ok, all_records} =\n  table\n  |\u003e Lethe.new\n  |\u003e Lethe.compile\n  |\u003e Lethe.run\n\n# Select a single field from a single record\n{:ok, [integer]} =\n  table\n  |\u003e Lethe.new\n  |\u003e Lethe.limit(1)\n  |\u003e Lethe.select(:integer)\n  |\u003e Lethe.compile\n  |\u003e Lethe.run\n\n# Select a bunch of records at once\n{:ok, records} =\n  table\n  |\u003e Lethe.new\n  |\u003e Lethe.limit(100)\n  |\u003e Lethe.compile\n  |\u003e Lethe.run\n\n# Select specific fields from a record\n{:ok, [{int, map}, {int, map}]} =\n  table\n  |\u003e Lethe.new\n  |\u003e Lethe.limit(2)\n  |\u003e Lethe.select([:integer, :map])\n  |\u003e Lethe.compile\n  |\u003e Lethe.run\n\n# Now let's use some operators!\n# Lethe internally rewrites all of these expressions into Mnesia guard form.\n\n# Select all values where :integer * 2 \u003c= 10\n{:ok, res} =\n  table\n  |\u003e Lethe.new\n  |\u003e Lethe.select(:integer)\n  |\u003e Lethe.where(:integer * 2 \u003c= 10)\n  |\u003e Lethe.compile\n  |\u003e Lethe.run\n\n# Select all values where :integer * 2 \u003e= 4 and :integer * 2 \u003c= 10\n{:ok, res} =\n  table\n  |\u003e Lethe.new\n  |\u003e Lethe.select(:integer)\n  |\u003e Lethe.where(:integer * 2 \u003e= 4 and :integer * 2 \u003c= 10)\n  |\u003e Lethe.compile\n  |\u003e Lethe.run\n\n# An example of a very complicated query\n{:ok, res} =\n  table\n  |\u003e Lethe.new\n  |\u003e Lethe.select(:integer)\n  |\u003e Lethe.where(\n    :integer * 2 == 666\n      and is_map(:map)\n      and is_map_key(:integer, :map)\n      and map_get(:integer, :map) == :string\n  )\n  |\u003e Lethe.compile\n  |\u003e Lethe.run\n\n# Using external variables in queries\ni = 333\n\n{:ok, res} =\n  table\n  |\u003e Lethe.new\n  |\u003e Lethe.select(:integer)\n  |\u003e Lethe.where(:integer * 2 == ^i * 2)\n  |\u003e Lethe.compile\n  |\u003e Lethe.run\n\n# Using atom literals in queries\n{:ok, res} =\n  table\n  |\u003e Lethe.new\n  |\u003e Lethe.select(:atom)\n  |\u003e Lethe.where(:atom == \u0026:atom)\n  |\u003e Lethe.compile\n  |\u003e Lethe.run\n\n# See the documentation on `Lethe.where/2` for a list of all available ops\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fqueer%2Flethe","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fqueer%2Flethe","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fqueer%2Flethe/lists"}