ExOdata4

An OData v4 query parser and Ecto query builder for Elixir. Parse OData query strings or full URIs and get back Ecto queries ready to execute against your own repo.

Installation

Add ex_odata4 to your dependencies in mix.exs:

def deps do
  [
    {:ex_odata4, "~> 0.1.0"}
  ]
end

Configuration

Tell the library which OData entity names map to your Ecto schemas in config/config.exs:

config :ex_odata4, schemas: %{
  "Orders" => MyApp.Orders,
  "Products" => MyApp.Products
}

The key is the entity name as it appears in the OData URI. The value is the Ecto schema module.

Usage

Parsing a full OData URI

ExOdata4.parse_uri("/Orders?$filter=Amount gt 1000&$top=25&$skip=0")
|> MyApp.Repo.all()

Parsing a query string directly

ExOdata4.get("Orders", "$filter=Status eq 'active'&$orderby=CreatedAt desc&$top=10")
|> MyApp.Repo.all()

Both functions return an %Ecto.Query{}, so you pipe it into your own repo. This means the library has no opinion about your database, connection pool, or repo configuration.

Supported OData query options

Option Example
$filter$filter=Name eq 'John'
$top$top=25
$skip$skip=50
$orderby$orderby=Amount desc

Supported filter operators

Operator Meaning
eq Equal
ne Not equal
gt Greater than
ge Greater than or equal
lt Less than
le Less than or equal
and Logical and
or Logical or

Supported filter functions

Function Example Translates to
containscontains(Name, 'John')LIKE '%John%'
startswithstartswith(Name, 'J')LIKE 'J%'
endswithendswith(Email, '.com')LIKE '%.com'

Functions can be combined with logical operators:

$filter=contains(Name, 'John') and Amount gt 100
$filter=startswith(Status, 'act') or endswith(Email, '.com')

Supported literal types

Not yet supported

The following OData v4 features are not currently implemented:

Query options

Filter functions

Filter operators

Path traversal

Contributions are welcome. Open an issue or PR on GitHub.

Error handling

If a schema name is not found in your config, a descriptive error is raised:

No schema configured for "Orders".

Add it to your config.exs:

    config :ex_odata4, schemas: %{
      "Orders" => MyApp.Orders
    }

License

MIT