diff --git a/.credo.exs b/.credo.exs index 16c6df25..faea0351 100644 --- a/.credo.exs +++ b/.credo.exs @@ -31,7 +31,13 @@ "apps/*/test/", "apps/*/web/" ], - excluded: [~r"/_build/", ~r"/deps/", ~r"/node_modules/"] + excluded: [ + ~r"/_build/", + ~r"/deps/", + ~r"/node_modules/", + ~r"/test/codegen/queries/", + ~r"/test/support/scripts/" + ] }, # # Load and configure plugins here: @@ -131,7 +137,7 @@ {Credo.Check.Refactor.MatchInCondition, []}, {Credo.Check.Refactor.NegatedConditionsInUnless, []}, {Credo.Check.Refactor.NegatedConditionsWithElse, []}, - {Credo.Check.Refactor.Nesting, []}, + {Credo.Check.Refactor.Nesting, [max_nesting: 3]}, {Credo.Check.Refactor.UnlessWithElse, []}, {Credo.Check.Refactor.WithClauses, []}, diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 7e5d95e3..f0f1aee9 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -59,12 +59,12 @@ jobs: run: | EDGEDB_VERSION=${EDGEDB_VERSION%%.*} - for migration_file in `ls priv/edgedb/schema/migrations/` + for migration_file in `ls test/support/schema/migrations/` do migration_number=${migration_file%.*} if test ${migration_number} -gt ${EDGEDB_VERSION} then - rm "priv/edgedb/schema/migrations/${migration_file}" + rm "test/support/schema/migrations/${migration_file}" fi done diff --git a/.gitignore b/.gitignore index 66715e07..a669cf68 100644 --- a/.gitignore +++ b/.gitignore @@ -28,4 +28,4 @@ edgedb-*.tar # dialyzer priv/plts/ -examples/ +test/codegen/queries/ diff --git a/CHANGELOG.md b/CHANGELOG.md index d09916ce..07bbff5b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - rendering hints for query errors from EdgeDB. +- support for generating Elixir modules from EdgeQL queries via `mix edgedb.generate`. +- abitility to pass atoms as valid arguments for enums. + +### Changed +- `jason` to be required library, but still configurable. +- `EdgeDB.NamedTuple.to_map/2` to include indexes as keys into result map. ## [0.6.1] - 2023-07-07 @@ -20,6 +26,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - support for `Elixir v1.15` and `Erlang/OTP 26`. +- support for generating Elixir modules from EdgeQL queries via `mix edgedb.generate`. +- abitility to pass atoms as valid arguments for enums. + +### Changed +- `jason` to be required library, but still configurable. +- `EdgeDB.NamedTuple.to_map/2` to include indexes as keys into result map. ### Fixed diff --git a/config/config.exs b/config/config.exs index 68457def..9288ddcc 100644 --- a/config/config.exs +++ b/config/config.exs @@ -1,3 +1,18 @@ import Config import_config("#{Mix.env()}.exs") + +config :edgedb, + generation: [ + queries_path: "test/support/codegen/edgeql/", + output_path: "test/codegen/queries/", + module_prefix: Tests.Codegen.Queries + ] + +# TODO: clean edgedb/edgeql, edgedb/schema, edgedb.toml +# config :edgedb, +# generation: [ +# queries_path: "priv/edgedb/edgeql/", +# output_path: "priv/edgedb/codegen/queries/", +# module_prefix: Tests.Codegen.Queries +# ] diff --git a/edgedb.toml b/edgedb.toml index 17811b37..4344650f 100644 --- a/edgedb.toml +++ b/edgedb.toml @@ -2,4 +2,5 @@ server-version = "3.0" [project] -schema-dir = "./priv/edgedb/schema" +schema-dir = "./test/support/schema" +#schema-dir = "./priv/edgedb/schema" diff --git a/lib/edgedb.ex b/lib/edgedb.ex index 8dfc4c5d..481ec57c 100644 --- a/lib/edgedb.ex +++ b/lib/edgedb.ex @@ -175,6 +175,11 @@ defmodule EdgeDB do """ @type result() :: EdgeDB.Set.t() | term() + @typedoc """ + Parameter types acceptable by `EdgeDB.query*/4` functions. + """ + @type params() :: map() | list() | Keyword.t() + @doc """ Creates a pool of EdgeDB connections linked to the current process. @@ -307,7 +312,7 @@ defmodule EdgeDB do See `t:EdgeDB.query_option/0` for supported options. """ - @spec query(client(), String.t(), list() | Keyword.t(), list(query_option())) :: + @spec query(client(), String.t(), params(), list(query_option())) :: {:ok, result()} | {:error, Exception.t()} def query(client, statement, params \\ [], opts \\ []) do @@ -317,7 +322,8 @@ defmodule EdgeDB do output_format: Keyword.get(opts, :output_format, :binary), required: Keyword.get(opts, :required, false), is_script: Keyword.get(opts, :script, false), - params: params + params: params, + __file__: opts[:__file__] } parse_execute_query(client, q, q.params, opts) @@ -332,7 +338,7 @@ defmodule EdgeDB do See `t:EdgeDB.query_option/0` for supported options. """ - @spec query!(client(), String.t(), list(), list(query_option())) :: result() + @spec query!(client(), String.t(), params(), list(query_option())) :: result() def query!(client, statement, params \\ [], opts \\ []) do client |> query(statement, params, opts) @@ -347,7 +353,7 @@ defmodule EdgeDB do See `t:EdgeDB.query_option/0` for supported options. """ - @spec query_single(client(), String.t(), list(), list(query_option())) :: + @spec query_single(client(), String.t(), params(), list(query_option())) :: {:ok, result()} | {:error, Exception.t()} def query_single(client, statement, params \\ [], opts \\ []) do @@ -363,7 +369,8 @@ defmodule EdgeDB do See `t:EdgeDB.query_option/0` for supported options. """ - @spec query_single!(client(), String.t(), list(), list(query_option())) :: result() + @spec query_single!(client(), String.t(), params(), list(query_option())) :: + result() def query_single!(client, statement, params \\ [], opts \\ []) do client |> query_single(statement, params, opts) @@ -378,7 +385,7 @@ defmodule EdgeDB do See `t:EdgeDB.query_option/0` for supported options. """ - @spec query_required_single(client(), String.t(), list(), list(query_option())) :: + @spec query_required_single(client(), String.t(), params(), list(query_option())) :: {:ok, result()} | {:error, Exception.t()} def query_required_single(client, statement, params \\ [], opts \\ []) do @@ -394,7 +401,7 @@ defmodule EdgeDB do See `t:EdgeDB.query_option/0` for supported options. """ - @spec query_required_single!(client(), String.t(), list(), list(query_option())) :: result() + @spec query_required_single!(client(), String.t(), params(), list(query_option())) :: result() def query_required_single!(client, statement, params \\ [], opts \\ []) do client |> query_required_single(statement, params, opts) @@ -409,7 +416,7 @@ defmodule EdgeDB do See `t:EdgeDB.query_option/0` for supported options. """ - @spec query_json(client(), String.t(), list(), list(query_option())) :: + @spec query_json(client(), String.t(), params(), list(query_option())) :: {:ok, result()} | {:error, Exception.t()} def query_json(client, statement, params \\ [], opts \\ []) do @@ -425,7 +432,7 @@ defmodule EdgeDB do See `t:EdgeDB.query_option/0` for supported options. """ - @spec query_json!(client(), String.t(), list(), list(query_option())) :: result() + @spec query_json!(client(), String.t(), params(), list(query_option())) :: result() def query_json!(client, statement, params \\ [], opts \\ []) do client |> query_json(statement, params, opts) @@ -440,7 +447,7 @@ defmodule EdgeDB do See `t:EdgeDB.query_option/0` for supported options. """ - @spec query_single_json(client(), String.t(), list(), list(query_option())) :: + @spec query_single_json(client(), String.t(), params(), list(query_option())) :: {:ok, result()} | {:error, Exception.t()} def query_single_json(client, statement, params \\ [], opts \\ []) do @@ -456,7 +463,7 @@ defmodule EdgeDB do See `t:EdgeDB.query_option/0` for supported options. """ - @spec query_single_json!(client(), String.t(), list(), list(query_option())) :: result() + @spec query_single_json!(client(), String.t(), params(), list(query_option())) :: result() def query_single_json!(client, statement, params \\ [], opts \\ []) do client |> query_single_json(statement, params, opts) @@ -471,7 +478,7 @@ defmodule EdgeDB do See `t:EdgeDB.query_option/0` for supported options. """ - @spec query_required_single_json(client(), String.t(), list(), list(query_option())) :: + @spec query_required_single_json(client(), String.t(), params(), list(query_option())) :: {:ok, result()} | {:error, Exception.t()} def query_required_single_json(client, statement, params \\ [], opts \\ []) do @@ -487,7 +494,7 @@ defmodule EdgeDB do See `t:EdgeDB.query_option/0` for supported options. """ - @spec query_required_single_json!(client(), String.t(), list(), list(query_option())) :: + @spec query_required_single_json!(client(), String.t(), params(), list(query_option())) :: result() def query_required_single_json!(client, statement, params \\ [], opts \\ []) do client @@ -500,7 +507,7 @@ defmodule EdgeDB do See `t:EdgeDB.query_option/0` for supported options. """ - @spec execute(client(), String.t(), list(), list(query_option())) :: + @spec execute(client(), String.t(), params(), list(query_option())) :: :ok | {:error, Exception.t()} def execute(client, statement, params \\ [], opts \\ []) do opts = Keyword.merge(opts, output_format: :none, script: true, raw: true) @@ -521,7 +528,7 @@ defmodule EdgeDB do See `t:EdgeDB.query_option/0` for supported options. """ - @spec execute!(client(), String.t(), list(), list(query_option())) :: :ok + @spec execute!(client(), String.t(), params(), list(query_option())) :: :ok def execute!(client, statement, params \\ [], opts \\ []) do opts = Keyword.merge(opts, output_format: :none, script: true, raw: true) query!(client, statement, params, opts) @@ -789,7 +796,7 @@ defmodule EdgeDB do end true -> - EdgeDB.Result.extract(result) + EdgeDB.Result.extract(result, Keyword.get(opts, :__transform_result__)) end end diff --git a/lib/edgedb/connection.ex b/lib/edgedb/connection.ex index b8902853..e9582fd2 100644 --- a/lib/edgedb/connection.ex +++ b/lib/edgedb/connection.ex @@ -934,7 +934,13 @@ defmodule EdgeDB.Connection do ) with {:ok, state} <- wait_for_server_ready(state) do - {:ok, %EdgeDB.Query{query | codec_storage: state.codec_storage}, state} + query = %EdgeDB.Query{ + query + | codec_storage: state.codec_storage, + result_cardinality: message.result_cardinality + } + + {:ok, query, state} end end @@ -983,17 +989,19 @@ defmodule EdgeDB.Connection do %Server.V0.PrepareComplete{ input_typedesc_id: in_id, output_typedesc_id: out_id, - headers: %{capabilities: capabilities} + headers: %{capabilities: capabilities}, + cardinality: result_cardinality }, state ) do with {:ok, state} <- wait_for_server_ready(state) do - maybe_legacy_describe_codecs( - %EdgeDB.Query{query | capabilities: capabilities}, - in_id, - out_id, - state - ) + query = %EdgeDB.Query{ + query + | capabilities: capabilities, + result_cardinality: result_cardinality + } + + maybe_legacy_describe_codecs(query, in_id, out_id, state) end end @@ -1062,7 +1070,13 @@ defmodule EdgeDB.Connection do ) with {:ok, state} <- wait_for_server_ready(state) do - {:ok, %EdgeDB.Query{query | codec_storage: state.codec_storage}, state} + query = %EdgeDB.Query{ + query + | codec_storage: state.codec_storage, + result_cardinality: message.result_cardinality + } + + {:ok, query, state} end end @@ -1158,7 +1172,11 @@ defmodule EdgeDB.Connection do query = save_query_with_codecs_in_cache( state.queries_cache, - %EdgeDB.Query{query | capabilities: capabilities}, + %EdgeDB.Query{ + query + | capabilities: capabilities, + result_cardinality: message.result_cardinality + }, message.input_typedesc_id, message.output_typedesc_id ) @@ -1311,7 +1329,11 @@ defmodule EdgeDB.Connection do query = save_query_with_codecs_in_cache( state.queries_cache, - query, + %EdgeDB.Query{ + query + | capabilities: message.capabilities, + result_cardinality: message.result_cardinality + }, message.input_typedesc_id, message.output_typedesc_id ) diff --git a/lib/edgedb/edgeql/generator.ex b/lib/edgedb/edgeql/generator.ex new file mode 100644 index 00000000..a4adfe60 --- /dev/null +++ b/lib/edgedb/edgeql/generator.ex @@ -0,0 +1,570 @@ +defmodule EdgeDB.EdgeQL.Generator do + @moduledoc false + + alias EdgeDB.Protocol.{ + Codecs, + CodecStorage + } + + require EEx + + @builtin_scalars_to_typespecs %{ + Codecs.UUID => {"std::uuid", "binary()"}, + Codecs.Str => {"std::str", "String.t()"}, + Codecs.Bytes => {"std::bytes", "bitstring()"}, + Codecs.Int16 => {"std::int16", "integer()"}, + Codecs.Int32 => {"std::int32", "integer()"}, + Codecs.Int64 => {"std::int64", "integer()"}, + Codecs.Float32 => {"std::float32", "float()"}, + Codecs.Float64 => {"std::float64", "float()"}, + Codecs.Decimal => {"std::decimal", "Decimal.t()"}, + Codecs.Bool => {"std::bool", "boolean()"}, + Codecs.DateTime => {"std::datetime", "DateTime.t()"}, + Codecs.Duration => {"std::duration", "integer()"}, + Codecs.JSON => {"std::json", "any()"}, + Codecs.LocalDateTime => {"cal::local_datetime", "NaiveDateTime.t()"}, + Codecs.LocalDate => {"cal::local_date", "Date.t()"}, + Codecs.LocalTime => {"cal::local_time", "Time.t()"}, + Codecs.BigInt => {"std::bigint", "Decimal.t()"}, + Codecs.RelativeDuration => {"cal::relative_duration", "EdgeDB.RelativeDuration.t()"}, + Codecs.DateDuration => {"cal::date_duration", "EdgeDB.DateDuration.t()"}, + Codecs.ConfigMemory => {"cfg::memory", "EdgeDB.ConfigMemory.t()"}, + Codecs.Vector => {"ext::pgvector::vector", "[float()]"} + } + @scalar_codecs Map.keys(@builtin_scalars_to_typespecs) + + @field_is_implicit Bitwise.bsl(1, 0) + @field_is_link_property Bitwise.bsl(1, 1) + + @types_tab :edgedb_edgeql_gen_types + + @default_output "./lib/" + @cardinality_to_function %{ + no_result: "execute", + at_most_one: "query_single", + one: "query_required_single", + at_least_one: "query", + many: "query" + } + + @query_template Path.join([:code.priv_dir(:edgedb), "codegen", "templates", "query.ex.eex"]) + @shape_template Path.join([:code.priv_dir(:edgedb), "codegen", "templates", "_shape.eex"]) + @schema_template Path.join([:code.priv_dir(:edgedb), "codegen", "templates", "_schema.eex"]) + @builtin_template Path.join([:code.priv_dir(:edgedb), "codegen", "templates", "_builtin.eex"]) + @object_template Path.join([:code.priv_dir(:edgedb), "codegen", "templates", "_object.eex"]) + @set_template Path.join([:code.priv_dir(:edgedb), "codegen", "templates", "_set.eex"]) + + EEx.function_from_file(:defp, :render_query_template, @query_template, [:assigns]) + EEx.function_from_file(:defp, :render_shape_template, @shape_template, [:assigns]) + EEx.function_from_file(:defp, :render_schema_template, @schema_template, [:assigns]) + EEx.function_from_file(:defp, :render_builtin_template, @builtin_template, [:assigns]) + EEx.function_from_file(:defp, :render_object_template, @object_template, [:assigns]) + EEx.function_from_file(:defp, :render_set_template, @set_template, [:assigns]) + + @spec generate(Keyword.t()) :: {:ok, list(Path.t())} | {:error, term()} + def generate(opts) do + silent? = Keyword.get(opts, :silent, false) + + {:ok, client} = + opts + |> Keyword.merge( + max_concurrency: 1, + queue_target: :timer.seconds(30), + queue_interval: :timer.seconds(10) + ) + |> EdgeDB.start_link() + + generation_config = Application.get_env(:edgedb, :generation) + + if Keyword.keyword?(generation_config) do + do_modules_generation(client, generation_config, silent?) + else + Enum.reduce_while(generation_config, {:ok, %{}}, fn config, {:ok, files} -> + case do_modules_generation(client, config, silent?) do + {:ok, new_files} -> + {:cont, {:ok, Map.merge(files, new_files)}} + + error -> + {:halt, error} + end + end) + end + end + + defp do_modules_generation(client, config, silent?) do + queries_path = Keyword.fetch!(config, :queries_path) + + query_files = + [queries_path, "**", "*.edgeql"] + |> Path.join() + |> Path.wildcard() + + DBConnection.run( + client, + fn conn -> + Enum.reduce_while(query_files, {:ok, %{}}, fn query_file, {:ok, files} -> + case generate_module_for_query_file(conn, config, query_file, silent?) do + {:ok, elixir_file} -> + files = Map.put(files, query_file, elixir_file) + {:cont, {:ok, files}} + + {:error, error} -> + {:halt, {:error, {query_file, error}}} + end + end) + end, + timeout: :infinity + ) + end + + defp generate_module_for_query_file(conn, config, query_file, silent?) do + queries_path = Keyword.fetch!(config, :queries_path) + output_path = Keyword.get(config, :output_path, @default_output) + module_prefix = config[:module_prefix] + + statement = File.read!(query_file) + + query_name = + query_file + |> Path.rootname() + |> Path.basename() + + query_parts = + query_file + |> Path.dirname() + |> Path.relative_to(queries_path) + |> Path.split() + |> Enum.reject(&(&1 == ".")) + + file_name = + [output_path, query_parts, query_name] + |> List.flatten() + |> Path.join() + + file_name = "#{file_name}.edgeql.ex" + + if not silent? do + IO.puts("Generating #{file_name} from #{query_file}") + end + + module_parts = + if module_prefix do + List.flatten([Module.split(module_prefix), query_parts, query_name]) + else + List.flatten([query_parts, query_name]) + end + + query = %EdgeDB.Query{ + statement: statement, + required: true, + inline_type_names: true, + __file__: query_file + } + + module_name = Enum.map_join(module_parts, ".", &Macro.camelize/1) + + with {:ok, query} <- DBConnection.prepare(conn, query, edgeql_state: %EdgeDB.Client.State{}), + {:ok, elixir_file} <- generate_elixir_module(query, query_file, file_name, module_name) do + {:ok, elixir_file} + else + {:error, error} -> + {:error, error} + end + end + + defp generate_elixir_module(%EdgeDB.Query{} = query, query_file, output_file, module_name) do + reset_types() + + input_codec = CodecStorage.get(query.codec_storage, query.input_codec) + output_codec = CodecStorage.get(query.codec_storage, query.output_codec) + + {args, positional?} = input_codec_to_args(input_codec, query.codec_storage) + raw_shape = output_codec_to_shape(query, output_codec, query.codec_storage) + raw_schema = shape_to_schema(raw_shape) + complex? = complex_shape?(raw_shape) + final_list? = query.result_cardinality in [:many, :at_least_one] + types = types() + + rendered_shape = + render_shape( + shape: raw_shape, + render_shape: &render_shape/1, + render_builtin: &render_builtin/1, + render_object: &render_object/1, + render_set: &render_set/1, + module_name: module_name + ) + + rendered_schema = + if raw_schema do + render_schema( + schema: raw_schema, + render_schema: &render_schema/1, + paths: [] + ) + else + nil + end + + generated_module = + generate_query_module( + query_file: query_file, + module_name: module_name, + types: types, + shape: rendered_shape, + schema: rendered_schema, + should_render_type_for_shape: rendered_schema && complex?, + cardinality_to_function: @cardinality_to_function, + result_type: + (complex? && final_list? && "list(Result.t())") || (complex? && "Result.t()") || + rendered_shape, + query: %{ + statement: query.statement, + has_positional_args: positional? and length(args) != 0, + has_named_args: not positional? and length(args) != 0, + cardinality: query.result_cardinality, + args: args + } + ) + + output_file + |> Path.dirname() + |> File.mkdir_p!() + + generated_module + |> Code.format_string!() + |> then(&File.write!(output_file, [&1, "\n"])) + + {:ok, output_file} + end + + defp input_codec_to_args(%Codecs.Null{}, _codec_storage) do + {[], false} + end + + defp input_codec_to_args(%Codecs.Object{} = codec, codec_storage) do + positional? = + Enum.reduce_while(codec.shape_elements, false, fn %{name: name}, positional? -> + case Integer.parse(name) do + {_arg_index, ""} -> + {:halt, true} + + _other -> + {:cont, positional?} + end + end) + + args = + codec.shape_elements + |> Enum.zip(codec.codecs) + |> Enum.reduce([], fn {element, codec}, args -> + codec = CodecStorage.get(codec_storage, codec) + + %{typespec: typespec} = codec_to_shape(codec, codec_storage) + + typespec = + case element.cardinality do + :at_most_one -> + "#{typespec} | nil" + + _other -> + typespec + end + + [%{name: element.name, typespec: typespec} | args] + end) + |> Enum.reverse() + + {args, positional?} + end + + defp output_codec_to_shape(%EdgeDB.Query{} = query, codec, codec_storage) do + Map.merge( + %{ + is_list: query.result_cardinality in [:many, :at_least_one], + is_optional: query.result_cardinality == :at_most_one + }, + codec_to_shape(codec, codec_storage) + ) + end + + defp codec_to_shape(%Codecs.Object{} = codec, codec_storage) do + fields = + codec.shape_elements + |> Enum.zip(codec.codecs) + |> Enum.reject(fn {%{flags: flags}, _codec} -> + Bitwise.band(flags, @field_is_implicit) != 0 + end) + |> Enum.with_index() + |> Enum.reduce([], fn {{%{flags: flags} = element, codec}, index}, fields -> + codec = CodecStorage.get(codec_storage, codec) + optional? = element.cardinality == :at_most_one + list? = element.cardinality in [:many, :at_least_one] + + link_property? = Bitwise.band(flags, @field_is_link_property) != 0 + + field_shape = + Map.merge( + %{ + is_list: list?, + is_optional: optional?, + is_link_property: link_property?, + index: index, + is_registered: false + }, + codec_to_shape(codec, codec_storage) + ) + + [{element.name, field_shape} | fields] + end) + |> Enum.reverse() + + %{type: :object, fields: fields} + end + + defp codec_to_shape(%Codecs.Set{} = codec, codec_storage) do + codec = CodecStorage.get(codec_storage, codec.codec) + element_shape = codec_to_shape(codec, codec_storage) + %{type: :set, is_list: true, shape: element_shape} + end + + defp codec_to_shape(%Codecs.UUID{}, _codec_storage) do + typename = "uuid()" + uuid_typespec = @builtin_scalars_to_typespecs[Codecs.UUID] + register_typespec(typename, uuid_typespec) + %{type: :builtin, typespec: typename, is_registered: true} + end + + defp codec_to_shape(%Codecs.JSON{}, _codec_storage) do + typename = "json()" + json_typespec = @builtin_scalars_to_typespecs[Codecs.JSON] + register_typespec(typename, json_typespec) + %{type: :builtin, typespec: typename, is_registered: true} + end + + defp codec_to_shape(%Codecs.Duration{}, _codec_storage) do + timex? = Application.get_env(:edgedb, :timex_duration, true) + + typename = "duration()" + + case Code.ensure_loaded?(Timex) do + true when timex? -> + {typedoc, typespec} = @builtin_scalars_to_typespecs[Codecs.Duration] + register_typespec(typename, {typedoc, ["Timex.Duration.t()", typespec]}) + + _other -> + duration_typespec = @builtin_scalars_to_typespecs[Codecs.Duration] + register_typespec(typename, duration_typespec) + end + + %{type: :builtin, typespec: typename, is_registered: true} + end + + defp codec_to_shape(%Codecs.Vector{}, _codec_storage) do + typename = "vector()" + vector_typespec = @builtin_scalars_to_typespecs[Codecs.Vector] + register_typespec(typename, vector_typespec) + %{type: :builtin, typespec: typename, is_registered: true} + end + + defp codec_to_shape(%codec_name{}, _codec_storage) when codec_name in @scalar_codecs do + %{type: :builtin, typespec: elem(@builtin_scalars_to_typespecs[codec_name], 1)} + end + + defp codec_to_shape(%Codecs.Scalar{codec: subcodec, name: nil}, codec_storage) do + %subcodec_name{} = CodecStorage.get(codec_storage, subcodec) + {_typedoc, subcodec_typespec} = @builtin_scalars_to_typespecs[subcodec_name] + %{type: :builtin, typespec: subcodec_typespec} + end + + defp codec_to_shape(%Codecs.Scalar{codec: subcodec, name: type_name}, codec_storage) do + %subcodec_name{} = CodecStorage.get(codec_storage, subcodec) + + full_type_name = full_name_to_typespec(type_name) + {typedoc, subcodec_typespec} = @builtin_scalars_to_typespecs[subcodec_name] + typedoc = "scalar type #{type_name} extending #{typedoc}" + + register_typespec(full_type_name, {typedoc, subcodec_typespec}) + + %{type: :builtin, typespec: full_type_name, is_registered: true} + end + + defp codec_to_shape(%Codecs.Enum{name: type_name, members: members}, _codec_storage) do + full_type_name = full_name_to_typespec(type_name) + typedoc = "scalar type #{type_name} extending enum<#{Enum.join(members, ", ")}>" + + register_typespec( + full_type_name, + {typedoc, ["String.t()" | Enum.map(members, &":#{inspect(&1)}")]} + ) + + %{type: :builtin, typespec: full_type_name, is_registered: true} + end + + defp codec_to_shape(%Codecs.Array{codec: subcodec}, codec_storage) do + subcodec = CodecStorage.get(codec_storage, subcodec) + %{typespec: typespec} = shape = codec_to_shape(subcodec, codec_storage) + %{type: :builtin, typespec: "[#{typespec}]", element: shape} + end + + defp codec_to_shape(%Codecs.Tuple{codecs: subcodecs}, codec_storage) do + shapes = + Enum.map(subcodecs, fn subcodec -> + subcodec = CodecStorage.get(codec_storage, subcodec) + codec_to_shape(subcodec, codec_storage) + end) + + typespec = "{#{Enum.map_join(shapes, ", ", & &1.typespec)}}" + %{type: :builtin, typespec: typespec, elements: shapes} + end + + defp codec_to_shape(%Codecs.NamedTuple{codecs: subcodecs, elements: elements}, codec_storage) do + shapes = + subcodecs + |> Enum.zip(elements) + |> Enum.with_index() + |> Enum.map(fn {{subcodec, element}, index} -> + subcodec = CodecStorage.get(codec_storage, subcodec) + shape = codec_to_shape(subcodec, codec_storage) + Map.merge(%{name: element.name, index: index}, shape) + end) + + map_elements = + Enum.map_join(shapes, ", ", &":#{&1.name} => #{&1.typespec}, #{&1.index} => #{&1.typespec}") + + typespec = "%{#{map_elements}}" + %{type: :builtin, typespec: typespec, elements: shapes} + end + + defp codec_to_shape(%Codecs.Range{codec: subcodec}, codec_storage) do + subcodec = CodecStorage.get(codec_storage, subcodec) + %{typespec: typespec} = codec_to_shape(subcodec, codec_storage) + %{type: :builtin, typespec: "EdgeDB.Range.t(#{typespec})"} + end + + defp full_name_to_typespec(type_name) do + type_name = + type_name + |> String.split("::", parts: 2) + |> Enum.map_join("__", &Macro.underscore/1) + + "#{type_name}()" + end + + defp complex_shape?(%{type: :builtin}) do + false + end + + defp complex_shape?(%{type: :set, shape: shape}) do + complex_shape?(shape) + end + + defp complex_shape?(%{type: :object}) do + true + end + + defp shape_to_schema(%{type: :set, shape: shape}) do + shape_to_schema(shape) + end + + defp shape_to_schema(%{type: :object, fields: fields}) do + schema = + fields + |> Enum.map(fn {name, shape} -> + case shape_to_schema(shape) do + nil -> + name + + shape -> + {name, shape} + end + end) + |> Enum.sort(:desc) + + case schema do + [] -> + nil + + schema -> + schema + end + end + + defp shape_to_schema(%{type: :builtin, element: element}) do + shape_to_schema(element) + end + + defp shape_to_schema(%{type: :builtin, elements: elements}) do + schema = + elements + |> Enum.map(fn + %{name: name} = element -> + case shape_to_schema(element) do + nil -> + name + + shape -> + {name, shape} + end + + element -> + shape_to_schema(element) + end) + |> Enum.reject(&is_nil/1) + |> Enum.sort(:desc) + + case schema do + [] -> + nil + + schema -> + [:builtin, schema] + end + end + + defp shape_to_schema(%{type: :builtin}) do + nil + end + + defp types do + @types_tab + |> :ets.tab2list() + |> Enum.sort() + |> Enum.reverse() + end + + defp reset_types do + :ets.new(@types_tab, [:named_table]) + rescue + ArgumentError -> + :ets.delete_all_objects(@types_tab) + end + + defp register_typespec(type_name, {typedoc, typespecs}) when is_list(typespecs) do + register_typespec(type_name, {typedoc, Enum.join(typespecs, "|")}) + end + + defp register_typespec(type_name, {typedoc, typespec}) do + :ets.insert(@types_tab, {type_name, {typedoc, typespec}}) + end + + defp generate_query_module(assigns), do: render_query_template(assigns) + + defp render_shape(assigns), + do: assigns |> render_shape_template() |> postprocess_render() + + defp render_schema(assigns), + do: assigns |> render_schema_template() |> postprocess_render() + + defp render_builtin(assigns), + do: assigns |> render_builtin_template() |> postprocess_render() + + defp render_object(assigns), + do: assigns |> render_object_template() |> postprocess_render() + + defp render_set(assigns), + do: assigns |> render_set_template() |> postprocess_render() + + defp postprocess_render(result), + do: result |> String.split("\n") |> Enum.join(" ") |> String.trim() +end diff --git a/lib/edgedb/error.ex b/lib/edgedb/error.ex index 94e4b060..0ef5640b 100644 --- a/lib/edgedb/error.ex +++ b/lib/edgedb/error.ex @@ -237,7 +237,7 @@ defmodule EdgeDB.Error do [:reset, "#{exception.name}: "], [:bright, "#{exception.message}", "\n"], [:blue, "#{String.pad_leading("", padding)} ┌─ "], - [:reset, "query:#{config.line}:#{config.col}", "\n"], + [:reset, "#{config.file}:#{config.line}:#{config.col}", "\n"], [:blue, "#{String.pad_leading("", padding)} │", "\n"] | Enum.reverse(lines) ] @@ -249,7 +249,11 @@ defmodule EdgeDB.Error do "#{exception.name}: #{exception.message}" end - defp generate_render_config(%__MODULE__{} = exception, true, color_errors?) do + defp generate_render_config( + %__MODULE__{query: %EdgeDB.Query{}} = exception, + true, + color_errors? + ) do position_start = case Integer.parse(exception.attributes[:character_start] || "") do {position_start, ""} -> @@ -274,6 +278,7 @@ defmodule EdgeDB.Error do line: exception.attributes[:line_start] || "?", col: exception.attributes[:column_start] || "?", hint: exception.attributes[:hint] || "error", + file: exception.query.__file__ || "query", use_color: color_errors? } end diff --git a/lib/edgedb/protocol.ex b/lib/edgedb/protocol.ex index 4eeca368..f3102301 100644 --- a/lib/edgedb/protocol.ex +++ b/lib/edgedb/protocol.ex @@ -479,6 +479,35 @@ defmodule EdgeDB.Protocol do %Server.ServerKeyData{data: data} end + defp do_type_description_parsing( + <<0xFF::uint8(), id::uuid(), data::binary>>, + codec_storage, + codecs + ) do + rest = + case CodecStorage.get(codec_storage, id) do + %codec_name{} = codec when codec_name in [Codecs.Scalar, Codecs.Enum] -> + {type_name, rest} = do_type_name_parsing(data) + codec = %{codec | name: type_name} + CodecStorage.add(codec_storage, id, codec) + rest + + %codec_name{id: id} -> + raise EdgeDB.InternalClientError.new( + "unable to parse descriptor with type name for #{codec_name} codec: " <> + UUID.binary_to_string!(id) + ) + + nil -> + raise EdgeDB.InternalClientError.new( + "unable to parse descriptor with type name for yet unkown codec: " <> + UUID.binary_to_string!(id) + ) + end + + do_type_description_parsing(rest, codec_storage, Map.put(codecs, map_size(codecs), id)) + end + defp do_type_description_parsing( <>, codec_storage, @@ -626,12 +655,12 @@ defmodule EdgeDB.Protocol do defp do_codec_parsing( 0xFF, - <>, + <>, _id, _codecs, false ) do - {nil, rest} + {type_name, rest} end defp do_codec_parsing( @@ -645,6 +674,10 @@ defmodule EdgeDB.Protocol do {nil, rest} end + defp do_type_name_parsing(data) do + do_codec_parsing(0xFF, data, nil, [], false) + end + defp decode_parameter_status_value("system_config", data) do do_system_config_decoding(data) end diff --git a/lib/edgedb/protocol/codecs/enum.ex b/lib/edgedb/protocol/codecs/enum.ex index c779d5b4..2df9324b 100644 --- a/lib/edgedb/protocol/codecs/enum.ex +++ b/lib/edgedb/protocol/codecs/enum.ex @@ -3,7 +3,11 @@ defmodule EdgeDB.Protocol.Codecs.Enum do alias EdgeDB.Protocol.Codec - defstruct [:id, :members] + defstruct [ + :id, + :members, + :name + ] @spec new(Codec.t(), list(String.t())) :: Codec.t() def new(id, members) do @@ -21,12 +25,17 @@ defimpl EdgeDB.Protocol.Codec, for: EdgeDB.Protocol.Codecs.Enum do @impl Codec def encode(%{members: members}, value, codec_storage) do - if value in members do - Codec.encode(@str_codec, value, codec_storage) - else - raise EdgeDB.InvalidArgumentError.new( - "value can not be encoded as enum: not enum member: #{inspect(value)}" - ) + cond do + is_binary(value) and value in members -> + Codec.encode(@str_codec, value, codec_storage) + + is_atom(value) and to_string(value) in members -> + Codec.encode(@str_codec, to_string(value), codec_storage) + + true -> + raise EdgeDB.InvalidArgumentError.new( + "value can not be encoded as enum: not enum member: #{inspect(value)}" + ) end end diff --git a/lib/edgedb/protocol/codecs/scalar.ex b/lib/edgedb/protocol/codecs/scalar.ex index cc360250..d457f9c5 100644 --- a/lib/edgedb/protocol/codecs/scalar.ex +++ b/lib/edgedb/protocol/codecs/scalar.ex @@ -5,7 +5,8 @@ defmodule EdgeDB.Protocol.Codecs.Scalar do defstruct [ :id, - :codec + :codec, + :name ] @spec new(Codec.id(), Codec.id()) :: Codec.t() diff --git a/lib/edgedb/query.ex b/lib/edgedb/query.ex index 0f956410..ec8884b6 100644 --- a/lib/edgedb/query.ex +++ b/lib/edgedb/query.ex @@ -15,6 +15,7 @@ defmodule EdgeDB.Query do inline_type_ids: false, inline_object_ids: true, cardinality: :many, + result_cardinality: :many, required: false, is_script: false, capabilities: [], @@ -22,7 +23,8 @@ defmodule EdgeDB.Query do output_codec: nil, codec_storage: nil, cached: false, - params: [] + params: [], + __file__: nil ] @type t() :: %__MODULE__{ @@ -33,6 +35,7 @@ defmodule EdgeDB.Query do inline_type_ids: boolean(), inline_object_ids: boolean(), cardinality: Enums.cardinality(), + result_cardinality: Enums.cardinality(), required: boolean(), is_script: boolean(), capabilities: Enums.capabilities(), @@ -40,7 +43,8 @@ defmodule EdgeDB.Query do output_codec: Codec.id() | nil, codec_storage: CodecStorage.t(), cached: boolean(), - params: list(any()) + params: map() | list() | Keyword.t(), + __file__: Path.t() | nil } end diff --git a/lib/edgedb/result.ex b/lib/edgedb/result.ex index 788f1f74..70b483d5 100644 --- a/lib/edgedb/result.ex +++ b/lib/edgedb/result.ex @@ -17,36 +17,182 @@ defmodule EdgeDB.Result do cardinality: Enums.cardinality() } - @spec extract(t()) :: + @spec extract(t(), Keyword.t() | nil) :: {:ok, EdgeDB.Set.t() | term() | :done} | {:error, Exception.t()} - def extract(%__MODULE__{set: data}) when is_list(data) do + def extract(result, transform_result \\ nil) + + def extract(%__MODULE__{set: data}, _transform_result) when is_list(data) do {:error, EdgeDB.InterfaceError.new("result hasn't been decoded yet")} end - def extract(%__MODULE__{cardinality: :at_most_one, required: required, set: set}) do + def extract( + %__MODULE__{ + cardinality: :at_most_one, + required: required, + set: set + }, + transform_result + ) do if EdgeDB.Set.empty?(set) and required do {:error, EdgeDB.NoDataError.new("expected result, but query did not return any data")} else - value = - set - |> Enum.take(1) - |> List.first() - - {:ok, value} + set + |> Enum.take(1) + |> List.first() + |> maybe_transform_result(transform_result) end end - def extract(%__MODULE__{cardinality: :many, set: %EdgeDB.Set{} = set}) do - {:ok, set} + def extract(%__MODULE__{cardinality: :many, set: %EdgeDB.Set{} = set}, transform_result) do + maybe_transform_result(set, transform_result) end - def extract(%__MODULE__{cardinality: :no_result, required: true}) do + def extract(%__MODULE__{cardinality: :no_result, required: true}, _transform_result) do {:error, EdgeDB.InterfaceError.new("query does not return data")} end - def extract(%__MODULE__{cardinality: :no_result}) do + def extract(%__MODULE__{cardinality: :no_result}, _transform_result) do {:ok, :executed} end + + defp maybe_transform_result(value, nil) do + {:ok, value} + end + + defp maybe_transform_result(value, opts) do + schema = + opts + |> Keyword.get(:schema, []) + |> stringify_schema() + + do_transform(value, schema) + end + + defp do_transform(%EdgeDB.Set{} = set, schema) do + transformation_result = + Enum.reduce_while(set, {:ok, []}, fn element, {:ok, list} -> + case do_transform(element, schema) do + {:ok, element} -> + {:cont, {:ok, [element | list]}} + + {:error, _reason} = error -> + {:halt, error} + end + end) + + with {:ok, list} <- transformation_result do + {:ok, Enum.reverse(list)} + end + end + + defp do_transform(%EdgeDB.Object{} = object, schema) do + object.__fields__ + |> Enum.reject(fn {name, field} -> + not Map.has_key?(schema, name) or field.is_implicit + end) + |> Enum.reduce_while({:ok, %{}}, fn {name, field}, {:ok, map} -> + case do_transform(field.value, schema[name]) do + {:ok, value} -> + {:cont, {:ok, Map.put(map, String.to_existing_atom(name), value)}} + + {:error, _reason} = error -> + {:halt, error} + end + end) + end + + defp do_transform(%EdgeDB.NamedTuple{} = nt, schema) do + index_map = + Enum.into(nt.__fields_ordering__, %{}, fn {index, name} -> + {index, nt.__items__[name]} + end) + + keys_map = + Enum.reduce(nt.__items__, %{}, fn {key, value}, acc -> + if Map.has_key?(schema, key) do + Map.put(acc, key, value) + else + acc + end + end) + + index_map + |> Map.merge(keys_map) + |> Enum.reduce_while({:ok, %{}}, fn {key, value}, {:ok, map} -> + schema = + if is_integer(key) do + schema[nt.__fields_ordering__[key]] + else + schema[key] + end + + case do_transform(value, schema) do + {:ok, value} when is_binary(key) -> + {:cont, {:ok, Map.put(map, String.to_existing_atom(key), value)}} + + {:ok, value} when is_integer(key) -> + {:cont, {:ok, Map.put(map, key, value)}} + + {:error, _reason} = error -> + {:halt, error} + end + end) + end + + defp do_transform(array, schema) when is_list(array) do + transformation_result = + Enum.reduce_while(array, {:ok, []}, fn value, {:ok, list} -> + case do_transform(value, schema) do + {:ok, value} -> + {:cont, {:ok, [value | list]}} + + {:error, _reason} = error -> + {:halt, error} + end + end) + + with {:ok, list} <- transformation_result do + {:ok, Enum.reverse(list)} + end + end + + defp do_transform(tuple, schema) when is_tuple(tuple) do + transformation_result = + tuple + |> Tuple.to_list() + |> Enum.reduce_while({:ok, []}, fn value, {:ok, list} -> + case do_transform(value, schema) do + {:ok, value} -> + {:cont, {:ok, [value | list]}} + + {:error, _reason} = error -> + {:halt, error} + end + end) + + with {:ok, list} <- transformation_result do + tuple = + list + |> Enum.reverse() + |> List.to_tuple() + + {:ok, tuple} + end + end + + defp do_transform(value, _schema) do + {:ok, value} + end + + defp stringify_schema(schema) do + Enum.into(schema, %{}, fn + {name, schema} -> + {to_string(name), stringify_schema(schema)} + + name -> + {to_string(name), nil} + end) + end end diff --git a/lib/edgedb/types/named_tuple.ex b/lib/edgedb/types/named_tuple.ex index 1eb4eed1..d8bbcf43 100644 --- a/lib/edgedb/types/named_tuple.ex +++ b/lib/edgedb/types/named_tuple.ex @@ -55,12 +55,16 @@ defmodule EdgeDB.NamedTuple do iex(1)> {:ok, client} = EdgeDB.start_link() iex(2)> nt = EdgeDB.query_required_single!(client, "select (a := 1, b := 'a', c := [3])") iex(3)> EdgeDB.NamedTuple.to_map(nt) - %{"a" => 1, "b" => "a", "c" => [3]} + %{"a" => 1, 0 => 1, "b" => "a", 1 => "a", "c" => [3], 2 => [3]} ``` """ - @spec to_map(t()) :: %{String.t() => term()} - def to_map(%__MODULE__{__items__: items}) do - items + @spec to_map(t()) :: %{(String.t() | integer()) => term()} + def to_map(%__MODULE__{__items__: items, __fields_ordering__: fields_order}) do + fields_order + |> Enum.into(%{}, fn {index, name} -> + {index, items[name]} + end) + |> Map.merge(items) end @doc """ diff --git a/lib/mix/edgedb/generate.ex b/lib/mix/edgedb/generate.ex new file mode 100644 index 00000000..559e8ec8 --- /dev/null +++ b/lib/mix/edgedb/generate.ex @@ -0,0 +1,119 @@ +# credo:disable-for-this-file +defmodule Mix.Tasks.Edgedb.Generate do + @validator_definition [ + silent: [ + type: :boolean, + doc: "Show processing messages." + ], + dsn: [ + type: :string, + doc: "DSN that defines the primary information that can be used to connect to the instance." + ], + credentials_file: [ + type: :string, + doc: + "the path to the instance credentials file containing the instance parameters to connect to." + ], + instance: [ + type: :string, + doc: "the name of the instance to connect to." + ], + host: [ + type: :string, + doc: "the host name of the instance to connect to." + ], + port: [ + type: :non_neg_integer, + doc: "the port number of the instance to connect to." + ], + database: [ + type: :string, + doc: "the name of the database to connect to." + ], + user: [ + type: :string, + doc: "the user name to connect to." + ], + password: [ + type: :string, + doc: "the user password to connect." + ], + tls_ca_file: [ + type: :string, + doc: "the path to the TLS certificate to be used when connecting to the instance." + ], + tls_security: [ + type: {:in, ["insecure", "no_host_verification", "strict", "default"]}, + doc: "security mode for the TLS connection." + ] + ] + + @shortdoc "Generate Elixir modules from EdgeQL queries" + + @moduledoc """ + Generate Elixir modules from EdgeQL queries. + + To configure generation modify `:generation` key under + the `:edgedb` application configuration. + + Supported options (may be provided as a list of configs): + + * `:queries_path` - path to queries. Required. + * `:output_path` - path to store generated Elixir code. By default + `./lib` is used. + * `:module_prefix` - prefix to name generated modules. By default + no prefix is used. + + Supported arguments for task: + + #{NimbleOptions.docs(@validator_definition)} + """ + + use Mix.Task + + @impl Mix.Task + def run(args) do + Application.ensure_all_started(:edgedb) + + with {args, [], []} <- OptionParser.parse(args, strict: parser_definition()), + {:ok, args} <- NimbleOptions.validate(args, @validator_definition), + {:ok, _files} <- EdgeDB.EdgeQL.Generator.generate(args) do + Mix.shell().info("Modules for queries generated succesfully!") + else + {_args, _unparsed, errors} -> + Mix.shell().error( + "Unable to parse arguments: #{inspect(Enum.map(errors, fn {key, _value} -> key end))}" + ) + + {_args, unparsed, []} -> + Mix.shell().error("Unable to parse some of provided arguments: #{inspect(unparsed)}") + + {:error, %NimbleOptions.ValidationError{key: key} = error} -> + Mix.shell().error( + "Error while validating #{inspect(key)} argument: #{Exception.message(error)}" + ) + + {:error, {query_file, %EdgeDB.Error{} = error}} -> + Mix.shell().error("Error while generating module for query from #{query_file}!") + Mix.shell().error(Exception.message(error)) + end + end + + defp parser_definition do + Enum.map(@validator_definition, fn {arg, opts} -> + type = + case opts[:type] do + :non_neg_integer -> + :integer + + {:in, _variants} -> + :string + + type -> + type + end + + {arg, type} + end) + end +end diff --git a/mix.exs b/mix.exs index 33e364ec..8b86f187 100644 --- a/mix.exs +++ b/mix.exs @@ -33,7 +33,8 @@ defmodule EdgeDB.MixProject do extra_applications: [ :crypto, :logger, - :ssl + :ssl, + :eex ] ] end @@ -48,7 +49,8 @@ defmodule EdgeDB.MixProject do {:crc, "~> 0.10.4"}, {:castore, "~> 0.1.0 or ~> 1.0"}, {:ucwidth, "~> 0.2.0"}, - {:jason, "~> 1.2", optional: true}, + {:nimble_options, "~> 1.0"}, + {:jason, "~> 1.2"}, {:timex, "~> 3.7", optional: true}, # test {:excoveralls, "~> 0.14", only: [:test, :ci]}, @@ -63,7 +65,7 @@ defmodule EdgeDB.MixProject do end defp elixirc_paths(:test) do - ["lib", "test/support"] + ["lib", "test/support", "test/codegen"] end defp elixirc_paths(_env) do @@ -98,7 +100,8 @@ defmodule EdgeDB.MixProject do "edgedb.docs": :ci, coveralls: :test, "coveralls.detail": :test, - "coveralls.html": :test + "coveralls.html": :test, + "edgedb.generate": :dev ] end @@ -107,7 +110,8 @@ defmodule EdgeDB.MixProject do plt_add_apps: [ :ex_unit, :jason, - :timex + :timex, + :mix ], plt_file: {:no_warn, "priv/plts/dialyzer.plt"} ] @@ -133,6 +137,7 @@ defmodule EdgeDB.MixProject do extras: [ "pages/md/main.md", "pages/md/usage.md", + "pages/md/codegen.md", "pages/md/datatypes.md", "pages/md/custom-codecs.md", "CHANGELOG.md" @@ -162,14 +167,14 @@ defmodule EdgeDB.MixProject do defp aliases do [ "edgedb.roles.setup": [ - "cmd priv/scripts/setup-roles.sh" + "cmd test/support/scripts/setup-roles.sh" ], "edgedb.roles.reset": [ - "cmd priv/scripts/drop-roles.sh", - "cmd priv/scripts/setup-roles.sh" + "cmd test/support/scripts/drop-roles.sh", + "cmd test/support/scripts/setup-roles.sh" ], "edgedb.docs": [ - "run priv/scripts/edgedb_docs.exs" + "run test/support/scripts/edgedb_docs.exs" ] ] end diff --git a/mix.lock b/mix.lock index d0ac405f..fd3ea225 100644 --- a/mix.lock +++ b/mix.lock @@ -28,6 +28,7 @@ "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"}, "mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm", "f278585650aa581986264638ebf698f8bb19df297f66ad91b18910dfc6e19323"}, "mox": {:hex, :mox, "1.0.2", "dc2057289ac478b35760ba74165b4b3f402f68803dd5aecd3bfd19c183815d64", [:mix], [], "hexpm", "f9864921b3aaf763c8741b5b8e6f908f44566f1e427b2630e89e9a73b981fef2"}, + "nimble_options": {:hex, :nimble_options, "1.0.2", "92098a74df0072ff37d0c12ace58574d26880e522c22801437151a159392270e", [:mix], [], "hexpm", "fd12a8db2021036ce12a309f26f564ec367373265b53e25403f0ee697380f1b8"}, "nimble_parsec": {:hex, :nimble_parsec, "1.3.1", "2c54013ecf170e249e9291ed0a62e5832f70a476c61da16f6aac6dca0189f2af", [:mix], [], "hexpm", "2682e3c0b2eb58d90c6375fc0cc30bc7be06f365bf72608804fb9cffa5e1b167"}, "panpipe": {:hex, :panpipe, "0.3.0", "388a5541b2baf393b25a84b51eaf36f6d30aa4660f189a8cfad71bee4aebef20", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:protocol_ex, "~> 0.4", [hex: :protocol_ex, repo: "hexpm", optional: false]}, {:rambo, "~> 0.2", [hex: :rambo, repo: "hexpm", optional: false]}], "hexpm", "79d56f9b71dff43def1bc4ee541bf05fab03fbb8367a34295f47b442193bc67a"}, "parse_trans": {:hex, :parse_trans, "3.4.1", "6e6aa8167cb44cc8f39441d05193be6e6f4e7c2946cb2759f015f8c56b76e5ff", [:rebar3], [], "hexpm", "620a406ce75dada827b82e453c19cf06776be266f5a67cff34e1ef2cbb60e49a"}, diff --git a/pages/md/codegen.md b/pages/md/codegen.md new file mode 100644 index 00000000..7d7975a6 --- /dev/null +++ b/pages/md/codegen.md @@ -0,0 +1,87 @@ +# Code Generation with Elixir client + +`edgedb-elixir` provides a custom `Mix` task for generating Elixir modules from EdgeQL query files. + + +First, add the following lines for `:edgedb` to the config: + +```elixir +config :edgedb, :generation, + queries_path: "priv/edgedb/edgeql/", + output_path: "lib/my_app/edgedb/queries", + module_prefix: MyApp.EdgeDB +``` + +Or in case you have multiple locations for your queries like this: + +```elixir +config :edgedb, + generation: [ + [ + queries_path: "priv/edgedb/edgeql/path1", + output_path: "lib/my_app/edgedb/queries/path1", + module_prefix: MyApp.EdgeDB.Path1 + ], + [ + queries_path: "priv/edgedb/edgeql/path2", + output_path: "lib/my_app/edgedb/queries/path2", + module_prefix: MyApp.EdgeDB.Path2 + ], + ] +``` + +> #### NOTE {: .info} +> +> `module_prefix` is an optional parameter that allows you to control the prefix for the module being generated + +Then, let's place a new EdgeQL query into `priv/edgedb/edgeql/select_string.edgeql`: + +```edgeql +select $arg +``` + +Now we can run `mix edgedb.generate` and it should produce new `lib/my_app/edgedb/queries/select_string.edgeql.ex`. The result should look similar to this: + +```elixir +defmodule MyApp.EdgeDB.SelectString do + @query """ + select $arg + """ + + @type keyword_args() :: [{:arg, String.t() | nil}] + @type map_args() :: %{arg: String.t() | nil} + @type args() :: map_args() | keyword_args() + + @spec query(client :: EdgeDB.client(), args :: args(), opts :: list(EdgeDB.query_option())) :: + {:ok, String.t() | nil} | {:error, reason} when reason: any() + def query(client, args, opts \\ []) do + do_query(client, args, opts) + end + + @spec query!(client :: EdgeDB.client(), args :: args(), opts :: list(EdgeDB.query_option())) :: + String.t() | nil + def query!(client, args, opts \\ []) do + case do_query(client, args, opts) do + {:ok, result} -> + result + + {:error, exc} -> + raise exc + end + end + + defp do_query(client, args, opts) do + EdgeDB.query_single(client, @query, args, opts) + end +end +``` + +To use it just call the `MyApp.EdgeDB.SelectString.query/3` function: + +```elixir +iex(1)> {:ok, client} = EdgeDB.start_link() +iex(2)> {:ok, "hello world"} = MyApp.EdgeDB.SelectString.query(client, arg: "hello world") +``` + +You can check out a more interesting and complete use case in the example repository: +https://github.com/nsidnev/edgebeats diff --git a/pages/md/main.md b/pages/md/main.md index ca22635a..61920146 100644 --- a/pages/md/main.md +++ b/pages/md/main.md @@ -16,11 +16,6 @@ ## JSON support `EdgeDB` comes with JSON support out of the box via the `Jason` library. - To use it, add `:jason` to your dependencies in the `mix.exs` file: - -```elixir -{:jason, "~> 1.0"} -``` The JSON library can be configured using the `:json` option in the `:edgedb` application configuration: diff --git a/pages/rst/api/edgedb-types.rst b/pages/rst/api/edgedb-types.rst index 35cf7007..93713805 100644 --- a/pages/rst/api/edgedb-types.rst +++ b/pages/rst/api/edgedb-types.rst @@ -312,7 +312,7 @@ Get named tuple keys. .. code:: elixir - @spec EdgeDB.NamedTuple.to_map(t()) :: %{required(String.t()) => term()} + @spec EdgeDB.NamedTuple.to_map(t()) :: %{required(String.t() | integer()) => term()} Convert a named tuple into a regular map. @@ -321,7 +321,7 @@ Convert a named tuple into a regular map. iex(1)> {:ok, client} = EdgeDB.start_link() iex(2)> nt = EdgeDB.query_required_single!(client, "select (a := 1, b := 'a', c := [3])") iex(3)> EdgeDB.NamedTuple.to_map(nt) - %{"a" => 1, "b" => "a", "c" => [3]} + %{"a" => 1, 0 => 1, "b" => "a", 1 => "a", "c" => [3], 2 => [3]} *function* ``EdgeDB.NamedTuple.to_tuple(nt)`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/pages/rst/codegen.rst b/pages/rst/codegen.rst new file mode 100644 index 00000000..77a60704 --- /dev/null +++ b/pages/rst/codegen.rst @@ -0,0 +1,92 @@ +.. _edgedb-elixir-codegen: + +Code Generation with Elixir client +================================== + +``edgedb-elixir`` provides a custom ``Mix`` task for generating Elixir modules from EdgeQL query files. + +First, add the following lines for ``:edgedb`` to the config: + +.. code:: elixir + + config :edgedb, :generation, + queries_path: "priv/edgedb/edgeql/", + output_path: "lib/my_app/edgedb/queries", + module_prefix: MyApp.EdgeDB + +Or in case you have multiple locations for your queries like this: + +.. code:: elixir + + config :edgedb, + generation: [ + [ + queries_path: "priv/edgedb/edgeql/path1", + output_path: "lib/my_app/edgedb/queries/path1", + module_prefix: MyApp.EdgeDB.Path1 + ], + [ + queries_path: "priv/edgedb/edgeql/path2", + output_path: "lib/my_app/edgedb/queries/path2", + module_prefix: MyApp.EdgeDB.Path2 + ], + ] + +.. + +.. note:: + :name: note-.info + + ``module_prefix`` is an optional parameter that allows you to control the prefix for the module being generated + +Then, let’s place a new EdgeQL query into ``priv/edgedb/edgeql/select_string.edgeql``: + +.. code:: edgeql + + select $arg + +Now we can run ``mix edgedb.generate`` and it should produce new ``lib/my_app/edgedb/queries/select_string.edgeql.ex``. The result should look +similar to this: + +.. code:: elixir + + defmodule MyApp.EdgeDB.SelectString do + @query """ + select $arg + """ + + @type keyword_args() :: [{:arg, String.t() | nil}] + @type map_args() :: %{arg: String.t() | nil} + @type args() :: map_args() | keyword_args() + + @spec query(client :: EdgeDB.client(), args :: args(), opts :: list(EdgeDB.query_option())) :: + {:ok, String.t() | nil} | {:error, reason} when reason: any() + def query(client, args, opts \\ []) do + do_query(client, args, opts) + end + + @spec query!(client :: EdgeDB.client(), args :: args(), opts :: list(EdgeDB.query_option())) :: + String.t() | nil + def query!(client, args, opts \\ []) do + case do_query(client, args, opts) do + {:ok, result} -> + result + + {:error, exc} -> + raise exc + end + end + + defp do_query(client, args, opts) do + EdgeDB.query_single(client, @query, args, opts) + end + end + +To use it just call the ``MyApp.EdgeDB.SelectString.query/3`` function: + +.. code:: elixir + + iex(1)> {:ok, client} = EdgeDB.start_link() + iex(2)> {:ok, "hello world"} = MyApp.EdgeDB.SelectString.query(client, arg: "hello world") + +You can check out a more interesting and complete use case in the example repository: https://github.com/nsidnev/edgebeats diff --git a/pages/rst/index.rst b/pages/rst/index.rst index e38ea0f3..04a72f64 100644 --- a/pages/rst/index.rst +++ b/pages/rst/index.rst @@ -8,6 +8,7 @@ EdgeDB client for Elixir :hidden: usage + codegen datatypes custom-codecs api/api @@ -32,12 +33,7 @@ dependencies in the ``mix.exs`` file: JSON support ------------ -``EdgeDB`` comes with JSON support out of the box via the ``Jason`` library. To use it, add ``:jason`` to your dependencies in the ``mix.exs`` -file: - -.. code:: elixir - - {:jason, "~> 1.0"} +``EdgeDB`` comes with JSON support out of the box via the ``Jason`` library. The JSON library can be configured using the ``:json`` option in the ``:edgedb`` application configuration: diff --git a/priv/codegen/templates/_builtin.eex b/priv/codegen/templates/_builtin.eex new file mode 100644 index 00000000..9fb6cb7d --- /dev/null +++ b/priv/codegen/templates/_builtin.eex @@ -0,0 +1,6 @@ +<%= if @builtin[:is_list] do %>list(<% end %> +<%= if @builtin[:is_registered] do %><%= @module_name %>.<% end %><%= @builtin.typespec %> +<%= if @builtin[:is_list] do %>)<% end %> +<%= if @builtin[:is_optional] do %> +| nil +<% end %> \ No newline at end of file diff --git a/priv/codegen/templates/_object.eex b/priv/codegen/templates/_object.eex new file mode 100644 index 00000000..0afd7033 --- /dev/null +++ b/priv/codegen/templates/_object.eex @@ -0,0 +1,59 @@ +<%= for {name, field} <- @object.fields do %> + <%= case field do %> + <% %{type: :object} -> %> + defmodule <%= Macro.camelize(name) %> do + <%= @render_object.( + object: field, + render_shape: @render_shape, + render_builtin: @render_builtin, + render_object: @render_object, + render_set: @render_set, + module_name: @module_name + ) %> + end; + <% %{type: :set} -> %> + defmodule <%= Macro.camelize(name) %> do + <%= if field.shape[:type] == :builtin do %>@type t() ::<% end %> + <%= @render_set.( + set: field, + render_shape: @render_shape, + render_builtin: @render_builtin, + render_object: @render_object, + render_set: @render_set, + module_name: @module_name + ) %> + end; + <% _ -> %> + <% false %> + <% end %> +<% end %> + +@derive Jason.Encoder; +defstruct [ + <%= for {name, _} <- @object.fields do %> + :<%= name %>, + <% end %> +]; + +@type t() :: %__MODULE__{ + <%= for {name, field} <- @object.fields do %> + <%= case field do %> + <% %{type: type} when type in [:object, :set] -> %> + <%= name %>: <%= if field[:is_list] do %>list(<% end %> + <%= Macro.camelize(name) %>.t() + <%= if field[:is_list] do %>)<% end %><%= if field[:is_optional] do %>| nil<% end %>, + + <% _ -> %> + <%= name %>: <%= @render_shape.( + shape: field, + render_shape: @render_shape, + render_builtin: @render_builtin, + render_object: @render_object, + render_set: @render_set, + module_name: @module_name + ) %>, + <% end %> + <% end %> +} <%= if @object[:is_optional] do %> +| nil +<% end %>; diff --git a/priv/codegen/templates/_schema.eex b/priv/codegen/templates/_schema.eex new file mode 100644 index 00000000..0f73ec5b --- /dev/null +++ b/priv/codegen/templates/_schema.eex @@ -0,0 +1,20 @@ +{ + <%= for type <- @schema do %> + <%= case type do %> + <% {name, [:builtin, schema]} -> %> + <%= name %>: %<%= @render_schema.( + schema: schema, + render_schema: @render_schema, + paths: @paths ++ [name]) + %>, + <% {name, schema} -> %> + <%= name %>: %Result.<%= Enum.map_join(@paths ++ [name],".", &(Macro.camelize(&1))) %><%= @render_schema.( + schema: schema, + render_schema: @render_schema, + paths: @paths ++ [name]) + %>, + <% name -> %> + <%= name %>: result<%= Enum.map_join(@paths, &("[\"#{&1}\"]")) %>["<%= name %>"], + <% end %> + <% end %> +} diff --git a/priv/codegen/templates/_set.eex b/priv/codegen/templates/_set.eex new file mode 100644 index 00000000..0f5bd364 --- /dev/null +++ b/priv/codegen/templates/_set.eex @@ -0,0 +1,8 @@ +<%= @render_shape.( + shape: @set.shape, + render_shape: @render_shape, + render_builtin: @render_builtin, + render_object: @render_object, + render_set: @render_set, + module_name: @module_name +) %> diff --git a/priv/codegen/templates/_shape.eex b/priv/codegen/templates/_shape.eex new file mode 100644 index 00000000..f233d4a2 --- /dev/null +++ b/priv/codegen/templates/_shape.eex @@ -0,0 +1,24 @@ +<%= case @shape do %> + <% %{type: :builtin} = builtin -> %> + <%= @render_builtin.(builtin: builtin, module_name: @module_name) %> + + <% %{type: :object} = object -> %> + <%= @render_object.( + object: object, + render_shape: @render_shape, + render_builtin: @render_builtin, + render_object: @render_object, + render_set: @render_set, + module_name: @module_name + ) %> + + <% %{type: :set} = set -> %> + <%= @render_set.( + set: set, + render_shape: @render_shape, + render_builtin: @render_builtin, + render_object: @render_object, + render_set: @render_set, + module_name: @module_name + ) %> +<% end %> diff --git a/priv/codegen/templates/query.ex.eex b/priv/codegen/templates/query.ex.eex new file mode 100644 index 00000000..bb85c121 --- /dev/null +++ b/priv/codegen/templates/query.ex.eex @@ -0,0 +1,190 @@ +# AUTOGENERATED: DO NOT MODIFY +# Generated by Elixir client for EdgeDB via `mix edgedb.generate` from +# `<%= @query_file %>`. +defmodule <%= @module_name %> do + @query """ +<%= String.trim_trailing(@query.statement, "\n") %> +""" + + @moduledoc """ + Generated module for the EdgeQL query from + `<%= @query_file %>`. + + Query: + + ```edgeql + #{@query} + ``` + """ + + @query_file "<%= @query_file %>" + + <%= for {type_name, {typedoc, typespec}} <- @types do %> + @typedoc """ + ```edgeql + <%= typedoc %> + ``` + """ + @type <%= type_name %> :: <%= typespec %> + <% end %> + + <%= if @should_render_type_for_shape do %> + defmodule Result do + <%= @shape %> + end + <% end %> + + <%= if @query.has_positional_args do %> + + @doc """ + Run the query. + """ + @spec query( + client :: EdgeDB.client(), + <%= Enum.map_join(@query.args, ",\n", &("arg_#{&1.name} :: #{&1.typespec}")) %>, + opts :: list(EdgeDB.query_option()) + ) :: {:ok, <%= @result_type %>} + | {:error, reason} + when reason: any() + def query(client, <%= Enum.map_join(@query.args, ",", &("arg_#{&1.name}")) %>, opts \\ []) do + args = [<%= Enum.map_join(@query.args, ", ", &("arg_#{&1.name}")) %>] + do_query(client, args, opts) + end + + @doc """ + Run the query. + """ + @spec query!( + client :: EdgeDB.client(), + <%= Enum.map_join(@query.args, ",\n", &("arg_#{&1.name} :: #{&1.typespec}")) %>, + opts :: list(EdgeDB.query_option()) + ) :: <%= @result_type %> + def query!(client, <%= Enum.map_join(@query.args, ",", &("arg_#{&1.name}")) %>, opts \\ []) do + args = [<%= Enum.map_join(@query.args, ", ", &("arg_#{&1.name}")) %>] + + case do_query(client, args, opts) do + {:ok, result} -> + result + + {:error, exc} -> + raise exc + end + end + + <% end %> + + <%= if @query.has_named_args do %> + + @type keyword_args() :: [<%= Enum.map_join(@query.args, " | ", &("{:#{&1.name}, #{&1.typespec}}")) %>] + + @type map_args() :: %{ + <%= for arg <- @query.args do %> + <%= arg.name %>: <%= arg.typespec %>, + <% end %> + } + + @type args() :: map_args() | keyword_args() + + @doc """ + Run the query. + """ + @spec query( + client :: EdgeDB.client(), + args :: args(), + opts :: list(EdgeDB.query_option()) + ) :: + {:ok, <%= @result_type %>} + | {:error, reason} + when reason: any() + def query(client, args, opts \\ []) do + do_query(client, args, opts) + end + + @doc """ + Run the query. + """ + @spec query!( + client :: EdgeDB.client(), + args :: args(), + opts :: list(EdgeDB.query_option()) + ) :: <%= @result_type %> + def query!(client, args, opts \\ []) do + case do_query(client, args, opts) do + {:ok, result} -> + result + + {:error, exc} -> + raise exc + end + end + + <% end %> + + <%= if length(@query.args) == 0 do %> + + @doc """ + Run the query. + """ + @spec query( + client :: EdgeDB.client(), + opts :: list(EdgeDB.query_option()) + ) :: + {:ok, <%= @result_type %>} + | {:error, reason} + when reason: any() + def query(client, opts \\ []) do + do_query(client, [], opts) + end + + @doc """ + Run the query. + """ + @spec query!( + client :: EdgeDB.client(), + opts :: list(EdgeDB.query_option()) + ) :: <%= @result_type %> + def query!(client, opts \\ []) do + case do_query(client, [], opts) do + {:ok, result} -> + result + + {:error, exc} -> + raise exc + end + end + + <% end %> + + defp do_query(client, args, opts) do + opts = Keyword.merge(opts, __file__: @query_file, __transform_result__: [schema: @schema]); + <%= case @query.cardinality do %> + <% :at_most_one -> %> + with {:ok, result} when not is_nil(result) <- EdgeDB.query_single(client, @query, args, opts) do + + <% :one -> %> + with {:ok, result} <- EdgeDB.query_required_single(client, @query, args, opts) do + + <% :no_result -> %> + with {:ok, result} <- EdgeDB.execute(client, @query, args, opts) do + + <% _ -> %> + with {:ok, results} <- EdgeDB.query(client, @query, args, opts) do + results = case results do + [] -> nil + _ -> Enum.map(results, fn result -> + <% end %> + + <%= if @should_render_type_for_shape do %> + %Result<%= @schema %> + <% else %> + {:ok, result} + <% end %> + + <%= if @query.cardinality in [:at_least_one, :many] do %> + end); + end; + {:ok, results}; + <% end %> + end + end +end diff --git a/priv/edgedb/schema/migrations/00003.edgeql b/priv/edgedb/schema/migrations/00003.edgeql deleted file mode 100644 index 08ac5b7c..00000000 --- a/priv/edgedb/schema/migrations/00003.edgeql +++ /dev/null @@ -1,6 +0,0 @@ -CREATE MIGRATION m16wualxmsuqqryhwrn6kgd6upwxge3cwruitgz63wbe5mynxxieva - ONTO m1ryrngpym75cc5zcmkrfebkg6dcmyflzu7727vnjhmy2zl4q3tjda -{ - CREATE EXTENSION pgvector VERSION '0.4'; - CREATE SCALAR TYPE default::ExVector EXTENDING ext::pgvector::vector<1602>; -}; diff --git a/priv/scripts/drop-roles.sh b/priv/scripts/drop-roles.sh deleted file mode 100755 index 6f27712f..00000000 --- a/priv/scripts/drop-roles.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash - -set -e - -edgedb query --file priv/scripts/edgeql/drop-roles.edgeql diff --git a/priv/scripts/setup-roles.sh b/priv/scripts/setup-roles.sh deleted file mode 100755 index 3fc5b897..00000000 --- a/priv/scripts/setup-roles.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash - -set -e - -edgedb query --file priv/scripts/edgeql/setup-roles.edgeql diff --git a/test/codegen/codegen_test.exs b/test/codegen/codegen_test.exs new file mode 100644 index 00000000..a8e0e786 --- /dev/null +++ b/test/codegen/codegen_test.exs @@ -0,0 +1,68 @@ +defmodule Tests.CodegenTest do + use Tests.Support.EdgeDBCase + + skip_before(version: 3, scope: :module) + + @queries_path Application.compile_env!(:edgedb, :generation)[:queries_path] + + queries = + [@queries_path, "**", "*.edgeql"] + |> Path.join() + |> Path.wildcard() + + setup :edgedb_client + + describe "queries generation" do + setup do + {:ok, files} = EdgeDB.EdgeQL.Generator.generate(silent: true) + + Code.put_compiler_option(:ignore_module_conflict, true) + + on_exit(fn -> + Code.put_compiler_option(:ignore_module_conflict, false) + end) + + %{files: files} + end + + test "codegen returns a complex shape as atomized maps", %{client: client, files: files} do + [{mod, _code}] = + files + |> Enum.find(fn {_query_file, elixir_file} -> + String.contains?(elixir_file, "select_startart_types_named_simple") + end) + |> elem(1) + |> Code.compile_file() + + e = "arg" + f = 42 + + assert %{ + a: 1, + b: %{ + b_a: 2, + b_b: 3 + }, + c: "hello world", + d: [4, 5, 6], + e: ^e, + f: ^f + } = mod.query!(client, e: e, f: f) + end + + for query_path <- queries do + test "for #{query_path} equals the desired module state", %{files: files} do + assert %{unquote(query_path) => elixir_path} = files + prepared_module = File.read!("#{unquote(query_path)}.ex.assert") + generated_module = File.read!(elixir_path) + assert String.trim(prepared_module) == String.trim(generated_module) + end + + test "for #{query_path} compiles", %{files: files} do + assert %{unquote(query_path) => elixir_path} = files + Code.compile_file(elixir_path) + :ok + end + end + end +end diff --git a/test/edgedb/types/named_tuple_test.exs b/test/edgedb/types/named_tuple_test.exs index 3ec1f4a0..0dc4ef70 100644 --- a/test/edgedb/types/named_tuple_test.exs +++ b/test/edgedb/types/named_tuple_test.exs @@ -37,7 +37,9 @@ defmodule Tests.EdgeDB.Types.NamedTupleTest do describe "EdgeDB.NamedTuple.to_map/1" do test "returns map converted from object", %{client: client} do nt = EdgeDB.query_required_single!(client, select_named_tuple_query()) - expected_map = Enum.into(1..100, %{}, &{"key_#{&1}", &1}) + expected_keys_map = Enum.into(1..100, %{}, &{"key_#{&1}", &1}) + expected_index_map = Enum.into(1..100, %{}, &{&1 - 1, &1}) + expected_map = Map.merge(expected_keys_map, expected_index_map) assert EdgeDB.NamedTuple.to_map(nt) == expected_map end diff --git a/test/support/codegen/edgeql/scalars/select_int_named.edgeql b/test/support/codegen/edgeql/scalars/select_int_named.edgeql new file mode 100644 index 00000000..dbda8c83 --- /dev/null +++ b/test/support/codegen/edgeql/scalars/select_int_named.edgeql @@ -0,0 +1 @@ +select $cp_int diff --git a/test/support/codegen/edgeql/scalars/select_int_named.edgeql.ex.assert b/test/support/codegen/edgeql/scalars/select_int_named.edgeql.ex.assert new file mode 100644 index 00000000..75b682b6 --- /dev/null +++ b/test/support/codegen/edgeql/scalars/select_int_named.edgeql.ex.assert @@ -0,0 +1,67 @@ +# AUTOGENERATED: DO NOT MODIFY +# Generated by Elixir client for EdgeDB via `mix edgedb.generate` from +# `test/support/codegen/edgeql/scalars/select_int_named.edgeql`. +defmodule Tests.Codegen.Queries.Scalars.SelectIntNamed do + @query """ + select $cp_int + """ + + @moduledoc """ + Generated module for the EdgeQL query from + `test/support/codegen/edgeql/scalars/select_int_named.edgeql`. + + Query: + + ```edgeql + #{@query} + ``` + """ + + @query_file "test/support/codegen/edgeql/scalars/select_int_named.edgeql" + + @type keyword_args() :: [{:cp_int, integer()}] + + @type map_args() :: %{ + cp_int: integer() + } + + @type args() :: map_args() | keyword_args() + + @doc """ + Run the query. + """ + @spec query( + client :: EdgeDB.client(), + args :: args(), + opts :: list(EdgeDB.query_option()) + ) :: + {:ok, integer()} + | {:error, reason} + when reason: any() + def query(client, args, opts \\ []) do + do_query(client, args, opts) + end + + @doc """ + Run the query. + """ + @spec query!( + client :: EdgeDB.client(), + args :: args(), + opts :: list(EdgeDB.query_option()) + ) :: integer() + def query!(client, args, opts \\ []) do + case do_query(client, args, opts) do + {:ok, result} -> + result + + {:error, exc} -> + raise exc + end + end + + defp do_query(client, args, opts) do + opts = Keyword.merge(opts, __file__: @query_file) + EdgeDB.query_required_single(client, @query, args, opts) + end +end diff --git a/test/support/codegen/edgeql/scalars/select_int_positional.edgeql b/test/support/codegen/edgeql/scalars/select_int_positional.edgeql new file mode 100644 index 00000000..ba9d58c1 --- /dev/null +++ b/test/support/codegen/edgeql/scalars/select_int_positional.edgeql @@ -0,0 +1 @@ +select $0 diff --git a/test/support/codegen/edgeql/scalars/select_int_positional.edgeql.ex.assert b/test/support/codegen/edgeql/scalars/select_int_positional.edgeql.ex.assert new file mode 100644 index 00000000..ca4066b5 --- /dev/null +++ b/test/support/codegen/edgeql/scalars/select_int_positional.edgeql.ex.assert @@ -0,0 +1,62 @@ +# AUTOGENERATED: DO NOT MODIFY +# Generated by Elixir client for EdgeDB via `mix edgedb.generate` from +# `test/support/codegen/edgeql/scalars/select_int_positional.edgeql`. +defmodule Tests.Codegen.Queries.Scalars.SelectIntPositional do + @query """ + select $0 + """ + + @moduledoc """ + Generated module for the EdgeQL query from + `test/support/codegen/edgeql/scalars/select_int_positional.edgeql`. + + Query: + + ```edgeql + #{@query} + ``` + """ + + @query_file "test/support/codegen/edgeql/scalars/select_int_positional.edgeql" + + @doc """ + Run the query. + """ + @spec query( + client :: EdgeDB.client(), + arg_0 :: integer(), + opts :: list(EdgeDB.query_option()) + ) :: + {:ok, integer()} + | {:error, reason} + when reason: any() + def query(client, arg_0, opts \\ []) do + args = [arg_0] + do_query(client, args, opts) + end + + @doc """ + Run the query. + """ + @spec query!( + client :: EdgeDB.client(), + arg_0 :: integer(), + opts :: list(EdgeDB.query_option()) + ) :: integer() + def query!(client, arg_0, opts \\ []) do + args = [arg_0] + + case do_query(client, args, opts) do + {:ok, result} -> + result + + {:error, exc} -> + raise exc + end + end + + defp do_query(client, args, opts) do + opts = Keyword.merge(opts, __file__: @query_file) + EdgeDB.query_required_single(client, @query, args, opts) + end +end diff --git a/test/support/codegen/edgeql/scalars/select_optional_string_named.edgeql b/test/support/codegen/edgeql/scalars/select_optional_string_named.edgeql new file mode 100644 index 00000000..6e59f764 --- /dev/null +++ b/test/support/codegen/edgeql/scalars/select_optional_string_named.edgeql @@ -0,0 +1 @@ +select $cp_str diff --git a/test/support/codegen/edgeql/scalars/select_optional_string_named.edgeql.ex.assert b/test/support/codegen/edgeql/scalars/select_optional_string_named.edgeql.ex.assert new file mode 100644 index 00000000..3a67054b --- /dev/null +++ b/test/support/codegen/edgeql/scalars/select_optional_string_named.edgeql.ex.assert @@ -0,0 +1,67 @@ +# AUTOGENERATED: DO NOT MODIFY +# Generated by Elixir client for EdgeDB via `mix edgedb.generate` from +# `test/support/codegen/edgeql/scalars/select_optional_string_named.edgeql`. +defmodule Tests.Codegen.Queries.Scalars.SelectOptionalStringNamed do + @query """ + select $cp_str + """ + + @moduledoc """ + Generated module for the EdgeQL query from + `test/support/codegen/edgeql/scalars/select_optional_string_named.edgeql`. + + Query: + + ```edgeql + #{@query} + ``` + """ + + @query_file "test/support/codegen/edgeql/scalars/select_optional_string_named.edgeql" + + @type keyword_args() :: [{:cp_str, String.t() | nil}] + + @type map_args() :: %{ + cp_str: String.t() | nil + } + + @type args() :: map_args() | keyword_args() + + @doc """ + Run the query. + """ + @spec query( + client :: EdgeDB.client(), + args :: args(), + opts :: list(EdgeDB.query_option()) + ) :: + {:ok, String.t() | nil} + | {:error, reason} + when reason: any() + def query(client, args, opts \\ []) do + do_query(client, args, opts) + end + + @doc """ + Run the query. + """ + @spec query!( + client :: EdgeDB.client(), + args :: args(), + opts :: list(EdgeDB.query_option()) + ) :: String.t() | nil + def query!(client, args, opts \\ []) do + case do_query(client, args, opts) do + {:ok, result} -> + result + + {:error, exc} -> + raise exc + end + end + + defp do_query(client, args, opts) do + opts = Keyword.merge(opts, __file__: @query_file) + EdgeDB.query_single(client, @query, args, opts) + end +end diff --git a/test/support/codegen/edgeql/scalars/select_optional_string_positional.edgeql b/test/support/codegen/edgeql/scalars/select_optional_string_positional.edgeql new file mode 100644 index 00000000..f86c2182 --- /dev/null +++ b/test/support/codegen/edgeql/scalars/select_optional_string_positional.edgeql @@ -0,0 +1 @@ +select $0 diff --git a/test/support/codegen/edgeql/scalars/select_optional_string_positional.edgeql.ex.assert b/test/support/codegen/edgeql/scalars/select_optional_string_positional.edgeql.ex.assert new file mode 100644 index 00000000..cc069fe4 --- /dev/null +++ b/test/support/codegen/edgeql/scalars/select_optional_string_positional.edgeql.ex.assert @@ -0,0 +1,62 @@ +# AUTOGENERATED: DO NOT MODIFY +# Generated by Elixir client for EdgeDB via `mix edgedb.generate` from +# `test/support/codegen/edgeql/scalars/select_optional_string_positional.edgeql`. +defmodule Tests.Codegen.Queries.Scalars.SelectOptionalStringPositional do + @query """ + select $0 + """ + + @moduledoc """ + Generated module for the EdgeQL query from + `test/support/codegen/edgeql/scalars/select_optional_string_positional.edgeql`. + + Query: + + ```edgeql + #{@query} + ``` + """ + + @query_file "test/support/codegen/edgeql/scalars/select_optional_string_positional.edgeql" + + @doc """ + Run the query. + """ + @spec query( + client :: EdgeDB.client(), + arg_0 :: String.t() | nil, + opts :: list(EdgeDB.query_option()) + ) :: + {:ok, String.t() | nil} + | {:error, reason} + when reason: any() + def query(client, arg_0, opts \\ []) do + args = [arg_0] + do_query(client, args, opts) + end + + @doc """ + Run the query. + """ + @spec query!( + client :: EdgeDB.client(), + arg_0 :: String.t() | nil, + opts :: list(EdgeDB.query_option()) + ) :: String.t() | nil + def query!(client, arg_0, opts \\ []) do + args = [arg_0] + + case do_query(client, args, opts) do + {:ok, result} -> + result + + {:error, exc} -> + raise exc + end + end + + defp do_query(client, args, opts) do + opts = Keyword.merge(opts, __file__: @query_file) + EdgeDB.query_single(client, @query, args, opts) + end +end diff --git a/test/support/codegen/edgeql/select_string_from_root.edgeql b/test/support/codegen/edgeql/select_string_from_root.edgeql new file mode 100644 index 00000000..d0f78cf5 --- /dev/null +++ b/test/support/codegen/edgeql/select_string_from_root.edgeql @@ -0,0 +1 @@ +select 'Hello world!' diff --git a/test/support/codegen/edgeql/select_string_from_root.edgeql.ex.assert b/test/support/codegen/edgeql/select_string_from_root.edgeql.ex.assert new file mode 100644 index 00000000..2fc23660 --- /dev/null +++ b/test/support/codegen/edgeql/select_string_from_root.edgeql.ex.assert @@ -0,0 +1,57 @@ +# AUTOGENERATED: DO NOT MODIFY +# Generated by Elixir client for EdgeDB via `mix edgedb.generate` from +# `test/support/codegen/edgeql/select_string_from_root.edgeql`. +defmodule Tests.Codegen.Queries.SelectStringFromRoot do + @query """ + select 'Hello world!' + """ + + @moduledoc """ + Generated module for the EdgeQL query from + `test/support/codegen/edgeql/select_string_from_root.edgeql`. + + Query: + + ```edgeql + #{@query} + ``` + """ + + @query_file "test/support/codegen/edgeql/select_string_from_root.edgeql" + + @doc """ + Run the query. + """ + @spec query( + client :: EdgeDB.client(), + opts :: list(EdgeDB.query_option()) + ) :: + {:ok, String.t()} + | {:error, reason} + when reason: any() + def query(client, opts \\ []) do + do_query(client, [], opts) + end + + @doc """ + Run the query. + """ + @spec query!( + client :: EdgeDB.client(), + opts :: list(EdgeDB.query_option()) + ) :: String.t() + def query!(client, opts \\ []) do + case do_query(client, [], opts) do + {:ok, result} -> + result + + {:error, exc} -> + raise exc + end + end + + defp do_query(client, args, opts) do + opts = Keyword.merge(opts, __file__: @query_file) + EdgeDB.query_required_single(client, @query, args, opts) + end +end diff --git a/test/support/codegen/edgeql/standart/select_standart_types_named.edgeql b/test/support/codegen/edgeql/standart/select_standart_types_named.edgeql new file mode 100644 index 00000000..9f61c918 --- /dev/null +++ b/test/support/codegen/edgeql/standart/select_standart_types_named.edgeql @@ -0,0 +1,95 @@ +select { + # string + cp_str := $cp_str, + cp_str_type := $cp_str_type, + + cp_bool := $cp_bool, + cp_bool_type := $cp_bool_type, + + cp_int16 := $cp_int16, + cp_int16_type := $cp_int16_type, + + cp_int32 := $cp_int32, + cp_int32_type := $cp_int32_type, + + cp_int64 := $cp_int64, + cp_int64_type := $cp_int64_type, + + cp_float32 := $cp_float32, + cp_float32_type := $cp_float32_type, + + cp_float64 := $cp_float64, + cp_float64_type := $cp_float64_type, + + cp_decimal := $cp_decimal, + cp_decimal_type := $cp_decimal_type, + + # json + + cp_json := $cp_json, + cp_json_type := $cp_json_type, + + # uuid + + cp_uuid := $cp_uuid, + cp_uuid_type := $cp_uuid_type, + + # enum + + cp_enum := $cp_enum, + + # date/time + + cp_datetime := $cp_datetime, + cp_datetime_type := $cp_datetime_type, + + cp_duration := $cp_duration, + cp_duration_type := $cp_duration_type, + + cp_cal_local_datetime := $cp_cal_local_datetime, + cp_cal_local_datetime_type := $cp_cal_local_datetime_type, + + cp_cal_local_date := $cp_cal_local_date, + cp_cal_local_date_type := $cp_cal_local_date_type, + + cp_cal_local_time := $cp_cal_local_time, + cp_cal_local_time_type := $cp_cal_local_time_type, + + cp_cal_relative_duration := $cp_cal_relative_duration, + cp_cal_relative_duration_type := $cp_cal_relative_duration_type, + + cp_cal_date_duration := $cp_cal_date_duration, + cp_cal_date_duration_type := $cp_cal_date_duration_type, + + # array + + cp_array_int64 := >$cp_array_int64, + + # range + + cp_range_int32 := >$cp_range_int32, + + cp_range_int64 := >$cp_range_int64, + + cp_range_float32 := >$cp_range_float32, + + cp_range_float64 := >$cp_range_float64, + + cp_range_decimal := >$cp_range_decimal, + + cp_range_datetime := >$cp_range_datetime, + + cp_range_cal_local_datetime := >$cp_range_cal_local_datetime, + + cp_range_cal_local_date := >$cp_range_cal_local_date, + + # bytes + + cp_bytes := $cp_bytes, + cp_bytes_type := $cp_bytes_type, + + # config + + cp_cfg_memory := $cp_cfg_memory, + cp_cfg_memory_type := $cp_cfg_memory_type, +} diff --git a/test/support/codegen/edgeql/standart/select_standart_types_named.edgeql.ex.assert b/test/support/codegen/edgeql/standart/select_standart_types_named.edgeql.ex.assert new file mode 100644 index 00000000..4b7ea6b3 --- /dev/null +++ b/test/support/codegen/edgeql/standart/select_standart_types_named.edgeql.ex.assert @@ -0,0 +1,519 @@ +# AUTOGENERATED: DO NOT MODIFY +# Generated by Elixir client for EdgeDB via `mix edgedb.generate` from +# `test/support/codegen/edgeql/standart/select_standart_types_named.edgeql`. +defmodule Tests.Codegen.Queries.Standart.SelectStandartTypesNamed do + @query """ + select { + # string + cp_str := $cp_str, + cp_str_type := $cp_str_type, + + cp_bool := $cp_bool, + cp_bool_type := $cp_bool_type, + + cp_int16 := $cp_int16, + cp_int16_type := $cp_int16_type, + + cp_int32 := $cp_int32, + cp_int32_type := $cp_int32_type, + + cp_int64 := $cp_int64, + cp_int64_type := $cp_int64_type, + + cp_float32 := $cp_float32, + cp_float32_type := $cp_float32_type, + + cp_float64 := $cp_float64, + cp_float64_type := $cp_float64_type, + + cp_decimal := $cp_decimal, + cp_decimal_type := $cp_decimal_type, + + # json + + cp_json := $cp_json, + cp_json_type := $cp_json_type, + + # uuid + + cp_uuid := $cp_uuid, + cp_uuid_type := $cp_uuid_type, + + # enum + + cp_enum := $cp_enum, + + # date/time + + cp_datetime := $cp_datetime, + cp_datetime_type := $cp_datetime_type, + + cp_duration := $cp_duration, + cp_duration_type := $cp_duration_type, + + cp_cal_local_datetime := $cp_cal_local_datetime, + cp_cal_local_datetime_type := $cp_cal_local_datetime_type, + + cp_cal_local_date := $cp_cal_local_date, + cp_cal_local_date_type := $cp_cal_local_date_type, + + cp_cal_local_time := $cp_cal_local_time, + cp_cal_local_time_type := $cp_cal_local_time_type, + + cp_cal_relative_duration := $cp_cal_relative_duration, + cp_cal_relative_duration_type := $cp_cal_relative_duration_type, + + cp_cal_date_duration := $cp_cal_date_duration, + cp_cal_date_duration_type := $cp_cal_date_duration_type, + + # array + + cp_array_int64 := >$cp_array_int64, + + # range + + cp_range_int32 := >$cp_range_int32, + + cp_range_int64 := >$cp_range_int64, + + cp_range_float32 := >$cp_range_float32, + + cp_range_float64 := >$cp_range_float64, + + cp_range_decimal := >$cp_range_decimal, + + cp_range_datetime := >$cp_range_datetime, + + cp_range_cal_local_datetime := >$cp_range_cal_local_datetime, + + cp_range_cal_local_date := >$cp_range_cal_local_date, + + # bytes + + cp_bytes := $cp_bytes, + cp_bytes_type := $cp_bytes_type, + + # config + + cp_cfg_memory := $cp_cfg_memory, + cp_cfg_memory_type := $cp_cfg_memory_type, + } + """ + + @moduledoc """ + Generated module for the EdgeQL query from + `test/support/codegen/edgeql/standart/select_standart_types_named.edgeql`. + + Query: + + ```edgeql + #{@query} + ``` + """ + + @query_file "test/support/codegen/edgeql/standart/select_standart_types_named.edgeql" + + @typedoc """ + ```edgeql + std::uuid + ``` + """ + @type uuid() :: binary() + + @typedoc """ + ```edgeql + std::json + ``` + """ + @type json() :: any() + + @typedoc """ + ```edgeql + std::duration + ``` + """ + @type duration() :: Timex.Duration.t() | integer() + + @typedoc """ + ```edgeql + scalar type codegen::UuidType extending std::uuid + ``` + """ + @type codegen__uuid_type() :: binary() + + @typedoc """ + ```edgeql + scalar type codegen::StrType extending std::str + ``` + """ + @type codegen__str_type() :: String.t() + + @typedoc """ + ```edgeql + scalar type codegen::JsonType extending std::json + ``` + """ + @type codegen__json_type() :: any() + + @typedoc """ + ```edgeql + scalar type codegen::Int64Type extending std::int64 + ``` + """ + @type codegen__int64_type() :: integer() + + @typedoc """ + ```edgeql + scalar type codegen::Int32Type extending std::int32 + ``` + """ + @type codegen__int32_type() :: integer() + + @typedoc """ + ```edgeql + scalar type codegen::Int16Type extending std::int16 + ``` + """ + @type codegen__int16_type() :: integer() + + @typedoc """ + ```edgeql + scalar type codegen::Float64Type extending std::float64 + ``` + """ + @type codegen__float64_type() :: float() + + @typedoc """ + ```edgeql + scalar type codegen::Float32Type extending std::float32 + ``` + """ + @type codegen__float32_type() :: float() + + @typedoc """ + ```edgeql + scalar type codegen::EnumType extending enum + ``` + """ + @type codegen__enum_type() :: String.t() | :A | :B | :C + + @typedoc """ + ```edgeql + scalar type codegen::DurationType extending std::duration + ``` + """ + @type codegen__duration_type() :: integer() + + @typedoc """ + ```edgeql + scalar type codegen::DecimalType extending std::decimal + ``` + """ + @type codegen__decimal_type() :: Decimal.t() + + @typedoc """ + ```edgeql + scalar type codegen::DatetimeType extending std::datetime + ``` + """ + @type codegen__datetime_type() :: DateTime.t() + + @typedoc """ + ```edgeql + scalar type codegen::CfgMemoryType extending cfg::memory + ``` + """ + @type codegen__cfg_memory_type() :: EdgeDB.ConfigMemory.t() + + @typedoc """ + ```edgeql + scalar type codegen::CalRelativeDurationType extending cal::relative_duration + ``` + """ + @type codegen__cal_relative_duration_type() :: EdgeDB.RelativeDuration.t() + + @typedoc """ + ```edgeql + scalar type codegen::CalLocalTimeType extending cal::local_time + ``` + """ + @type codegen__cal_local_time_type() :: Time.t() + + @typedoc """ + ```edgeql + scalar type codegen::CalLocalDatetimeType extending cal::local_datetime + ``` + """ + @type codegen__cal_local_datetime_type() :: NaiveDateTime.t() + + @typedoc """ + ```edgeql + scalar type codegen::CalLocalDateType extending cal::local_date + ``` + """ + @type codegen__cal_local_date_type() :: Date.t() + + @typedoc """ + ```edgeql + scalar type codegen::CalDateDurationType extending cal::date_duration + ``` + """ + @type codegen__cal_date_duration_type() :: EdgeDB.DateDuration.t() + + @typedoc """ + ```edgeql + scalar type codegen::BytesType extending std::bytes + ``` + """ + @type codegen__bytes_type() :: bitstring() + + @typedoc """ + ```edgeql + scalar type codegen::BoolType extending std::bool + ``` + """ + @type codegen__bool_type() :: boolean() + + @type result() :: %{ + cp_str: String.t(), + cp_str_type: codegen__str_type(), + cp_bool: boolean(), + cp_bool_type: codegen__bool_type(), + cp_int16: integer(), + cp_int16_type: codegen__int16_type(), + cp_int32: integer(), + cp_int32_type: codegen__int32_type(), + cp_int64: integer(), + cp_int64_type: codegen__int64_type(), + cp_float32: float(), + cp_float32_type: codegen__float32_type(), + cp_float64: float(), + cp_float64_type: codegen__float64_type(), + cp_decimal: Decimal.t(), + cp_decimal_type: codegen__decimal_type(), + cp_json: json(), + cp_json_type: codegen__json_type(), + cp_uuid: uuid(), + cp_uuid_type: codegen__uuid_type(), + cp_enum: codegen__enum_type(), + cp_datetime: DateTime.t(), + cp_datetime_type: codegen__datetime_type(), + cp_duration: duration(), + cp_duration_type: codegen__duration_type(), + cp_cal_local_datetime: NaiveDateTime.t(), + cp_cal_local_datetime_type: codegen__cal_local_datetime_type(), + cp_cal_local_date: Date.t(), + cp_cal_local_date_type: codegen__cal_local_date_type(), + cp_cal_local_time: Time.t(), + cp_cal_local_time_type: codegen__cal_local_time_type(), + cp_cal_relative_duration: EdgeDB.RelativeDuration.t(), + cp_cal_relative_duration_type: codegen__cal_relative_duration_type(), + cp_cal_date_duration: EdgeDB.DateDuration.t(), + cp_cal_date_duration_type: codegen__cal_date_duration_type(), + cp_array_int64: [integer()], + cp_range_int32: EdgeDB.Range.t(integer()), + cp_range_int64: EdgeDB.Range.t(integer()), + cp_range_float32: EdgeDB.Range.t(float()), + cp_range_float64: EdgeDB.Range.t(float()), + cp_range_decimal: EdgeDB.Range.t(Decimal.t()), + cp_range_datetime: EdgeDB.Range.t(DateTime.t()), + cp_range_cal_local_datetime: EdgeDB.Range.t(NaiveDateTime.t()), + cp_range_cal_local_date: EdgeDB.Range.t(Date.t()), + cp_bytes: bitstring(), + cp_bytes_type: codegen__bytes_type(), + cp_cfg_memory: EdgeDB.ConfigMemory.t(), + cp_cfg_memory_type: codegen__cfg_memory_type() + } + + @type keyword_args() :: [ + {:cp_str, String.t()} + | {:cp_str_type, codegen__str_type()} + | {:cp_bool, boolean()} + | {:cp_bool_type, codegen__bool_type()} + | {:cp_int16, integer()} + | {:cp_int16_type, codegen__int16_type()} + | {:cp_int32, integer()} + | {:cp_int32_type, codegen__int32_type()} + | {:cp_int64, integer()} + | {:cp_int64_type, codegen__int64_type()} + | {:cp_float32, float()} + | {:cp_float32_type, codegen__float32_type()} + | {:cp_float64, float()} + | {:cp_float64_type, codegen__float64_type()} + | {:cp_decimal, Decimal.t()} + | {:cp_decimal_type, codegen__decimal_type()} + | {:cp_json, json()} + | {:cp_json_type, codegen__json_type()} + | {:cp_uuid, uuid()} + | {:cp_uuid_type, codegen__uuid_type()} + | {:cp_enum, codegen__enum_type()} + | {:cp_datetime, DateTime.t()} + | {:cp_datetime_type, codegen__datetime_type()} + | {:cp_duration, duration()} + | {:cp_duration_type, codegen__duration_type()} + | {:cp_cal_local_datetime, NaiveDateTime.t()} + | {:cp_cal_local_datetime_type, codegen__cal_local_datetime_type()} + | {:cp_cal_local_date, Date.t()} + | {:cp_cal_local_date_type, codegen__cal_local_date_type()} + | {:cp_cal_local_time, Time.t()} + | {:cp_cal_local_time_type, codegen__cal_local_time_type()} + | {:cp_cal_relative_duration, EdgeDB.RelativeDuration.t()} + | {:cp_cal_relative_duration_type, codegen__cal_relative_duration_type()} + | {:cp_cal_date_duration, EdgeDB.DateDuration.t()} + | {:cp_cal_date_duration_type, codegen__cal_date_duration_type()} + | {:cp_array_int64, [integer()]} + | {:cp_range_int32, EdgeDB.Range.t(integer())} + | {:cp_range_int64, EdgeDB.Range.t(integer())} + | {:cp_range_float32, EdgeDB.Range.t(float())} + | {:cp_range_float64, EdgeDB.Range.t(float())} + | {:cp_range_decimal, EdgeDB.Range.t(Decimal.t())} + | {:cp_range_datetime, EdgeDB.Range.t(DateTime.t())} + | {:cp_range_cal_local_datetime, EdgeDB.Range.t(NaiveDateTime.t())} + | {:cp_range_cal_local_date, EdgeDB.Range.t(Date.t())} + | {:cp_bytes, bitstring()} + | {:cp_bytes_type, codegen__bytes_type()} + | {:cp_cfg_memory, EdgeDB.ConfigMemory.t()} + | {:cp_cfg_memory_type, codegen__cfg_memory_type()} + ] + + @type map_args() :: %{ + cp_str: String.t(), + cp_str_type: codegen__str_type(), + cp_bool: boolean(), + cp_bool_type: codegen__bool_type(), + cp_int16: integer(), + cp_int16_type: codegen__int16_type(), + cp_int32: integer(), + cp_int32_type: codegen__int32_type(), + cp_int64: integer(), + cp_int64_type: codegen__int64_type(), + cp_float32: float(), + cp_float32_type: codegen__float32_type(), + cp_float64: float(), + cp_float64_type: codegen__float64_type(), + cp_decimal: Decimal.t(), + cp_decimal_type: codegen__decimal_type(), + cp_json: json(), + cp_json_type: codegen__json_type(), + cp_uuid: uuid(), + cp_uuid_type: codegen__uuid_type(), + cp_enum: codegen__enum_type(), + cp_datetime: DateTime.t(), + cp_datetime_type: codegen__datetime_type(), + cp_duration: duration(), + cp_duration_type: codegen__duration_type(), + cp_cal_local_datetime: NaiveDateTime.t(), + cp_cal_local_datetime_type: codegen__cal_local_datetime_type(), + cp_cal_local_date: Date.t(), + cp_cal_local_date_type: codegen__cal_local_date_type(), + cp_cal_local_time: Time.t(), + cp_cal_local_time_type: codegen__cal_local_time_type(), + cp_cal_relative_duration: EdgeDB.RelativeDuration.t(), + cp_cal_relative_duration_type: codegen__cal_relative_duration_type(), + cp_cal_date_duration: EdgeDB.DateDuration.t(), + cp_cal_date_duration_type: codegen__cal_date_duration_type(), + cp_array_int64: [integer()], + cp_range_int32: EdgeDB.Range.t(integer()), + cp_range_int64: EdgeDB.Range.t(integer()), + cp_range_float32: EdgeDB.Range.t(float()), + cp_range_float64: EdgeDB.Range.t(float()), + cp_range_decimal: EdgeDB.Range.t(Decimal.t()), + cp_range_datetime: EdgeDB.Range.t(DateTime.t()), + cp_range_cal_local_datetime: EdgeDB.Range.t(NaiveDateTime.t()), + cp_range_cal_local_date: EdgeDB.Range.t(Date.t()), + cp_bytes: bitstring(), + cp_bytes_type: codegen__bytes_type(), + cp_cfg_memory: EdgeDB.ConfigMemory.t(), + cp_cfg_memory_type: codegen__cfg_memory_type() + } + + @type args() :: map_args() | keyword_args() + + @doc """ + Run the query. + """ + @spec query( + client :: EdgeDB.client(), + args :: args(), + opts :: list(EdgeDB.query_option()) + ) :: + {:ok, result()} + | {:error, reason} + when reason: any() + def query(client, args, opts \\ []) do + do_query(client, args, opts) + end + + @doc """ + Run the query. + """ + @spec query!( + client :: EdgeDB.client(), + args :: args(), + opts :: list(EdgeDB.query_option()) + ) :: result() + def query!(client, args, opts \\ []) do + case do_query(client, args, opts) do + {:ok, result} -> + result + + {:error, exc} -> + raise exc + end + end + + @schema [ + :cp_uuid_type, + :cp_uuid, + :cp_str_type, + :cp_str, + :cp_range_int64, + :cp_range_int32, + :cp_range_float64, + :cp_range_float32, + :cp_range_decimal, + :cp_range_datetime, + :cp_range_cal_local_datetime, + :cp_range_cal_local_date, + :cp_json_type, + :cp_json, + :cp_int64_type, + :cp_int64, + :cp_int32_type, + :cp_int32, + :cp_int16_type, + :cp_int16, + :cp_float64_type, + :cp_float64, + :cp_float32_type, + :cp_float32, + :cp_enum, + :cp_duration_type, + :cp_duration, + :cp_decimal_type, + :cp_decimal, + :cp_datetime_type, + :cp_datetime, + :cp_cfg_memory_type, + :cp_cfg_memory, + :cp_cal_relative_duration_type, + :cp_cal_relative_duration, + :cp_cal_local_time_type, + :cp_cal_local_time, + :cp_cal_local_datetime_type, + :cp_cal_local_datetime, + :cp_cal_local_date_type, + :cp_cal_local_date, + :cp_cal_date_duration_type, + :cp_cal_date_duration, + :cp_bytes_type, + :cp_bytes, + :cp_bool_type, + :cp_bool, + :cp_array_int64 + ] + defp do_query(client, args, opts) do + opts = Keyword.merge(opts, __file__: @query_file, __transform_result__: [schema: @schema]) + EdgeDB.query_required_single(client, @query, args, opts) + end +end diff --git a/test/support/codegen/edgeql/standart/select_standart_types_positional.edgeql b/test/support/codegen/edgeql/standart/select_standart_types_positional.edgeql new file mode 100644 index 00000000..23d16430 --- /dev/null +++ b/test/support/codegen/edgeql/standart/select_standart_types_positional.edgeql @@ -0,0 +1,95 @@ +select { + # string + cp_str := $0, + cp_str_type := $1, + + cp_bool := $2, + cp_bool_type := $3, + + cp_int16 := $4, + cp_int16_type := $5, + + cp_int32 := $6, + cp_int32_type := $7, + + cp_int64 := $8, + cp_int64_type := $9, + + cp_float32 := $10, + cp_float32_type := $11, + + cp_float64 := $12, + cp_float64_type := $13, + + cp_decimal := $14, + cp_decimal_type := $15, + + # json + + cp_json := $16, + cp_json_type := $17, + + # uuid + + cp_uuid := $18, + cp_uuid_type := $19, + + # enum + + cp_enum := $20, + + # date/time + + cp_datetime := $21, + cp_datetime_type := $22, + + cp_duration := $23, + cp_duration_type := $24, + + cp_cal_local_datetime := $25, + cp_cal_local_datetime_type := $26, + + cp_cal_local_date := $27, + cp_cal_local_date_type := $28, + + cp_cal_local_time := $29, + cp_cal_local_time_type := $30, + + cp_cal_relative_duration := $31, + cp_cal_relative_duration_type := $32, + + cp_cal_date_duration := $33, + cp_cal_date_duration_type := $34, + + # array + + cp_array_int64 := >$35, + + # range + + cp_range_int32 := >$36, + + cp_range_int64 := >$37, + + cp_range_float32 := >$38, + + cp_range_float64 := >$39, + + cp_range_decimal := >$40, + + cp_range_datetime := >$41, + + cp_range_cal_local_datetime := >$42, + + cp_range_cal_local_date := >$43, + + # bytes + + cp_bytes := $44, + cp_bytes_type := $45, + + # config + + cp_cfg_memory := $46, + cp_cfg_memory_type := $47, +} diff --git a/test/support/codegen/edgeql/standart/select_standart_types_positional.edgeql.ex.assert b/test/support/codegen/edgeql/standart/select_standart_types_positional.edgeql.ex.assert new file mode 100644 index 00000000..15f0c530 --- /dev/null +++ b/test/support/codegen/edgeql/standart/select_standart_types_positional.edgeql.ex.assert @@ -0,0 +1,713 @@ +# AUTOGENERATED: DO NOT MODIFY +# Generated by Elixir client for EdgeDB via `mix edgedb.generate` from +# `test/support/codegen/edgeql/standart/select_standart_types_positional.edgeql`. +defmodule Tests.Codegen.Queries.Standart.SelectStandartTypesPositional do + @query """ + select { + # string + cp_str := $0, + cp_str_type := $1, + + cp_bool := $2, + cp_bool_type := $3, + + cp_int16 := $4, + cp_int16_type := $5, + + cp_int32 := $6, + cp_int32_type := $7, + + cp_int64 := $8, + cp_int64_type := $9, + + cp_float32 := $10, + cp_float32_type := $11, + + cp_float64 := $12, + cp_float64_type := $13, + + cp_decimal := $14, + cp_decimal_type := $15, + + # json + + cp_json := $16, + cp_json_type := $17, + + # uuid + + cp_uuid := $18, + cp_uuid_type := $19, + + # enum + + cp_enum := $20, + + # date/time + + cp_datetime := $21, + cp_datetime_type := $22, + + cp_duration := $23, + cp_duration_type := $24, + + cp_cal_local_datetime := $25, + cp_cal_local_datetime_type := $26, + + cp_cal_local_date := $27, + cp_cal_local_date_type := $28, + + cp_cal_local_time := $29, + cp_cal_local_time_type := $30, + + cp_cal_relative_duration := $31, + cp_cal_relative_duration_type := $32, + + cp_cal_date_duration := $33, + cp_cal_date_duration_type := $34, + + # array + + cp_array_int64 := >$35, + + # range + + cp_range_int32 := >$36, + + cp_range_int64 := >$37, + + cp_range_float32 := >$38, + + cp_range_float64 := >$39, + + cp_range_decimal := >$40, + + cp_range_datetime := >$41, + + cp_range_cal_local_datetime := >$42, + + cp_range_cal_local_date := >$43, + + # bytes + + cp_bytes := $44, + cp_bytes_type := $45, + + # config + + cp_cfg_memory := $46, + cp_cfg_memory_type := $47, + } + """ + + @moduledoc """ + Generated module for the EdgeQL query from + `test/support/codegen/edgeql/standart/select_standart_types_positional.edgeql`. + + Query: + + ```edgeql + #{@query} + ``` + """ + + @query_file "test/support/codegen/edgeql/standart/select_standart_types_positional.edgeql" + + @typedoc """ + ```edgeql + std::uuid + ``` + """ + @type uuid() :: binary() + + @typedoc """ + ```edgeql + std::json + ``` + """ + @type json() :: any() + + @typedoc """ + ```edgeql + std::duration + ``` + """ + @type duration() :: Timex.Duration.t() | integer() + + @typedoc """ + ```edgeql + scalar type codegen::UuidType extending std::uuid + ``` + """ + @type codegen__uuid_type() :: binary() + + @typedoc """ + ```edgeql + scalar type codegen::StrType extending std::str + ``` + """ + @type codegen__str_type() :: String.t() + + @typedoc """ + ```edgeql + scalar type codegen::JsonType extending std::json + ``` + """ + @type codegen__json_type() :: any() + + @typedoc """ + ```edgeql + scalar type codegen::Int64Type extending std::int64 + ``` + """ + @type codegen__int64_type() :: integer() + + @typedoc """ + ```edgeql + scalar type codegen::Int32Type extending std::int32 + ``` + """ + @type codegen__int32_type() :: integer() + + @typedoc """ + ```edgeql + scalar type codegen::Int16Type extending std::int16 + ``` + """ + @type codegen__int16_type() :: integer() + + @typedoc """ + ```edgeql + scalar type codegen::Float64Type extending std::float64 + ``` + """ + @type codegen__float64_type() :: float() + + @typedoc """ + ```edgeql + scalar type codegen::Float32Type extending std::float32 + ``` + """ + @type codegen__float32_type() :: float() + + @typedoc """ + ```edgeql + scalar type codegen::EnumType extending enum + ``` + """ + @type codegen__enum_type() :: String.t() | :A | :B | :C + + @typedoc """ + ```edgeql + scalar type codegen::DurationType extending std::duration + ``` + """ + @type codegen__duration_type() :: integer() + + @typedoc """ + ```edgeql + scalar type codegen::DecimalType extending std::decimal + ``` + """ + @type codegen__decimal_type() :: Decimal.t() + + @typedoc """ + ```edgeql + scalar type codegen::DatetimeType extending std::datetime + ``` + """ + @type codegen__datetime_type() :: DateTime.t() + + @typedoc """ + ```edgeql + scalar type codegen::CfgMemoryType extending cfg::memory + ``` + """ + @type codegen__cfg_memory_type() :: EdgeDB.ConfigMemory.t() + + @typedoc """ + ```edgeql + scalar type codegen::CalRelativeDurationType extending cal::relative_duration + ``` + """ + @type codegen__cal_relative_duration_type() :: EdgeDB.RelativeDuration.t() + + @typedoc """ + ```edgeql + scalar type codegen::CalLocalTimeType extending cal::local_time + ``` + """ + @type codegen__cal_local_time_type() :: Time.t() + + @typedoc """ + ```edgeql + scalar type codegen::CalLocalDatetimeType extending cal::local_datetime + ``` + """ + @type codegen__cal_local_datetime_type() :: NaiveDateTime.t() + + @typedoc """ + ```edgeql + scalar type codegen::CalLocalDateType extending cal::local_date + ``` + """ + @type codegen__cal_local_date_type() :: Date.t() + + @typedoc """ + ```edgeql + scalar type codegen::CalDateDurationType extending cal::date_duration + ``` + """ + @type codegen__cal_date_duration_type() :: EdgeDB.DateDuration.t() + + @typedoc """ + ```edgeql + scalar type codegen::BytesType extending std::bytes + ``` + """ + @type codegen__bytes_type() :: bitstring() + + @typedoc """ + ```edgeql + scalar type codegen::BoolType extending std::bool + ``` + """ + @type codegen__bool_type() :: boolean() + + @type result() :: %{ + cp_str: String.t(), + cp_str_type: codegen__str_type(), + cp_bool: boolean(), + cp_bool_type: codegen__bool_type(), + cp_int16: integer(), + cp_int16_type: codegen__int16_type(), + cp_int32: integer(), + cp_int32_type: codegen__int32_type(), + cp_int64: integer(), + cp_int64_type: codegen__int64_type(), + cp_float32: float(), + cp_float32_type: codegen__float32_type(), + cp_float64: float(), + cp_float64_type: codegen__float64_type(), + cp_decimal: Decimal.t(), + cp_decimal_type: codegen__decimal_type(), + cp_json: json(), + cp_json_type: codegen__json_type(), + cp_uuid: uuid(), + cp_uuid_type: codegen__uuid_type(), + cp_enum: codegen__enum_type(), + cp_datetime: DateTime.t(), + cp_datetime_type: codegen__datetime_type(), + cp_duration: duration(), + cp_duration_type: codegen__duration_type(), + cp_cal_local_datetime: NaiveDateTime.t(), + cp_cal_local_datetime_type: codegen__cal_local_datetime_type(), + cp_cal_local_date: Date.t(), + cp_cal_local_date_type: codegen__cal_local_date_type(), + cp_cal_local_time: Time.t(), + cp_cal_local_time_type: codegen__cal_local_time_type(), + cp_cal_relative_duration: EdgeDB.RelativeDuration.t(), + cp_cal_relative_duration_type: codegen__cal_relative_duration_type(), + cp_cal_date_duration: EdgeDB.DateDuration.t(), + cp_cal_date_duration_type: codegen__cal_date_duration_type(), + cp_array_int64: [integer()], + cp_range_int32: EdgeDB.Range.t(integer()), + cp_range_int64: EdgeDB.Range.t(integer()), + cp_range_float32: EdgeDB.Range.t(float()), + cp_range_float64: EdgeDB.Range.t(float()), + cp_range_decimal: EdgeDB.Range.t(Decimal.t()), + cp_range_datetime: EdgeDB.Range.t(DateTime.t()), + cp_range_cal_local_datetime: EdgeDB.Range.t(NaiveDateTime.t()), + cp_range_cal_local_date: EdgeDB.Range.t(Date.t()), + cp_bytes: bitstring(), + cp_bytes_type: codegen__bytes_type(), + cp_cfg_memory: EdgeDB.ConfigMemory.t(), + cp_cfg_memory_type: codegen__cfg_memory_type() + } + + @doc """ + Run the query. + """ + @spec query( + client :: EdgeDB.client(), + arg_0 :: String.t(), + arg_1 :: codegen__str_type(), + arg_2 :: boolean(), + arg_3 :: codegen__bool_type(), + arg_4 :: integer(), + arg_5 :: codegen__int16_type(), + arg_6 :: integer(), + arg_7 :: codegen__int32_type(), + arg_8 :: integer(), + arg_9 :: codegen__int64_type(), + arg_10 :: float(), + arg_11 :: codegen__float32_type(), + arg_12 :: float(), + arg_13 :: codegen__float64_type(), + arg_14 :: Decimal.t(), + arg_15 :: codegen__decimal_type(), + arg_16 :: json(), + arg_17 :: codegen__json_type(), + arg_18 :: uuid(), + arg_19 :: codegen__uuid_type(), + arg_20 :: codegen__enum_type(), + arg_21 :: DateTime.t(), + arg_22 :: codegen__datetime_type(), + arg_23 :: duration(), + arg_24 :: codegen__duration_type(), + arg_25 :: NaiveDateTime.t(), + arg_26 :: codegen__cal_local_datetime_type(), + arg_27 :: Date.t(), + arg_28 :: codegen__cal_local_date_type(), + arg_29 :: Time.t(), + arg_30 :: codegen__cal_local_time_type(), + arg_31 :: EdgeDB.RelativeDuration.t(), + arg_32 :: codegen__cal_relative_duration_type(), + arg_33 :: EdgeDB.DateDuration.t(), + arg_34 :: codegen__cal_date_duration_type(), + arg_35 :: [integer()], + arg_36 :: EdgeDB.Range.t(integer()), + arg_37 :: EdgeDB.Range.t(integer()), + arg_38 :: EdgeDB.Range.t(float()), + arg_39 :: EdgeDB.Range.t(float()), + arg_40 :: EdgeDB.Range.t(Decimal.t()), + arg_41 :: EdgeDB.Range.t(DateTime.t()), + arg_42 :: EdgeDB.Range.t(NaiveDateTime.t()), + arg_43 :: EdgeDB.Range.t(Date.t()), + arg_44 :: bitstring(), + arg_45 :: codegen__bytes_type(), + arg_46 :: EdgeDB.ConfigMemory.t(), + arg_47 :: codegen__cfg_memory_type(), + opts :: list(EdgeDB.query_option()) + ) :: + {:ok, result()} + | {:error, reason} + when reason: any() + def query( + client, + arg_0, + arg_1, + arg_2, + arg_3, + arg_4, + arg_5, + arg_6, + arg_7, + arg_8, + arg_9, + arg_10, + arg_11, + arg_12, + arg_13, + arg_14, + arg_15, + arg_16, + arg_17, + arg_18, + arg_19, + arg_20, + arg_21, + arg_22, + arg_23, + arg_24, + arg_25, + arg_26, + arg_27, + arg_28, + arg_29, + arg_30, + arg_31, + arg_32, + arg_33, + arg_34, + arg_35, + arg_36, + arg_37, + arg_38, + arg_39, + arg_40, + arg_41, + arg_42, + arg_43, + arg_44, + arg_45, + arg_46, + arg_47, + opts \\ [] + ) do + args = [ + arg_0, + arg_1, + arg_2, + arg_3, + arg_4, + arg_5, + arg_6, + arg_7, + arg_8, + arg_9, + arg_10, + arg_11, + arg_12, + arg_13, + arg_14, + arg_15, + arg_16, + arg_17, + arg_18, + arg_19, + arg_20, + arg_21, + arg_22, + arg_23, + arg_24, + arg_25, + arg_26, + arg_27, + arg_28, + arg_29, + arg_30, + arg_31, + arg_32, + arg_33, + arg_34, + arg_35, + arg_36, + arg_37, + arg_38, + arg_39, + arg_40, + arg_41, + arg_42, + arg_43, + arg_44, + arg_45, + arg_46, + arg_47 + ] + + do_query(client, args, opts) + end + + @doc """ + Run the query. + """ + @spec query!( + client :: EdgeDB.client(), + arg_0 :: String.t(), + arg_1 :: codegen__str_type(), + arg_2 :: boolean(), + arg_3 :: codegen__bool_type(), + arg_4 :: integer(), + arg_5 :: codegen__int16_type(), + arg_6 :: integer(), + arg_7 :: codegen__int32_type(), + arg_8 :: integer(), + arg_9 :: codegen__int64_type(), + arg_10 :: float(), + arg_11 :: codegen__float32_type(), + arg_12 :: float(), + arg_13 :: codegen__float64_type(), + arg_14 :: Decimal.t(), + arg_15 :: codegen__decimal_type(), + arg_16 :: json(), + arg_17 :: codegen__json_type(), + arg_18 :: uuid(), + arg_19 :: codegen__uuid_type(), + arg_20 :: codegen__enum_type(), + arg_21 :: DateTime.t(), + arg_22 :: codegen__datetime_type(), + arg_23 :: duration(), + arg_24 :: codegen__duration_type(), + arg_25 :: NaiveDateTime.t(), + arg_26 :: codegen__cal_local_datetime_type(), + arg_27 :: Date.t(), + arg_28 :: codegen__cal_local_date_type(), + arg_29 :: Time.t(), + arg_30 :: codegen__cal_local_time_type(), + arg_31 :: EdgeDB.RelativeDuration.t(), + arg_32 :: codegen__cal_relative_duration_type(), + arg_33 :: EdgeDB.DateDuration.t(), + arg_34 :: codegen__cal_date_duration_type(), + arg_35 :: [integer()], + arg_36 :: EdgeDB.Range.t(integer()), + arg_37 :: EdgeDB.Range.t(integer()), + arg_38 :: EdgeDB.Range.t(float()), + arg_39 :: EdgeDB.Range.t(float()), + arg_40 :: EdgeDB.Range.t(Decimal.t()), + arg_41 :: EdgeDB.Range.t(DateTime.t()), + arg_42 :: EdgeDB.Range.t(NaiveDateTime.t()), + arg_43 :: EdgeDB.Range.t(Date.t()), + arg_44 :: bitstring(), + arg_45 :: codegen__bytes_type(), + arg_46 :: EdgeDB.ConfigMemory.t(), + arg_47 :: codegen__cfg_memory_type(), + opts :: list(EdgeDB.query_option()) + ) :: result() + def query!( + client, + arg_0, + arg_1, + arg_2, + arg_3, + arg_4, + arg_5, + arg_6, + arg_7, + arg_8, + arg_9, + arg_10, + arg_11, + arg_12, + arg_13, + arg_14, + arg_15, + arg_16, + arg_17, + arg_18, + arg_19, + arg_20, + arg_21, + arg_22, + arg_23, + arg_24, + arg_25, + arg_26, + arg_27, + arg_28, + arg_29, + arg_30, + arg_31, + arg_32, + arg_33, + arg_34, + arg_35, + arg_36, + arg_37, + arg_38, + arg_39, + arg_40, + arg_41, + arg_42, + arg_43, + arg_44, + arg_45, + arg_46, + arg_47, + opts \\ [] + ) do + args = [ + arg_0, + arg_1, + arg_2, + arg_3, + arg_4, + arg_5, + arg_6, + arg_7, + arg_8, + arg_9, + arg_10, + arg_11, + arg_12, + arg_13, + arg_14, + arg_15, + arg_16, + arg_17, + arg_18, + arg_19, + arg_20, + arg_21, + arg_22, + arg_23, + arg_24, + arg_25, + arg_26, + arg_27, + arg_28, + arg_29, + arg_30, + arg_31, + arg_32, + arg_33, + arg_34, + arg_35, + arg_36, + arg_37, + arg_38, + arg_39, + arg_40, + arg_41, + arg_42, + arg_43, + arg_44, + arg_45, + arg_46, + arg_47 + ] + + case do_query(client, args, opts) do + {:ok, result} -> + result + + {:error, exc} -> + raise exc + end + end + + @schema [ + :cp_uuid_type, + :cp_uuid, + :cp_str_type, + :cp_str, + :cp_range_int64, + :cp_range_int32, + :cp_range_float64, + :cp_range_float32, + :cp_range_decimal, + :cp_range_datetime, + :cp_range_cal_local_datetime, + :cp_range_cal_local_date, + :cp_json_type, + :cp_json, + :cp_int64_type, + :cp_int64, + :cp_int32_type, + :cp_int32, + :cp_int16_type, + :cp_int16, + :cp_float64_type, + :cp_float64, + :cp_float32_type, + :cp_float32, + :cp_enum, + :cp_duration_type, + :cp_duration, + :cp_decimal_type, + :cp_decimal, + :cp_datetime_type, + :cp_datetime, + :cp_cfg_memory_type, + :cp_cfg_memory, + :cp_cal_relative_duration_type, + :cp_cal_relative_duration, + :cp_cal_local_time_type, + :cp_cal_local_time, + :cp_cal_local_datetime_type, + :cp_cal_local_datetime, + :cp_cal_local_date_type, + :cp_cal_local_date, + :cp_cal_date_duration_type, + :cp_cal_date_duration, + :cp_bytes_type, + :cp_bytes, + :cp_bool_type, + :cp_bool, + :cp_array_int64 + ] + defp do_query(client, args, opts) do + opts = Keyword.merge(opts, __file__: @query_file, __transform_result__: [schema: @schema]) + EdgeDB.query_required_single(client, @query, args, opts) + end +end diff --git a/test/support/codegen/edgeql/standart/select_startart_types_named_simple.edgeql b/test/support/codegen/edgeql/standart/select_startart_types_named_simple.edgeql new file mode 100644 index 00000000..104bad8f --- /dev/null +++ b/test/support/codegen/edgeql/standart/select_startart_types_named_simple.edgeql @@ -0,0 +1,11 @@ +select { + a := 1, + b := { + b_a := 2, + b_b := 3 + }, + c := "hello world", + d := {4, 5, 6}, + e := $e, + f := $f, +} diff --git a/test/support/codegen/edgeql/standart/select_startart_types_named_simple.edgeql.ex.assert b/test/support/codegen/edgeql/standart/select_startart_types_named_simple.edgeql.ex.assert new file mode 100644 index 00000000..21c8bd0f --- /dev/null +++ b/test/support/codegen/edgeql/standart/select_startart_types_named_simple.edgeql.ex.assert @@ -0,0 +1,88 @@ +# AUTOGENERATED: DO NOT MODIFY +# Generated by Elixir client for EdgeDB via `mix edgedb.generate` from +# `test/support/codegen/edgeql/standart/select_startart_types_named_simple.edgeql`. +defmodule Tests.Codegen.Queries.Standart.SelectStartartTypesNamedSimple do + @query """ + select { + a := 1, + b := { + b_a := 2, + b_b := 3 + }, + c := "hello world", + d := {4, 5, 6}, + e := $e, + f := $f, + } + """ + + @moduledoc """ + Generated module for the EdgeQL query from + `test/support/codegen/edgeql/standart/select_startart_types_named_simple.edgeql`. + + Query: + + ```edgeql + #{@query} + ``` + """ + + @query_file "test/support/codegen/edgeql/standart/select_startart_types_named_simple.edgeql" + + @type result() :: %{ + a: integer(), + b: %{b_a: integer(), b_b: integer()}, + c: String.t(), + d: [integer()], + e: String.t(), + f: integer() + } + + @type keyword_args() :: [{:e, String.t()} | {:f, integer()}] + + @type map_args() :: %{ + e: String.t(), + f: integer() + } + + @type args() :: map_args() | keyword_args() + + @doc """ + Run the query. + """ + @spec query( + client :: EdgeDB.client(), + args :: args(), + opts :: list(EdgeDB.query_option()) + ) :: + {:ok, result()} + | {:error, reason} + when reason: any() + def query(client, args, opts \\ []) do + do_query(client, args, opts) + end + + @doc """ + Run the query. + """ + @spec query!( + client :: EdgeDB.client(), + args :: args(), + opts :: list(EdgeDB.query_option()) + ) :: result() + def query!(client, args, opts \\ []) do + case do_query(client, args, opts) do + {:ok, result} -> + result + + {:error, exc} -> + raise exc + end + end + + @schema [:f, :e, :d, :c, :a, b: [:b_b, :b_a]] + defp do_query(client, args, opts) do + opts = Keyword.merge(opts, __file__: @query_file, __transform_result__: [schema: @schema]) + EdgeDB.query_required_single(client, @query, args, opts) + end +end diff --git a/test/support/codegen/edgeql/types/insert_f_named.edgeql b/test/support/codegen/edgeql/types/insert_f_named.edgeql new file mode 100644 index 00000000..2c9c5b03 --- /dev/null +++ b/test/support/codegen/edgeql/types/insert_f_named.edgeql @@ -0,0 +1,11 @@ +with l_e := (insert codegen::E{ rp_a_str := $rp_a_str, rp_e_str := $rp_e_str }) +insert codegen::F { + rp_a_str := $rp_a_str, + rp_b_str := $rp_b_str, + rp_c_str := $rp_c_str, + rp_d_str := $rp_d_str, + rp_f_str := $rp_f_str, + + ol_a_b := l_e, + ml_a_b := {l_e}, +} diff --git a/test/support/codegen/edgeql/types/insert_f_named.edgeql.ex.assert b/test/support/codegen/edgeql/types/insert_f_named.edgeql.ex.assert new file mode 100644 index 00000000..1850fe64 --- /dev/null +++ b/test/support/codegen/edgeql/types/insert_f_named.edgeql.ex.assert @@ -0,0 +1,91 @@ +# AUTOGENERATED: DO NOT MODIFY +# Generated by Elixir client for EdgeDB via `mix edgedb.generate` from +# `test/support/codegen/edgeql/types/insert_f_named.edgeql`. +defmodule Tests.Codegen.Queries.Types.InsertFNamed do + @query """ + with l_e := (insert codegen::E{ rp_a_str := $rp_a_str, rp_e_str := $rp_e_str }) + insert codegen::F { + rp_a_str := $rp_a_str, + rp_b_str := $rp_b_str, + rp_c_str := $rp_c_str, + rp_d_str := $rp_d_str, + rp_f_str := $rp_f_str, + + ol_a_b := l_e, + ml_a_b := {l_e}, + } + """ + + @moduledoc """ + Generated module for the EdgeQL query from + `test/support/codegen/edgeql/types/insert_f_named.edgeql`. + + Query: + + ```edgeql + #{@query} + ``` + """ + + @query_file "test/support/codegen/edgeql/types/insert_f_named.edgeql" + + @type result() :: %{} + + @type keyword_args() :: [ + {:rp_a_str, String.t()} + | {:rp_e_str, String.t()} + | {:rp_b_str, String.t()} + | {:rp_c_str, String.t()} + | {:rp_d_str, String.t()} + | {:rp_f_str, String.t()} + ] + + @type map_args() :: %{ + rp_a_str: String.t(), + rp_e_str: String.t(), + rp_b_str: String.t(), + rp_c_str: String.t(), + rp_d_str: String.t(), + rp_f_str: String.t() + } + + @type args() :: map_args() | keyword_args() + + @doc """ + Run the query. + """ + @spec query( + client :: EdgeDB.client(), + args :: args(), + opts :: list(EdgeDB.query_option()) + ) :: + {:ok, result()} + | {:error, reason} + when reason: any() + def query(client, args, opts \\ []) do + do_query(client, args, opts) + end + + @doc """ + Run the query. + """ + @spec query!( + client :: EdgeDB.client(), + args :: args(), + opts :: list(EdgeDB.query_option()) + ) :: result() + def query!(client, args, opts \\ []) do + case do_query(client, args, opts) do + {:ok, result} -> + result + + {:error, exc} -> + raise exc + end + end + + defp do_query(client, args, opts) do + opts = Keyword.merge(opts, __file__: @query_file) + EdgeDB.query_required_single(client, @query, args, opts) + end +end diff --git a/test/support/codegen/edgeql/types/insert_f_positional.edgeql b/test/support/codegen/edgeql/types/insert_f_positional.edgeql new file mode 100644 index 00000000..f50de887 --- /dev/null +++ b/test/support/codegen/edgeql/types/insert_f_positional.edgeql @@ -0,0 +1,11 @@ +with l_e := (insert codegen::E{ rp_a_str := $0, rp_e_str := $4 }) +insert codegen::F { + rp_a_str := $0, + rp_b_str := $1, + rp_c_str := $2, + rp_d_str := $3, + rp_f_str := $5, + + ol_a_b := l_e, + ml_a_b := {l_e}, +} diff --git a/test/support/codegen/edgeql/types/insert_f_positional.edgeql.ex.assert b/test/support/codegen/edgeql/types/insert_f_positional.edgeql.ex.assert new file mode 100644 index 00000000..7d4fdfc0 --- /dev/null +++ b/test/support/codegen/edgeql/types/insert_f_positional.edgeql.ex.assert @@ -0,0 +1,84 @@ +# AUTOGENERATED: DO NOT MODIFY +# Generated by Elixir client for EdgeDB via `mix edgedb.generate` from +# `test/support/codegen/edgeql/types/insert_f_positional.edgeql`. +defmodule Tests.Codegen.Queries.Types.InsertFPositional do + @query """ + with l_e := (insert codegen::E{ rp_a_str := $0, rp_e_str := $4 }) + insert codegen::F { + rp_a_str := $0, + rp_b_str := $1, + rp_c_str := $2, + rp_d_str := $3, + rp_f_str := $5, + + ol_a_b := l_e, + ml_a_b := {l_e}, + } + """ + + @moduledoc """ + Generated module for the EdgeQL query from + `test/support/codegen/edgeql/types/insert_f_positional.edgeql`. + + Query: + + ```edgeql + #{@query} + ``` + """ + + @query_file "test/support/codegen/edgeql/types/insert_f_positional.edgeql" + + @type result() :: %{} + + @doc """ + Run the query. + """ + @spec query( + client :: EdgeDB.client(), + arg_0 :: String.t(), + arg_1 :: String.t(), + arg_2 :: String.t(), + arg_3 :: String.t(), + arg_4 :: String.t(), + arg_5 :: String.t(), + opts :: list(EdgeDB.query_option()) + ) :: + {:ok, result()} + | {:error, reason} + when reason: any() + def query(client, arg_0, arg_1, arg_2, arg_3, arg_4, arg_5, opts \\ []) do + args = [arg_0, arg_1, arg_2, arg_3, arg_4, arg_5] + do_query(client, args, opts) + end + + @doc """ + Run the query. + """ + @spec query!( + client :: EdgeDB.client(), + arg_0 :: String.t(), + arg_1 :: String.t(), + arg_2 :: String.t(), + arg_3 :: String.t(), + arg_4 :: String.t(), + arg_5 :: String.t(), + opts :: list(EdgeDB.query_option()) + ) :: result() + def query!(client, arg_0, arg_1, arg_2, arg_3, arg_4, arg_5, opts \\ []) do + args = [arg_0, arg_1, arg_2, arg_3, arg_4, arg_5] + + case do_query(client, args, opts) do + {:ok, result} -> + result + + {:error, exc} -> + raise exc + end + end + + defp do_query(client, args, opts) do + opts = Keyword.merge(opts, __file__: @query_file) + EdgeDB.query_required_single(client, @query, args, opts) + end +end diff --git a/test/support/codegen/edgeql/types/select_result.edgeql b/test/support/codegen/edgeql/types/select_result.edgeql new file mode 100644 index 00000000..42244381 --- /dev/null +++ b/test/support/codegen/edgeql/types/select_result.edgeql @@ -0,0 +1,355 @@ +select codegen::Result { + # special + id, + + # properties + + # string + + rp_str, + op_str, + mp_str, + + rp_str_type, + op_str_type, + mp_str_type, + + # boolean + + rp_bool, + op_bool, + mp_bool, + + rp_bool_type, + op_bool_type, + mp_bool_type, + + # number + + rp_int16, + op_int16, + mp_int16, + + rp_int16_type, + op_int16_type, + mp_int16_type, + + rp_int32, + op_int32, + mp_int32, + + rp_int32_type, + op_int32_type, + mp_int32_type, + + rp_int64, + op_int64, + mp_int64, + + rp_int64_type, + op_int64_type, + mp_int64_type, + + rp_float32, + op_float32, + mp_float32, + + rp_float32_type, + op_float32_type, + mp_float32_type, + + rp_float64, + op_float64, + mp_float64, + + rp_float64_type, + op_float64_type, + mp_float64_type, + + rp_decimal, + op_decimal, + mp_decimal, + + rp_decimal_type, + op_decimal_type, + mp_decimal_type, + + # json + + rp_json, + op_json, + mp_json, + + rp_json_type, + op_json_type, + mp_json_type, + + # uuid + + rp_uuid, + op_uuid, + mp_uuid, + + rp_uuid_type, + op_uuid_type, + mp_uuid_type, + + # enum + + rp_enum, + op_enum, + mp_enum, + + # date/time + + rp_datetime, + op_datetime, + mp_datetime, + + rp_datetime_type, + op_datetime_type, + mp_datetime_type, + + rp_duration, + op_duration, + mp_duration, + + rp_duration_type, + op_duration_type, + mp_duration_type, + + rp_cal_local_datetime, + op_cal_local_datetime, + mp_cal_local_datetime, + + rp_cal_local_datetime_type, + op_cal_local_datetime_type, + mp_cal_local_datetime_type, + + rp_cal_local_date, + op_cal_local_date, + mp_cal_local_date, + + rp_cal_local_date_type, + op_cal_local_date_type, + mp_cal_local_date_type, + + rp_cal_local_time, + op_cal_local_time, + mp_cal_local_time, + + rp_cal_local_time_type, + op_cal_local_time_type, + mp_cal_local_time_type, + + rp_cal_relative_duration, + op_cal_relative_duration, + mp_cal_relative_duration, + + rp_cal_relative_duration_type, + op_cal_relative_duration_type, + mp_cal_relative_duration_type, + + rp_cal_date_duration, + op_cal_date_duration, + mp_cal_date_duration, + + rp_cal_date_duration_type, + op_cal_date_duration_type, + mp_cal_date_duration_type, + + # array + + rp_array_int64, + op_array_int64, + mp_array_int64, + + # tuple + + rp_tuple_int64_int64, + op_tuple_int64_int64, + mp_tuple_int64_int64, + + rp_named_tuple_x_int64_y_int64, + op_named_tuple_x_int64_y_int64, + mp_named_tuple_x_int64_y_int64, + + # range + + rp_range_int32, + op_range_int32, + mp_range_int32, + + rp_range_int64, + op_range_int64, + mp_range_int64, + + rp_range_float32, + op_range_float32, + mp_range_float32, + + rp_range_float64, + op_range_float64, + mp_range_float64, + + rp_range_decimal, + op_range_decimal, + mp_range_decimal, + + rp_range_datetime, + op_range_datetime, + mp_range_datetime, + + rp_range_cal_local_datetime, + op_range_cal_local_datetime, + mp_range_cal_local_datetime, + + rp_range_cal_local_date, + op_range_cal_local_date, + mp_range_cal_local_date, + + # bytes + + rp_bytes, + op_bytes, + mp_bytes, + + rp_bytes_type, + op_bytes_type, + mp_bytes_type, + + # sequence + + rp_sequence, + op_sequence, + mp_sequence, + + # config + + rp_cfg_memory, + op_cfg_memory, + mp_cfg_memory, + + rp_cfg_memory_type, + op_cfg_memory_type, + mp_cfg_memory_type, + + # links + + rl_f: { + # special + + id, + + # properties + + rp_a_str, + rp_b_str, + rp_c_str, + rp_d_str, + rp_f_str, + + # links + + ol_a: { + id, + rp_a_str, + rp_e_str, + }, + + ml_a: { + id, + rp_a_str, + rp_e_str, + }, + + ol_a_b: { + id, + }, + + ml_a_b: { + id, + }, + }, + + ol_f: { + # special + + id, + + # properties + + rp_a_str, + rp_b_str, + rp_c_str, + rp_d_str, + rp_f_str, + + # links + + ol_a: { + id, + rp_a_str, + rp_e_str, + }, + + ml_a: { + id, + rp_a_str, + rp_e_str, + }, + + ol_a_b: { + id, + }, + + ml_a_b: { + id, + }, + }, + + ml_f: { + # special + + id, + + # properties + + rp_a_str, + rp_b_str, + rp_c_str, + rp_d_str, + rp_f_str, + + # links + + ol_a: { + id, + rp_a_str, + rp_e_str, + }, + + ml_a: { + id, + rp_a_str, + rp_e_str, + }, + + ol_a_b: { + id, + }, + + ml_a_b: { + id, + }, + }, + + rl_lp_f: { + id, + + # link properties + + @olp_a, + } +} +filter .id in array_unpack(>$ids) diff --git a/test/support/codegen/edgeql/types/select_result.edgeql.ex.assert b/test/support/codegen/edgeql/types/select_result.edgeql.ex.assert new file mode 100644 index 00000000..5b8b6f57 --- /dev/null +++ b/test/support/codegen/edgeql/types/select_result.edgeql.ex.assert @@ -0,0 +1,990 @@ +# AUTOGENERATED: DO NOT MODIFY +# Generated by Elixir client for EdgeDB via `mix edgedb.generate` from +# `test/support/codegen/edgeql/types/select_result.edgeql`. +defmodule Tests.Codegen.Queries.Types.SelectResult do + @query """ + select codegen::Result { + # special + id, + + # properties + + # string + + rp_str, + op_str, + mp_str, + + rp_str_type, + op_str_type, + mp_str_type, + + # boolean + + rp_bool, + op_bool, + mp_bool, + + rp_bool_type, + op_bool_type, + mp_bool_type, + + # number + + rp_int16, + op_int16, + mp_int16, + + rp_int16_type, + op_int16_type, + mp_int16_type, + + rp_int32, + op_int32, + mp_int32, + + rp_int32_type, + op_int32_type, + mp_int32_type, + + rp_int64, + op_int64, + mp_int64, + + rp_int64_type, + op_int64_type, + mp_int64_type, + + rp_float32, + op_float32, + mp_float32, + + rp_float32_type, + op_float32_type, + mp_float32_type, + + rp_float64, + op_float64, + mp_float64, + + rp_float64_type, + op_float64_type, + mp_float64_type, + + rp_decimal, + op_decimal, + mp_decimal, + + rp_decimal_type, + op_decimal_type, + mp_decimal_type, + + # json + + rp_json, + op_json, + mp_json, + + rp_json_type, + op_json_type, + mp_json_type, + + # uuid + + rp_uuid, + op_uuid, + mp_uuid, + + rp_uuid_type, + op_uuid_type, + mp_uuid_type, + + # enum + + rp_enum, + op_enum, + mp_enum, + + # date/time + + rp_datetime, + op_datetime, + mp_datetime, + + rp_datetime_type, + op_datetime_type, + mp_datetime_type, + + rp_duration, + op_duration, + mp_duration, + + rp_duration_type, + op_duration_type, + mp_duration_type, + + rp_cal_local_datetime, + op_cal_local_datetime, + mp_cal_local_datetime, + + rp_cal_local_datetime_type, + op_cal_local_datetime_type, + mp_cal_local_datetime_type, + + rp_cal_local_date, + op_cal_local_date, + mp_cal_local_date, + + rp_cal_local_date_type, + op_cal_local_date_type, + mp_cal_local_date_type, + + rp_cal_local_time, + op_cal_local_time, + mp_cal_local_time, + + rp_cal_local_time_type, + op_cal_local_time_type, + mp_cal_local_time_type, + + rp_cal_relative_duration, + op_cal_relative_duration, + mp_cal_relative_duration, + + rp_cal_relative_duration_type, + op_cal_relative_duration_type, + mp_cal_relative_duration_type, + + rp_cal_date_duration, + op_cal_date_duration, + mp_cal_date_duration, + + rp_cal_date_duration_type, + op_cal_date_duration_type, + mp_cal_date_duration_type, + + # array + + rp_array_int64, + op_array_int64, + mp_array_int64, + + # tuple + + rp_tuple_int64_int64, + op_tuple_int64_int64, + mp_tuple_int64_int64, + + rp_named_tuple_x_int64_y_int64, + op_named_tuple_x_int64_y_int64, + mp_named_tuple_x_int64_y_int64, + + # range + + rp_range_int32, + op_range_int32, + mp_range_int32, + + rp_range_int64, + op_range_int64, + mp_range_int64, + + rp_range_float32, + op_range_float32, + mp_range_float32, + + rp_range_float64, + op_range_float64, + mp_range_float64, + + rp_range_decimal, + op_range_decimal, + mp_range_decimal, + + rp_range_datetime, + op_range_datetime, + mp_range_datetime, + + rp_range_cal_local_datetime, + op_range_cal_local_datetime, + mp_range_cal_local_datetime, + + rp_range_cal_local_date, + op_range_cal_local_date, + mp_range_cal_local_date, + + # bytes + + rp_bytes, + op_bytes, + mp_bytes, + + rp_bytes_type, + op_bytes_type, + mp_bytes_type, + + # sequence + + rp_sequence, + op_sequence, + mp_sequence, + + # config + + rp_cfg_memory, + op_cfg_memory, + mp_cfg_memory, + + rp_cfg_memory_type, + op_cfg_memory_type, + mp_cfg_memory_type, + + # links + + rl_f: { + # special + + id, + + # properties + + rp_a_str, + rp_b_str, + rp_c_str, + rp_d_str, + rp_f_str, + + # links + + ol_a: { + id, + rp_a_str, + rp_e_str, + }, + + ml_a: { + id, + rp_a_str, + rp_e_str, + }, + + ol_a_b: { + id, + }, + + ml_a_b: { + id, + }, + }, + + ol_f: { + # special + + id, + + # properties + + rp_a_str, + rp_b_str, + rp_c_str, + rp_d_str, + rp_f_str, + + # links + + ol_a: { + id, + rp_a_str, + rp_e_str, + }, + + ml_a: { + id, + rp_a_str, + rp_e_str, + }, + + ol_a_b: { + id, + }, + + ml_a_b: { + id, + }, + }, + + ml_f: { + # special + + id, + + # properties + + rp_a_str, + rp_b_str, + rp_c_str, + rp_d_str, + rp_f_str, + + # links + + ol_a: { + id, + rp_a_str, + rp_e_str, + }, + + ml_a: { + id, + rp_a_str, + rp_e_str, + }, + + ol_a_b: { + id, + }, + + ml_a_b: { + id, + }, + }, + + rl_lp_f: { + id, + + # link properties + + @olp_a, + } + } + filter .id in array_unpack(>$ids) + """ + + @moduledoc """ + Generated module for the EdgeQL query from + `test/support/codegen/edgeql/types/select_result.edgeql`. + + Query: + + ```edgeql + #{@query} + ``` + """ + + @query_file "test/support/codegen/edgeql/types/select_result.edgeql" + + @typedoc """ + ```edgeql + std::uuid + ``` + """ + @type uuid() :: binary() + + @typedoc """ + ```edgeql + std::json + ``` + """ + @type json() :: any() + + @typedoc """ + ```edgeql + std::duration + ``` + """ + @type duration() :: Timex.Duration.t() | integer() + + @typedoc """ + ```edgeql + scalar type codegen::UuidType extending std::uuid + ``` + """ + @type codegen__uuid_type() :: binary() + + @typedoc """ + ```edgeql + scalar type codegen::StrType extending std::str + ``` + """ + @type codegen__str_type() :: String.t() + + @typedoc """ + ```edgeql + scalar type codegen::SequenceType extending std::int64 + ``` + """ + @type codegen__sequence_type() :: integer() + + @typedoc """ + ```edgeql + scalar type codegen::JsonType extending std::json + ``` + """ + @type codegen__json_type() :: any() + + @typedoc """ + ```edgeql + scalar type codegen::Int64Type extending std::int64 + ``` + """ + @type codegen__int64_type() :: integer() + + @typedoc """ + ```edgeql + scalar type codegen::Int32Type extending std::int32 + ``` + """ + @type codegen__int32_type() :: integer() + + @typedoc """ + ```edgeql + scalar type codegen::Int16Type extending std::int16 + ``` + """ + @type codegen__int16_type() :: integer() + + @typedoc """ + ```edgeql + scalar type codegen::Float64Type extending std::float64 + ``` + """ + @type codegen__float64_type() :: float() + + @typedoc """ + ```edgeql + scalar type codegen::Float32Type extending std::float32 + ``` + """ + @type codegen__float32_type() :: float() + + @typedoc """ + ```edgeql + scalar type codegen::EnumType extending enum + ``` + """ + @type codegen__enum_type() :: String.t() | :A | :B | :C + + @typedoc """ + ```edgeql + scalar type codegen::DurationType extending std::duration + ``` + """ + @type codegen__duration_type() :: integer() + + @typedoc """ + ```edgeql + scalar type codegen::DecimalType extending std::decimal + ``` + """ + @type codegen__decimal_type() :: Decimal.t() + + @typedoc """ + ```edgeql + scalar type codegen::DatetimeType extending std::datetime + ``` + """ + @type codegen__datetime_type() :: DateTime.t() + + @typedoc """ + ```edgeql + scalar type codegen::CfgMemoryType extending cfg::memory + ``` + """ + @type codegen__cfg_memory_type() :: EdgeDB.ConfigMemory.t() + + @typedoc """ + ```edgeql + scalar type codegen::CalRelativeDurationType extending cal::relative_duration + ``` + """ + @type codegen__cal_relative_duration_type() :: EdgeDB.RelativeDuration.t() + + @typedoc """ + ```edgeql + scalar type codegen::CalLocalTimeType extending cal::local_time + ``` + """ + @type codegen__cal_local_time_type() :: Time.t() + + @typedoc """ + ```edgeql + scalar type codegen::CalLocalDatetimeType extending cal::local_datetime + ``` + """ + @type codegen__cal_local_datetime_type() :: NaiveDateTime.t() + + @typedoc """ + ```edgeql + scalar type codegen::CalLocalDateType extending cal::local_date + ``` + """ + @type codegen__cal_local_date_type() :: Date.t() + + @typedoc """ + ```edgeql + scalar type codegen::CalDateDurationType extending cal::date_duration + ``` + """ + @type codegen__cal_date_duration_type() :: EdgeDB.DateDuration.t() + + @typedoc """ + ```edgeql + scalar type codegen::BytesType extending std::bytes + ``` + """ + @type codegen__bytes_type() :: bitstring() + + @typedoc """ + ```edgeql + scalar type codegen::BoolType extending std::bool + ``` + """ + @type codegen__bool_type() :: boolean() + + @type result() :: [ + %{ + id: uuid(), + rp_str: String.t(), + op_str: String.t() | nil, + mp_str: [String.t()], + rp_str_type: codegen__str_type(), + op_str_type: codegen__str_type() | nil, + mp_str_type: [codegen__str_type()], + rp_bool: boolean(), + op_bool: boolean() | nil, + mp_bool: [boolean()], + rp_bool_type: codegen__bool_type(), + op_bool_type: codegen__bool_type() | nil, + mp_bool_type: [codegen__bool_type()], + rp_int16: integer(), + op_int16: integer() | nil, + mp_int16: [integer()], + rp_int16_type: codegen__int16_type(), + op_int16_type: codegen__int16_type() | nil, + mp_int16_type: [codegen__int16_type()], + rp_int32: integer(), + op_int32: integer() | nil, + mp_int32: [integer()], + rp_int32_type: codegen__int32_type(), + op_int32_type: codegen__int32_type() | nil, + mp_int32_type: [codegen__int32_type()], + rp_int64: integer(), + op_int64: integer() | nil, + mp_int64: [integer()], + rp_int64_type: codegen__int64_type(), + op_int64_type: codegen__int64_type() | nil, + mp_int64_type: [codegen__int64_type()], + rp_float32: float(), + op_float32: float() | nil, + mp_float32: [float()], + rp_float32_type: codegen__float32_type(), + op_float32_type: codegen__float32_type() | nil, + mp_float32_type: [codegen__float32_type()], + rp_float64: float(), + op_float64: float() | nil, + mp_float64: [float()], + rp_float64_type: codegen__float64_type(), + op_float64_type: codegen__float64_type() | nil, + mp_float64_type: [codegen__float64_type()], + rp_decimal: Decimal.t(), + op_decimal: Decimal.t() | nil, + mp_decimal: [Decimal.t()], + rp_decimal_type: codegen__decimal_type(), + op_decimal_type: codegen__decimal_type() | nil, + mp_decimal_type: [codegen__decimal_type()], + rp_json: json(), + op_json: json() | nil, + mp_json: [json()], + rp_json_type: codegen__json_type(), + op_json_type: codegen__json_type() | nil, + mp_json_type: [codegen__json_type()], + rp_uuid: uuid(), + op_uuid: uuid() | nil, + mp_uuid: [uuid()], + rp_uuid_type: codegen__uuid_type(), + op_uuid_type: codegen__uuid_type() | nil, + mp_uuid_type: [codegen__uuid_type()], + rp_enum: codegen__enum_type(), + op_enum: codegen__enum_type() | nil, + mp_enum: [codegen__enum_type()], + rp_datetime: DateTime.t(), + op_datetime: DateTime.t() | nil, + mp_datetime: [DateTime.t()], + rp_datetime_type: codegen__datetime_type(), + op_datetime_type: codegen__datetime_type() | nil, + mp_datetime_type: [codegen__datetime_type()], + rp_duration: duration(), + op_duration: duration() | nil, + mp_duration: [duration()], + rp_duration_type: codegen__duration_type(), + op_duration_type: codegen__duration_type() | nil, + mp_duration_type: [codegen__duration_type()], + rp_cal_local_datetime: NaiveDateTime.t(), + op_cal_local_datetime: NaiveDateTime.t() | nil, + mp_cal_local_datetime: [NaiveDateTime.t()], + rp_cal_local_datetime_type: codegen__cal_local_datetime_type(), + op_cal_local_datetime_type: codegen__cal_local_datetime_type() | nil, + mp_cal_local_datetime_type: [codegen__cal_local_datetime_type()], + rp_cal_local_date: Date.t(), + op_cal_local_date: Date.t() | nil, + mp_cal_local_date: [Date.t()], + rp_cal_local_date_type: codegen__cal_local_date_type(), + op_cal_local_date_type: codegen__cal_local_date_type() | nil, + mp_cal_local_date_type: [codegen__cal_local_date_type()], + rp_cal_local_time: Time.t(), + op_cal_local_time: Time.t() | nil, + mp_cal_local_time: [Time.t()], + rp_cal_local_time_type: codegen__cal_local_time_type(), + op_cal_local_time_type: codegen__cal_local_time_type() | nil, + mp_cal_local_time_type: [codegen__cal_local_time_type()], + rp_cal_relative_duration: EdgeDB.RelativeDuration.t(), + op_cal_relative_duration: EdgeDB.RelativeDuration.t() | nil, + mp_cal_relative_duration: [EdgeDB.RelativeDuration.t()], + rp_cal_relative_duration_type: codegen__cal_relative_duration_type(), + op_cal_relative_duration_type: codegen__cal_relative_duration_type() | nil, + mp_cal_relative_duration_type: [codegen__cal_relative_duration_type()], + rp_cal_date_duration: EdgeDB.DateDuration.t(), + op_cal_date_duration: EdgeDB.DateDuration.t() | nil, + mp_cal_date_duration: [EdgeDB.DateDuration.t()], + rp_cal_date_duration_type: codegen__cal_date_duration_type(), + op_cal_date_duration_type: codegen__cal_date_duration_type() | nil, + mp_cal_date_duration_type: [codegen__cal_date_duration_type()], + rp_array_int64: [integer()], + op_array_int64: [integer()] | nil, + mp_array_int64: [[integer()]], + rp_tuple_int64_int64: {integer(), integer()}, + op_tuple_int64_int64: {integer(), integer()} | nil, + mp_tuple_int64_int64: [{integer(), integer()}], + rp_named_tuple_x_int64_y_int64: %{ + :x => integer(), + 0 => integer(), + :y => integer(), + 1 => integer() + }, + op_named_tuple_x_int64_y_int64: + %{:x => integer(), 0 => integer(), :y => integer(), 1 => integer()} | nil, + mp_named_tuple_x_int64_y_int64: [ + %{:x => integer(), 0 => integer(), :y => integer(), 1 => integer()} + ], + rp_range_int32: EdgeDB.Range.t(integer()), + op_range_int32: EdgeDB.Range.t(integer()) | nil, + mp_range_int32: [EdgeDB.Range.t(integer())], + rp_range_int64: EdgeDB.Range.t(integer()), + op_range_int64: EdgeDB.Range.t(integer()) | nil, + mp_range_int64: [EdgeDB.Range.t(integer())], + rp_range_float32: EdgeDB.Range.t(float()), + op_range_float32: EdgeDB.Range.t(float()) | nil, + mp_range_float32: [EdgeDB.Range.t(float())], + rp_range_float64: EdgeDB.Range.t(float()), + op_range_float64: EdgeDB.Range.t(float()) | nil, + mp_range_float64: [EdgeDB.Range.t(float())], + rp_range_decimal: EdgeDB.Range.t(Decimal.t()), + op_range_decimal: EdgeDB.Range.t(Decimal.t()) | nil, + mp_range_decimal: [EdgeDB.Range.t(Decimal.t())], + rp_range_datetime: EdgeDB.Range.t(DateTime.t()), + op_range_datetime: EdgeDB.Range.t(DateTime.t()) | nil, + mp_range_datetime: [EdgeDB.Range.t(DateTime.t())], + rp_range_cal_local_datetime: EdgeDB.Range.t(NaiveDateTime.t()), + op_range_cal_local_datetime: EdgeDB.Range.t(NaiveDateTime.t()) | nil, + mp_range_cal_local_datetime: [EdgeDB.Range.t(NaiveDateTime.t())], + rp_range_cal_local_date: EdgeDB.Range.t(Date.t()), + op_range_cal_local_date: EdgeDB.Range.t(Date.t()) | nil, + mp_range_cal_local_date: [EdgeDB.Range.t(Date.t())], + rp_bytes: bitstring(), + op_bytes: bitstring() | nil, + mp_bytes: [bitstring()], + rp_bytes_type: codegen__bytes_type(), + op_bytes_type: codegen__bytes_type() | nil, + mp_bytes_type: [codegen__bytes_type()], + rp_sequence: codegen__sequence_type(), + op_sequence: codegen__sequence_type() | nil, + mp_sequence: [codegen__sequence_type()], + rp_cfg_memory: EdgeDB.ConfigMemory.t(), + op_cfg_memory: EdgeDB.ConfigMemory.t() | nil, + mp_cfg_memory: [EdgeDB.ConfigMemory.t()], + rp_cfg_memory_type: codegen__cfg_memory_type(), + op_cfg_memory_type: codegen__cfg_memory_type() | nil, + mp_cfg_memory_type: [codegen__cfg_memory_type()], + rl_f: %{ + id: uuid(), + rp_a_str: String.t(), + rp_b_str: String.t(), + rp_c_str: String.t(), + rp_d_str: String.t(), + rp_f_str: String.t(), + ol_a: %{id: uuid(), rp_a_str: String.t(), rp_e_str: String.t()} | nil, + ml_a: [%{id: uuid(), rp_a_str: String.t(), rp_e_str: String.t()}], + ol_a_b: %{id: uuid()} | nil, + ml_a_b: [%{id: uuid()}] + }, + ol_f: + %{ + id: uuid(), + rp_a_str: String.t(), + rp_b_str: String.t(), + rp_c_str: String.t(), + rp_d_str: String.t(), + rp_f_str: String.t(), + ol_a: %{id: uuid(), rp_a_str: String.t(), rp_e_str: String.t()} | nil, + ml_a: [%{id: uuid(), rp_a_str: String.t(), rp_e_str: String.t()}], + ol_a_b: %{id: uuid()} | nil, + ml_a_b: [%{id: uuid()}] + } + | nil, + ml_f: [ + %{ + id: uuid(), + rp_a_str: String.t(), + rp_b_str: String.t(), + rp_c_str: String.t(), + rp_d_str: String.t(), + rp_f_str: String.t(), + ol_a: %{id: uuid(), rp_a_str: String.t(), rp_e_str: String.t()} | nil, + ml_a: [%{id: uuid(), rp_a_str: String.t(), rp_e_str: String.t()}], + ol_a_b: %{id: uuid()} | nil, + ml_a_b: [%{id: uuid()}] + } + ], + rl_lp_f: %{id: uuid(), "@olp_a": integer() | nil} + } + ] + + @type keyword_args() :: [{:ids, [uuid()]}] + + @type map_args() :: %{ + ids: [uuid()] + } + + @type args() :: map_args() | keyword_args() + + @doc """ + Run the query. + """ + @spec query( + client :: EdgeDB.client(), + args :: args(), + opts :: list(EdgeDB.query_option()) + ) :: + {:ok, result()} + | {:error, reason} + when reason: any() + def query(client, args, opts \\ []) do + do_query(client, args, opts) + end + + @doc """ + Run the query. + """ + @spec query!( + client :: EdgeDB.client(), + args :: args(), + opts :: list(EdgeDB.query_option()) + ) :: result() + def query!(client, args, opts \\ []) do + case do_query(client, args, opts) do + {:ok, result} -> + result + + {:error, exc} -> + raise exc + end + end + + @schema [ + :rp_uuid_type, + :rp_uuid, + :rp_tuple_int64_int64, + :rp_str_type, + :rp_str, + :rp_sequence, + :rp_range_int64, + :rp_range_int32, + :rp_range_float64, + :rp_range_float32, + :rp_range_decimal, + :rp_range_datetime, + :rp_range_cal_local_datetime, + :rp_range_cal_local_date, + :rp_json_type, + :rp_json, + :rp_int64_type, + :rp_int64, + :rp_int32_type, + :rp_int32, + :rp_int16_type, + :rp_int16, + :rp_float64_type, + :rp_float64, + :rp_float32_type, + :rp_float32, + :rp_enum, + :rp_duration_type, + :rp_duration, + :rp_decimal_type, + :rp_decimal, + :rp_datetime_type, + :rp_datetime, + :rp_cfg_memory_type, + :rp_cfg_memory, + :rp_cal_relative_duration_type, + :rp_cal_relative_duration, + :rp_cal_local_time_type, + :rp_cal_local_time, + :rp_cal_local_datetime_type, + :rp_cal_local_datetime, + :rp_cal_local_date_type, + :rp_cal_local_date, + :rp_cal_date_duration_type, + :rp_cal_date_duration, + :rp_bytes_type, + :rp_bytes, + :rp_bool_type, + :rp_bool, + :rp_array_int64, + :op_uuid_type, + :op_uuid, + :op_tuple_int64_int64, + :op_str_type, + :op_str, + :op_sequence, + :op_range_int64, + :op_range_int32, + :op_range_float64, + :op_range_float32, + :op_range_decimal, + :op_range_datetime, + :op_range_cal_local_datetime, + :op_range_cal_local_date, + :op_json_type, + :op_json, + :op_int64_type, + :op_int64, + :op_int32_type, + :op_int32, + :op_int16_type, + :op_int16, + :op_float64_type, + :op_float64, + :op_float32_type, + :op_float32, + :op_enum, + :op_duration_type, + :op_duration, + :op_decimal_type, + :op_decimal, + :op_datetime_type, + :op_datetime, + :op_cfg_memory_type, + :op_cfg_memory, + :op_cal_relative_duration_type, + :op_cal_relative_duration, + :op_cal_local_time_type, + :op_cal_local_time, + :op_cal_local_datetime_type, + :op_cal_local_datetime, + :op_cal_local_date_type, + :op_cal_local_date, + :op_cal_date_duration_type, + :op_cal_date_duration, + :op_bytes_type, + :op_bytes, + :op_bool_type, + :op_bool, + :op_array_int64, + :mp_uuid_type, + :mp_uuid, + :mp_tuple_int64_int64, + :mp_str_type, + :mp_str, + :mp_sequence, + :mp_range_int64, + :mp_range_int32, + :mp_range_float64, + :mp_range_float32, + :mp_range_decimal, + :mp_range_datetime, + :mp_range_cal_local_datetime, + :mp_range_cal_local_date, + :mp_json_type, + :mp_json, + :mp_int64_type, + :mp_int64, + :mp_int32_type, + :mp_int32, + :mp_int16_type, + :mp_int16, + :mp_float64_type, + :mp_float64, + :mp_float32_type, + :mp_float32, + :mp_enum, + :mp_duration_type, + :mp_duration, + :mp_decimal_type, + :mp_decimal, + :mp_datetime_type, + :mp_datetime, + :mp_cfg_memory_type, + :mp_cfg_memory, + :mp_cal_relative_duration_type, + :mp_cal_relative_duration, + :mp_cal_local_time_type, + :mp_cal_local_time, + :mp_cal_local_datetime_type, + :mp_cal_local_datetime, + :mp_cal_local_date_type, + :mp_cal_local_date, + :mp_cal_date_duration_type, + :mp_cal_date_duration, + :mp_bytes_type, + :mp_bytes, + :mp_bool_type, + :mp_bool, + :mp_array_int64, + :id, + rp_named_tuple_x_int64_y_int64: [:y, :x], + rl_lp_f: [:olp_a, :id], + rl_f: [ + :rp_f_str, + :rp_d_str, + :rp_c_str, + :rp_b_str, + :rp_a_str, + :id, + ol_a_b: [:id], + ol_a: [:rp_e_str, :rp_a_str, :id], + ml_a_b: [:id], + ml_a: [:rp_e_str, :rp_a_str, :id] + ], + op_named_tuple_x_int64_y_int64: [:y, :x], + ol_f: [ + :rp_f_str, + :rp_d_str, + :rp_c_str, + :rp_b_str, + :rp_a_str, + :id, + ol_a_b: [:id], + ol_a: [:rp_e_str, :rp_a_str, :id], + ml_a_b: [:id], + ml_a: [:rp_e_str, :rp_a_str, :id] + ], + mp_named_tuple_x_int64_y_int64: [:y, :x], + ml_f: [ + :rp_f_str, + :rp_d_str, + :rp_c_str, + :rp_b_str, + :rp_a_str, + :id, + ol_a_b: [:id], + ol_a: [:rp_e_str, :rp_a_str, :id], + ml_a_b: [:id], + ml_a: [:rp_e_str, :rp_a_str, :id] + ] + ] + defp do_query(client, args, opts) do + opts = Keyword.merge(opts, __file__: @query_file, __transform_result__: [schema: @schema]) + EdgeDB.query(client, @query, args, opts) + end +end diff --git a/test/support/schema/codegen.esdl b/test/support/schema/codegen.esdl new file mode 100644 index 00000000..751e9915 --- /dev/null +++ b/test/support/schema/codegen.esdl @@ -0,0 +1,333 @@ +using extension pgvector; + +module codegen { + # enum + + scalar type EnumType extending enum; + + # sequence + + scalar type SequenceType extending sequence; + + # custom scalars + + scalar type StrType extending str; + scalar type BoolType extending bool; + scalar type Int16Type extending int16; + scalar type Int32Type extending int32; + scalar type Int64Type extending int64; + scalar type Float32Type extending float32; + scalar type Float64Type extending float64; + scalar type DecimalType extending decimal; + scalar type JsonType extending json; + scalar type UuidType extending uuid; + scalar type DatetimeType extending datetime; + scalar type DurationType extending duration; + scalar type CalLocalDatetimeType extending cal::local_datetime; + scalar type CalLocalDateType extending cal::local_date; + scalar type CalLocalTimeType extending cal::local_time; + scalar type CalRelativeDurationType extending cal::relative_duration; + scalar type CalDateDurationType extending cal::date_duration; + scalar type BytesType extending bytes; + scalar type CfgMemoryType extending cfg::memory; + scalar type VectorType extending ext::pgvector::vector<1>; + + # types + + abstract type A { + # properties + + required rp_a_str: str; + + # links + + ol_a: A; + multi ml_a: A; + } + + abstract type B { + required rp_b_str: str; + } + + abstract type C extending B { + required rp_c_str: str; + } + + abstract type D extending A, C { + required rp_d_str: str; + } + + type E extending A { + required rp_e_str: str; + }; + + type F extending D { + # properties + + overloaded rp_a_str: str; + + required rp_f_str: str; + + # links + + overloaded ol_a: E; + overloaded multi ml_a: E; + + ol_a_b: A | B; + multi ml_a_b: A | B; + } + + # result + + type Result { + # properties + + # string + + required rp_str: str; + op_str: str; + multi mp_str: str; + + required rp_str_type: StrType; + op_str_type: StrType; + multi mp_str_type: StrType; + + # boolean + + required rp_bool: bool; + op_bool: bool; + multi mp_bool: bool; + + required rp_bool_type: BoolType; + op_bool_type: BoolType; + multi mp_bool_type: BoolType; + + # number + + required rp_int16: int16; + op_int16: int16; + multi mp_int16: int16; + + required rp_int16_type: Int16Type; + op_int16_type: Int16Type; + multi mp_int16_type: Int16Type; + + required rp_int32: int32; + op_int32: int32; + multi mp_int32: int32; + + required rp_int32_type: Int32Type; + op_int32_type: Int32Type; + multi mp_int32_type: Int32Type; + + required rp_int64: int64; + op_int64: int64; + multi mp_int64: int64; + + required rp_int64_type: Int64Type; + op_int64_type: Int64Type; + multi mp_int64_type: Int64Type; + + required rp_float32: float32; + op_float32: float32; + multi mp_float32: float32; + + required rp_float32_type: Float32Type; + op_float32_type: Float32Type; + multi mp_float32_type: Float32Type; + + required rp_float64: float64; + op_float64: float64; + multi mp_float64: float64; + + required rp_float64_type: Float64Type; + op_float64_type: Float64Type; + multi mp_float64_type: Float64Type; + + required rp_decimal: decimal; + op_decimal: decimal; + multi mp_decimal: decimal; + + required rp_decimal_type: DecimalType; + op_decimal_type: DecimalType; + multi mp_decimal_type: DecimalType; + + # json + + required rp_json: json; + op_json: json; + multi mp_json: json; + + required rp_json_type: JsonType; + op_json_type: JsonType; + multi mp_json_type: JsonType; + + # uuid + + required rp_uuid: uuid; + op_uuid: uuid; + multi mp_uuid: uuid; + + required rp_uuid_type: UuidType; + op_uuid_type: UuidType; + multi mp_uuid_type: UuidType; + + # enum + + required rp_enum: EnumType; + op_enum: EnumType; + multi mp_enum: EnumType; + + # date/time + + required rp_datetime: datetime; + op_datetime: datetime; + multi mp_datetime: datetime; + + required rp_datetime_type: DatetimeType; + op_datetime_type: DatetimeType; + multi mp_datetime_type: DatetimeType; + + required rp_duration: duration; + op_duration: duration; + multi mp_duration: duration; + + required rp_duration_type: DurationType; + op_duration_type: DurationType; + multi mp_duration_type: DurationType; + + required rp_cal_local_datetime: cal::local_datetime; + op_cal_local_datetime: cal::local_datetime; + multi mp_cal_local_datetime: cal::local_datetime; + + required rp_cal_local_datetime_type: CalLocalDatetimeType; + op_cal_local_datetime_type: CalLocalDatetimeType; + multi mp_cal_local_datetime_type: CalLocalDatetimeType; + + required rp_cal_local_date: cal::local_date; + op_cal_local_date: cal::local_date; + multi mp_cal_local_date: cal::local_date; + + required rp_cal_local_date_type: CalLocalDateType; + op_cal_local_date_type: CalLocalDateType; + multi mp_cal_local_date_type: CalLocalDateType; + + required rp_cal_local_time: cal::local_time; + op_cal_local_time: cal::local_time; + multi mp_cal_local_time: cal::local_time; + + required rp_cal_local_time_type: CalLocalTimeType; + op_cal_local_time_type: CalLocalTimeType; + multi mp_cal_local_time_type: CalLocalTimeType; + + required rp_cal_relative_duration: cal::relative_duration; + op_cal_relative_duration: cal::relative_duration; + multi mp_cal_relative_duration: cal::relative_duration; + + required rp_cal_relative_duration_type: CalRelativeDurationType; + op_cal_relative_duration_type: CalRelativeDurationType; + multi mp_cal_relative_duration_type: CalRelativeDurationType; + + required rp_cal_date_duration: cal::date_duration; + op_cal_date_duration: cal::date_duration; + multi mp_cal_date_duration: cal::date_duration; + + required rp_cal_date_duration_type: CalDateDurationType; + op_cal_date_duration_type: CalDateDurationType; + multi mp_cal_date_duration_type: CalDateDurationType; + + # array + + required rp_array_int64: array; + op_array_int64: array; + multi mp_array_int64: array; + + # tuple + + required rp_tuple_int64_int64: tuple; + op_tuple_int64_int64: tuple; + multi mp_tuple_int64_int64: tuple; + + required rp_named_tuple_x_int64_y_int64: tuple; + op_named_tuple_x_int64_y_int64: tuple; + multi mp_named_tuple_x_int64_y_int64: tuple; + + # range + + required rp_range_int32: range; + op_range_int32: range; + multi mp_range_int32: range; + + required rp_range_int64: range; + op_range_int64: range; + multi mp_range_int64: range; + + required rp_range_float32: range; + op_range_float32: range; + multi mp_range_float32: range; + + required rp_range_float64: range; + op_range_float64: range; + multi mp_range_float64: range; + + required rp_range_decimal: range; + op_range_decimal: range; + multi mp_range_decimal: range; + + required rp_range_datetime: range; + op_range_datetime: range; + multi mp_range_datetime: range; + + required rp_range_cal_local_datetime: range; + op_range_cal_local_datetime: range; + multi mp_range_cal_local_datetime: range; + + required rp_range_cal_local_date: range; + op_range_cal_local_date: range; + multi mp_range_cal_local_date: range; + + # bytes + + required rp_bytes: bytes; + op_bytes: bytes; + multi mp_bytes: bytes; + + required rp_bytes_type: BytesType; + op_bytes_type: BytesType; + multi mp_bytes_type: BytesType; + + # sequence + + required rp_sequence: SequenceType; + op_sequence: SequenceType; + multi mp_sequence: SequenceType; + + # config + + required rp_cfg_memory: cfg::memory; + op_cfg_memory: cfg::memory; + multi mp_cfg_memory: cfg::memory; + + required rp_cfg_memory_type: CfgMemoryType; + op_cfg_memory_type: CfgMemoryType; + multi mp_cfg_memory_type: CfgMemoryType; + + # vector + + required rp_vector_type: VectorType; + op_vector_type: VectorType; + multi mp_vector_type: VectorType; + + # links + + required rl_f: F; + ol_f: F; + multi ml_f: F; + + # link properties + + required rl_lp_f: F { + olp_a: int64; + } + } +}; diff --git a/priv/edgedb/schema/default.esdl b/test/support/schema/default.esdl similarity index 70% rename from priv/edgedb/schema/default.esdl rename to test/support/schema/default.esdl index f150dbc8..ed85f6a0 100644 --- a/priv/edgedb/schema/default.esdl +++ b/test/support/schema/default.esdl @@ -1,44 +1,46 @@ using extension pgvector; module default { - global current_user -> str; + global current_user: str; abstract type HasImage { # just a URL to the image - required property image -> str; + required image: str; index on (.image); } type User extending HasImage { - required property name -> str; + required name: str; } type Review { - required property body -> str; - required property rating -> int64 { + required body: str; + required rating: int64 { constraint min_value(0); constraint max_value(5); } - required property flag -> bool { + required flag: bool { default := false; } - required link author -> User; - required link movie -> Movie; + required author: User; + required movie: Movie; - required property creation_time -> datetime { + required creation_time: datetime { default := datetime_current(); } } type Person extending HasImage { - required property first_name -> str { + required first_name: str { default := ''; } - required property middle_name -> str { + required middle_name: str { default := ''; } - required property last_name -> str; + + required last_name: str; + property full_name := ( ( @@ -53,14 +55,14 @@ module default { ) ++ .last_name ); - property bio -> str; + bio: str; } abstract link crew { # Provide a way to specify some "natural" # ordering, as relevant to the movie. This # may be order of importance, appearance, etc. - property list_order -> int64; + list_order: int64; } abstract link directors extending crew; @@ -68,8 +70,8 @@ module default { abstract link actors extending crew; type Movie extending HasImage { - required property title -> str; - required property year -> int64; + required title: str; + required year: int64; # Add an index for accessing movies by title and year, # separately and in combination. @@ -77,10 +79,10 @@ module default { index on (.year); index on ((.title, .year)); - property description -> str; + description: str; - multi link directors extending crew -> Person; - multi link actors extending crew -> Person; + multi directors extending crew: Person; + multi actors extending crew: Person; property avg_rating := math::mean(. TicketNo { + number: TicketNo { constraint exclusive; } } @@ -105,7 +107,7 @@ module default { }; alias MovieAlias := Movie { - # A computable link for accessing all the + # A computable for accessing all the # reviews for this movie. reviews := .{}); + }; + ALTER LINK ol_a { + SET OWNED; + SET TYPE codegen::E USING ({}); + }; + ALTER PROPERTY rp_a_str { + SET OWNED; + SET TYPE std::str; + }; + CREATE REQUIRED PROPERTY rp_f_str: std::str; + }; + CREATE SCALAR TYPE codegen::BoolType EXTENDING std::bool; + CREATE SCALAR TYPE codegen::BytesType EXTENDING std::bytes; + CREATE SCALAR TYPE codegen::CalDateDurationType EXTENDING cal::date_duration; + CREATE SCALAR TYPE codegen::CalLocalDateType EXTENDING cal::local_date; + CREATE SCALAR TYPE codegen::CalLocalDatetimeType EXTENDING cal::local_datetime; + CREATE SCALAR TYPE codegen::CalLocalTimeType EXTENDING cal::local_time; + CREATE SCALAR TYPE codegen::CalRelativeDurationType EXTENDING cal::relative_duration; + CREATE SCALAR TYPE codegen::CfgMemoryType EXTENDING cfg::memory; + CREATE SCALAR TYPE codegen::DatetimeType EXTENDING std::datetime; + CREATE SCALAR TYPE codegen::DecimalType EXTENDING std::decimal; + CREATE SCALAR TYPE codegen::DurationType EXTENDING std::duration; + CREATE SCALAR TYPE codegen::EnumType EXTENDING enum; + CREATE SCALAR TYPE codegen::Float32Type EXTENDING std::float32; + CREATE SCALAR TYPE codegen::Float64Type EXTENDING std::float64; + CREATE SCALAR TYPE codegen::Int16Type EXTENDING std::int16; + CREATE SCALAR TYPE codegen::Int32Type EXTENDING std::int32; + CREATE SCALAR TYPE codegen::Int64Type EXTENDING std::int64; + CREATE SCALAR TYPE codegen::JsonType EXTENDING std::json; + CREATE SCALAR TYPE codegen::SequenceType EXTENDING std::sequence; + CREATE SCALAR TYPE codegen::StrType EXTENDING std::str; + CREATE SCALAR TYPE codegen::UuidType EXTENDING std::uuid; + CREATE SCALAR TYPE codegen::VectorType EXTENDING ext::pgvector::vector<1>; + CREATE TYPE codegen::Result { + CREATE MULTI PROPERTY mp_array_int64: array; + CREATE PROPERTY op_array_int64: array; + CREATE REQUIRED PROPERTY rp_array_int64: array; + CREATE MULTI LINK ml_f: codegen::F; + CREATE LINK ol_f: codegen::F; + CREATE REQUIRED LINK rl_f: codegen::F; + CREATE REQUIRED LINK rl_lp_f: codegen::F { + CREATE PROPERTY olp_a: std::int64; + }; + CREATE MULTI PROPERTY mp_bool: std::bool; + CREATE MULTI PROPERTY mp_bool_type: codegen::BoolType; + CREATE MULTI PROPERTY mp_bytes: std::bytes; + CREATE MULTI PROPERTY mp_bytes_type: codegen::BytesType; + CREATE MULTI PROPERTY mp_cal_date_duration: cal::date_duration; + CREATE MULTI PROPERTY mp_cal_date_duration_type: codegen::CalDateDurationType; + CREATE MULTI PROPERTY mp_cal_local_date: cal::local_date; + CREATE MULTI PROPERTY mp_cal_local_date_type: codegen::CalLocalDateType; + CREATE MULTI PROPERTY mp_cal_local_datetime: cal::local_datetime; + CREATE MULTI PROPERTY mp_cal_local_datetime_type: codegen::CalLocalDatetimeType; + CREATE MULTI PROPERTY mp_cal_local_time: cal::local_time; + CREATE MULTI PROPERTY mp_cal_local_time_type: codegen::CalLocalTimeType; + CREATE MULTI PROPERTY mp_cal_relative_duration: cal::relative_duration; + CREATE MULTI PROPERTY mp_cal_relative_duration_type: codegen::CalRelativeDurationType; + CREATE MULTI PROPERTY mp_cfg_memory: cfg::memory; + CREATE MULTI PROPERTY mp_cfg_memory_type: codegen::CfgMemoryType; + CREATE MULTI PROPERTY mp_datetime: std::datetime; + CREATE MULTI PROPERTY mp_datetime_type: codegen::DatetimeType; + CREATE MULTI PROPERTY mp_decimal: std::decimal; + CREATE MULTI PROPERTY mp_decimal_type: codegen::DecimalType; + CREATE MULTI PROPERTY mp_duration: std::duration; + CREATE MULTI PROPERTY mp_duration_type: codegen::DurationType; + CREATE MULTI PROPERTY mp_enum: codegen::EnumType; + CREATE MULTI PROPERTY mp_float32: std::float32; + CREATE MULTI PROPERTY mp_float32_type: codegen::Float32Type; + CREATE MULTI PROPERTY mp_float64: std::float64; + CREATE MULTI PROPERTY mp_float64_type: codegen::Float64Type; + CREATE MULTI PROPERTY mp_int16: std::int16; + CREATE MULTI PROPERTY mp_int16_type: codegen::Int16Type; + CREATE MULTI PROPERTY mp_int32: std::int32; + CREATE MULTI PROPERTY mp_int32_type: codegen::Int32Type; + CREATE MULTI PROPERTY mp_int64: std::int64; + CREATE MULTI PROPERTY mp_int64_type: codegen::Int64Type; + CREATE MULTI PROPERTY mp_json: std::json; + CREATE MULTI PROPERTY mp_json_type: codegen::JsonType; + CREATE MULTI PROPERTY mp_named_tuple_x_int64_y_int64: tuple; + CREATE MULTI PROPERTY mp_range_cal_local_date: range; + CREATE MULTI PROPERTY mp_range_cal_local_datetime: range; + CREATE MULTI PROPERTY mp_range_datetime: range; + CREATE MULTI PROPERTY mp_range_decimal: range; + CREATE MULTI PROPERTY mp_range_float32: range; + CREATE MULTI PROPERTY mp_range_float64: range; + CREATE MULTI PROPERTY mp_range_int32: range; + CREATE MULTI PROPERTY mp_range_int64: range; + CREATE MULTI PROPERTY mp_sequence: codegen::SequenceType; + CREATE MULTI PROPERTY mp_str: std::str; + CREATE MULTI PROPERTY mp_str_type: codegen::StrType; + CREATE MULTI PROPERTY mp_tuple_int64_int64: tuple; + CREATE MULTI PROPERTY mp_uuid: std::uuid; + CREATE MULTI PROPERTY mp_uuid_type: codegen::UuidType; + CREATE MULTI PROPERTY mp_vector_type: codegen::VectorType; + CREATE PROPERTY op_bool: std::bool; + CREATE PROPERTY op_bool_type: codegen::BoolType; + CREATE PROPERTY op_bytes: std::bytes; + CREATE PROPERTY op_bytes_type: codegen::BytesType; + CREATE PROPERTY op_cal_date_duration: cal::date_duration; + CREATE PROPERTY op_cal_date_duration_type: codegen::CalDateDurationType; + CREATE PROPERTY op_cal_local_date: cal::local_date; + CREATE PROPERTY op_cal_local_date_type: codegen::CalLocalDateType; + CREATE PROPERTY op_cal_local_datetime: cal::local_datetime; + CREATE PROPERTY op_cal_local_datetime_type: codegen::CalLocalDatetimeType; + CREATE PROPERTY op_cal_local_time: cal::local_time; + CREATE PROPERTY op_cal_local_time_type: codegen::CalLocalTimeType; + CREATE PROPERTY op_cal_relative_duration: cal::relative_duration; + CREATE PROPERTY op_cal_relative_duration_type: codegen::CalRelativeDurationType; + CREATE PROPERTY op_cfg_memory: cfg::memory; + CREATE PROPERTY op_cfg_memory_type: codegen::CfgMemoryType; + CREATE PROPERTY op_datetime: std::datetime; + CREATE PROPERTY op_datetime_type: codegen::DatetimeType; + CREATE PROPERTY op_decimal: std::decimal; + CREATE PROPERTY op_decimal_type: codegen::DecimalType; + CREATE PROPERTY op_duration: std::duration; + CREATE PROPERTY op_duration_type: codegen::DurationType; + CREATE PROPERTY op_enum: codegen::EnumType; + CREATE PROPERTY op_float32: std::float32; + CREATE PROPERTY op_float32_type: codegen::Float32Type; + CREATE PROPERTY op_float64: std::float64; + CREATE PROPERTY op_float64_type: codegen::Float64Type; + CREATE PROPERTY op_int16: std::int16; + CREATE PROPERTY op_int16_type: codegen::Int16Type; + CREATE PROPERTY op_int32: std::int32; + CREATE PROPERTY op_int32_type: codegen::Int32Type; + CREATE PROPERTY op_int64: std::int64; + CREATE PROPERTY op_int64_type: codegen::Int64Type; + CREATE PROPERTY op_json: std::json; + CREATE PROPERTY op_json_type: codegen::JsonType; + CREATE PROPERTY op_named_tuple_x_int64_y_int64: tuple; + CREATE PROPERTY op_range_cal_local_date: range; + CREATE PROPERTY op_range_cal_local_datetime: range; + CREATE PROPERTY op_range_datetime: range; + CREATE PROPERTY op_range_decimal: range; + CREATE PROPERTY op_range_float32: range; + CREATE PROPERTY op_range_float64: range; + CREATE PROPERTY op_range_int32: range; + CREATE PROPERTY op_range_int64: range; + CREATE PROPERTY op_sequence: codegen::SequenceType; + CREATE PROPERTY op_str: std::str; + CREATE PROPERTY op_str_type: codegen::StrType; + CREATE PROPERTY op_tuple_int64_int64: tuple; + CREATE PROPERTY op_uuid: std::uuid; + CREATE PROPERTY op_uuid_type: codegen::UuidType; + CREATE PROPERTY op_vector_type: codegen::VectorType; + CREATE REQUIRED PROPERTY rp_bool: std::bool; + CREATE REQUIRED PROPERTY rp_bool_type: codegen::BoolType; + CREATE REQUIRED PROPERTY rp_bytes: std::bytes; + CREATE REQUIRED PROPERTY rp_bytes_type: codegen::BytesType; + CREATE REQUIRED PROPERTY rp_cal_date_duration: cal::date_duration; + CREATE REQUIRED PROPERTY rp_cal_date_duration_type: codegen::CalDateDurationType; + CREATE REQUIRED PROPERTY rp_cal_local_date: cal::local_date; + CREATE REQUIRED PROPERTY rp_cal_local_date_type: codegen::CalLocalDateType; + CREATE REQUIRED PROPERTY rp_cal_local_datetime: cal::local_datetime; + CREATE REQUIRED PROPERTY rp_cal_local_datetime_type: codegen::CalLocalDatetimeType; + CREATE REQUIRED PROPERTY rp_cal_local_time: cal::local_time; + CREATE REQUIRED PROPERTY rp_cal_local_time_type: codegen::CalLocalTimeType; + CREATE REQUIRED PROPERTY rp_cal_relative_duration: cal::relative_duration; + CREATE REQUIRED PROPERTY rp_cal_relative_duration_type: codegen::CalRelativeDurationType; + CREATE REQUIRED PROPERTY rp_cfg_memory: cfg::memory; + CREATE REQUIRED PROPERTY rp_cfg_memory_type: codegen::CfgMemoryType; + CREATE REQUIRED PROPERTY rp_datetime: std::datetime; + CREATE REQUIRED PROPERTY rp_datetime_type: codegen::DatetimeType; + CREATE REQUIRED PROPERTY rp_decimal: std::decimal; + CREATE REQUIRED PROPERTY rp_decimal_type: codegen::DecimalType; + CREATE REQUIRED PROPERTY rp_duration: std::duration; + CREATE REQUIRED PROPERTY rp_duration_type: codegen::DurationType; + CREATE REQUIRED PROPERTY rp_enum: codegen::EnumType; + CREATE REQUIRED PROPERTY rp_float32: std::float32; + CREATE REQUIRED PROPERTY rp_float32_type: codegen::Float32Type; + CREATE REQUIRED PROPERTY rp_float64: std::float64; + CREATE REQUIRED PROPERTY rp_float64_type: codegen::Float64Type; + CREATE REQUIRED PROPERTY rp_int16: std::int16; + CREATE REQUIRED PROPERTY rp_int16_type: codegen::Int16Type; + CREATE REQUIRED PROPERTY rp_int32: std::int32; + CREATE REQUIRED PROPERTY rp_int32_type: codegen::Int32Type; + CREATE REQUIRED PROPERTY rp_int64: std::int64; + CREATE REQUIRED PROPERTY rp_int64_type: codegen::Int64Type; + CREATE REQUIRED PROPERTY rp_json: std::json; + CREATE REQUIRED PROPERTY rp_json_type: codegen::JsonType; + CREATE REQUIRED PROPERTY rp_named_tuple_x_int64_y_int64: tuple; + CREATE REQUIRED PROPERTY rp_range_cal_local_date: range; + CREATE REQUIRED PROPERTY rp_range_cal_local_datetime: range; + CREATE REQUIRED PROPERTY rp_range_datetime: range; + CREATE REQUIRED PROPERTY rp_range_decimal: range; + CREATE REQUIRED PROPERTY rp_range_float32: range; + CREATE REQUIRED PROPERTY rp_range_float64: range; + CREATE REQUIRED PROPERTY rp_range_int32: range; + CREATE REQUIRED PROPERTY rp_range_int64: range; + CREATE REQUIRED PROPERTY rp_sequence: codegen::SequenceType; + CREATE REQUIRED PROPERTY rp_str: std::str; + CREATE REQUIRED PROPERTY rp_str_type: codegen::StrType; + CREATE REQUIRED PROPERTY rp_tuple_int64_int64: tuple; + CREATE REQUIRED PROPERTY rp_uuid: std::uuid; + CREATE REQUIRED PROPERTY rp_uuid_type: codegen::UuidType; + CREATE REQUIRED PROPERTY rp_vector_type: codegen::VectorType; + }; + CREATE SCALAR TYPE default::ExVector EXTENDING ext::pgvector::vector<1602>; +}; diff --git a/test/support/scripts/drop-roles.sh b/test/support/scripts/drop-roles.sh new file mode 100755 index 00000000..facdd066 --- /dev/null +++ b/test/support/scripts/drop-roles.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +set -e + +edgedb query --file test/support/scripts/edgeql/drop-roles.edgeql diff --git a/priv/scripts/edgedb_docs.exs b/test/support/scripts/edgedb_docs.exs similarity index 98% rename from priv/scripts/edgedb_docs.exs rename to test/support/scripts/edgedb_docs.exs index f6f95708..335f5cd9 100644 --- a/priv/scripts/edgedb_docs.exs +++ b/test/support/scripts/edgedb_docs.exs @@ -2,6 +2,9 @@ defmodule EdgeDB.Docs do @moduledoc false @skip_pages ~w(CHANGELOG.md) + @skip_modules [ + Mix.Tasks.Edgedb.Generate + ] @error_group :Errors @api_group :API @@ -252,6 +255,9 @@ defmodule EdgeDB.Docs do {module, Code.fetch_docs(module)} end) |> Enum.filter(fn + {mod, _doc} when mod in @skip_modules -> + false + {_mod, {:docs_v1, _annotation, _lang, _format, mod_doc, _meta, _docs}} when mod_doc in [:none, :hidden] -> false diff --git a/priv/scripts/edgeql/drop-roles.edgeql b/test/support/scripts/edgeql/drop-roles.edgeql similarity index 100% rename from priv/scripts/edgeql/drop-roles.edgeql rename to test/support/scripts/edgeql/drop-roles.edgeql diff --git a/priv/scripts/edgeql/setup-roles.edgeql b/test/support/scripts/edgeql/setup-roles.edgeql similarity index 100% rename from priv/scripts/edgeql/setup-roles.edgeql rename to test/support/scripts/edgeql/setup-roles.edgeql diff --git a/test/support/scripts/setup-roles.sh b/test/support/scripts/setup-roles.sh new file mode 100755 index 00000000..59191154 --- /dev/null +++ b/test/support/scripts/setup-roles.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +set -e + +edgedb query --file test/support/scripts/edgeql/setup-roles.edgeql