From 779d8973b51f7d467557420a5ad77856f26c25d6 Mon Sep 17 00:00:00 2001 From: Nik Sidnev Date: Thu, 25 Aug 2022 18:29:48 +0300 Subject: [PATCH 01/15] implement generation of EdgeQL queries modules --- .credo.exs | 4 +- .gitignore | 2 +- CHANGELOG.md | 6 + config/config.exs | 7 + edgedb.toml | 2 +- lib/edgedb.ex | 2 +- lib/edgedb/connection.ex | 44 +- lib/edgedb/edgeql/generator.ex | 550 ++++++++++ lib/edgedb/protocol.ex | 37 +- lib/edgedb/protocol/codecs/enum.ex | 23 +- lib/edgedb/protocol/codecs/scalar.ex | 3 +- lib/edgedb/query.ex | 2 + lib/edgedb/result.ex | 172 ++- lib/edgedb/types/named_tuple.ex | 12 +- lib/mix/edgedb/generate.ex | 120 +++ mix.exs | 23 +- mix.lock | 1 + pages/md/codegen.md | 87 ++ pages/md/main.md | 5 - priv/codegen/templates/_builtin.eex | 1 + priv/codegen/templates/_object.eex | 19 + priv/codegen/templates/_schema.eex | 11 + priv/codegen/templates/_set.eex | 7 + priv/codegen/templates/_shape.eex | 34 + priv/codegen/templates/query.ex.eex | 165 +++ priv/edgedb/schema/migrations/00003.edgeql | 6 - test/codegen/codegen_test.exs | 62 ++ test/edgedb/types/named_tuple_test.exs | 4 +- .../edgeql/scalars/select_int_named.edgeql | 1 + .../scalars/select_int_named.edgeql.ex.assert | 64 ++ .../scalars/select_int_positional.edgeql | 1 + .../select_int_positional.edgeql.ex.assert | 59 ++ .../select_optional_string_named.edgeql | 1 + ...ect_optional_string_named.edgeql.ex.assert | 64 ++ .../select_optional_string_positional.edgeql | 1 + ...ptional_string_positional.edgeql.ex.assert | 59 ++ .../edgeql/select_string_from_root.edgeql | 1 + .../select_string_from_root.edgeql.ex.assert | 54 + .../select_standart_types_named.edgeql | 95 ++ ...lect_standart_types_named.edgeql.ex.assert | 517 +++++++++ .../select_standart_types_positional.edgeql | 95 ++ ...standart_types_positional.edgeql.ex.assert | 711 +++++++++++++ .../select_startart_types_named_simple.edgeql | 11 + ...artart_types_named_simple.edgeql.ex.assert | 86 ++ .../edgeql/types/insert_f_named.edgeql | 11 + .../types/insert_f_named.edgeql.ex.assert | 88 ++ .../edgeql/types/insert_f_positional.edgeql | 11 + .../insert_f_positional.edgeql.ex.assert | 81 ++ .../codegen/edgeql/types/select_result.edgeql | 355 +++++++ .../types/select_result.edgeql.ex.assert | 988 ++++++++++++++++++ test/support/schema/codegen.esdl | 333 ++++++ .../support}/schema/default.esdl | 44 +- .../support}/schema/migrations/00001.edgeql | 0 .../support}/schema/migrations/00002.edgeql | 0 test/support/schema/migrations/00003.edgeql | 228 ++++ {priv => test/support}/scripts/drop-roles.sh | 0 .../support}/scripts/edgedb_docs.exs | 0 .../support}/scripts/edgeql/drop-roles.edgeql | 0 .../scripts/edgeql/setup-roles.edgeql | 0 {priv => test/support}/scripts/setup-roles.sh | 0 60 files changed, 5285 insertions(+), 85 deletions(-) create mode 100644 lib/edgedb/edgeql/generator.ex create mode 100644 lib/mix/edgedb/generate.ex create mode 100644 pages/md/codegen.md create mode 100644 priv/codegen/templates/_builtin.eex create mode 100644 priv/codegen/templates/_object.eex create mode 100644 priv/codegen/templates/_schema.eex create mode 100644 priv/codegen/templates/_set.eex create mode 100644 priv/codegen/templates/_shape.eex create mode 100644 priv/codegen/templates/query.ex.eex delete mode 100644 priv/edgedb/schema/migrations/00003.edgeql create mode 100644 test/codegen/codegen_test.exs create mode 100644 test/support/codegen/edgeql/scalars/select_int_named.edgeql create mode 100644 test/support/codegen/edgeql/scalars/select_int_named.edgeql.ex.assert create mode 100644 test/support/codegen/edgeql/scalars/select_int_positional.edgeql create mode 100644 test/support/codegen/edgeql/scalars/select_int_positional.edgeql.ex.assert create mode 100644 test/support/codegen/edgeql/scalars/select_optional_string_named.edgeql create mode 100644 test/support/codegen/edgeql/scalars/select_optional_string_named.edgeql.ex.assert create mode 100644 test/support/codegen/edgeql/scalars/select_optional_string_positional.edgeql create mode 100644 test/support/codegen/edgeql/scalars/select_optional_string_positional.edgeql.ex.assert create mode 100644 test/support/codegen/edgeql/select_string_from_root.edgeql create mode 100644 test/support/codegen/edgeql/select_string_from_root.edgeql.ex.assert create mode 100644 test/support/codegen/edgeql/standart/select_standart_types_named.edgeql create mode 100644 test/support/codegen/edgeql/standart/select_standart_types_named.edgeql.ex.assert create mode 100644 test/support/codegen/edgeql/standart/select_standart_types_positional.edgeql create mode 100644 test/support/codegen/edgeql/standart/select_standart_types_positional.edgeql.ex.assert create mode 100644 test/support/codegen/edgeql/standart/select_startart_types_named_simple.edgeql create mode 100644 test/support/codegen/edgeql/standart/select_startart_types_named_simple.edgeql.ex.assert create mode 100644 test/support/codegen/edgeql/types/insert_f_named.edgeql create mode 100644 test/support/codegen/edgeql/types/insert_f_named.edgeql.ex.assert create mode 100644 test/support/codegen/edgeql/types/insert_f_positional.edgeql create mode 100644 test/support/codegen/edgeql/types/insert_f_positional.edgeql.ex.assert create mode 100644 test/support/codegen/edgeql/types/select_result.edgeql create mode 100644 test/support/codegen/edgeql/types/select_result.edgeql.ex.assert create mode 100644 test/support/schema/codegen.esdl rename {priv/edgedb => test/support}/schema/default.esdl (70%) rename {priv/edgedb => test/support}/schema/migrations/00001.edgeql (100%) rename {priv/edgedb => test/support}/schema/migrations/00002.edgeql (100%) create mode 100644 test/support/schema/migrations/00003.edgeql rename {priv => test/support}/scripts/drop-roles.sh (100%) rename {priv => test/support}/scripts/edgedb_docs.exs (100%) rename {priv => test/support}/scripts/edgeql/drop-roles.edgeql (100%) rename {priv => test/support}/scripts/edgeql/setup-roles.edgeql (100%) rename {priv => test/support}/scripts/setup-roles.sh (100%) diff --git a/.credo.exs b/.credo.exs index 16c6df25..2f5a369f 100644 --- a/.credo.exs +++ b/.credo.exs @@ -31,7 +31,7 @@ "apps/*/test/", "apps/*/web/" ], - excluded: [~r"/_build/", ~r"/deps/", ~r"/node_modules/"] + excluded: [~r"/_build/", ~r"/deps/", ~r"/node_modules/", ~r"/test/*/codegen/"] }, # # Load and configure plugins here: @@ -131,7 +131,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/.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 1020c101..340bfd54 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,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..af58acb3 100644 --- a/config/config.exs +++ b/config/config.exs @@ -1,3 +1,10 @@ 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 + ] diff --git a/edgedb.toml b/edgedb.toml index 17811b37..06b4ea8c 100644 --- a/edgedb.toml +++ b/edgedb.toml @@ -2,4 +2,4 @@ server-version = "3.0" [project] -schema-dir = "./priv/edgedb/schema" +schema-dir = "./test/support/schema" diff --git a/lib/edgedb.ex b/lib/edgedb.ex index f9de7dfc..fee822d8 100644 --- a/lib/edgedb.ex +++ b/lib/edgedb.ex @@ -785,7 +785,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..47f169ba --- /dev/null +++ b/lib/edgedb/edgeql/generator.ex @@ -0,0 +1,550 @@ +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} + 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) + + 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 + ) + + rendered_schema = + if raw_schema do + render_schema( + schema: raw_schema, + render_schema: &render_schema/1 + ) + else + nil + end + + generated_module = + generate_query_module( + query_file: query_file, + module_name: module_name, + types: types(), + shape: rendered_shape, + schema: rendered_schema, + query_function: @cardinality_to_function[query.result_cardinality], + should_render_type_for_shape: complex_shape?(raw_shape), + result_type: (complex_shape?(raw_shape) && "result()") || rendered_shape, + query: %{ + statement: query.statement, + has_positional_args: positional? and length(args) != 0, + has_named_args: not positional? and length(args) != 0, + 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 + }, + 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} + 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} + end + + defp codec_to_shape(%Codecs.Duration{}, _codec_storage) do + timex? = Application.get_env(:edgedb, :timex_duration, true) + + typename = "duration()" + + case Code.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} + 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} + 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} + 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, &":#{&1}")]}) + %{type: :builtin, typespec: full_type_name} + 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 -> + 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/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..467b8e25 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: [], @@ -33,6 +34,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(), 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..dc2563bd --- /dev/null +++ b/lib/mix/edgedb/generate.ex @@ -0,0 +1,120 @@ +# 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}: #{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 18ebfe88..f65ef903 100644 --- a/mix.exs +++ b/mix.exs @@ -33,7 +33,8 @@ defmodule EdgeDB.MixProject do extra_applications: [ :crypto, :logger, - :ssl + :ssl, + :eex ] ] end @@ -47,7 +48,8 @@ defmodule EdgeDB.MixProject do {:jose, "~> 1.11"}, {:crc, "~> 0.10.4"}, {:castore, "~> 0.1.0 or ~> 1.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]}, @@ -62,7 +64,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 @@ -97,7 +99,8 @@ defmodule EdgeDB.MixProject do "edgedb.docs": :ci, coveralls: :test, "coveralls.detail": :test, - "coveralls.html": :test + "coveralls.html": :test, + "edgedb.generate": :dev ] end @@ -106,7 +109,8 @@ defmodule EdgeDB.MixProject do plt_add_apps: [ :ex_unit, :jason, - :timex + :timex, + :mix ], plt_file: {:no_warn, "priv/plts/dialyzer.plt"} ] @@ -132,6 +136,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" @@ -161,14 +166,14 @@ defmodule EdgeDB.MixProject do defp aliases do [ "edgedb.roles.setup": [ - "cmd priv/scripts/setup-roles.sh" + "cmd priv/test/support/scripts/setup-roles.sh" ], "edgedb.roles.reset": [ - "cmd priv/scripts/drop-roles.sh", - "cmd priv/scripts/setup-roles.sh" + "cmd priv/test/support/scripts/drop-roles.sh", + "cmd priv/test/support/scripts/setup-roles.sh" ], "edgedb.docs": [ - "run priv/scripts/edgedb_docs.exs" + "run priv/test/suppport/scripts/edgedb_docs.exs" ] ] end diff --git a/mix.lock b/mix.lock index cbdf442b..00c76871 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/priv/codegen/templates/_builtin.eex b/priv/codegen/templates/_builtin.eex new file mode 100644 index 00000000..02ba25f9 --- /dev/null +++ b/priv/codegen/templates/_builtin.eex @@ -0,0 +1 @@ +<%= @builtin.typespec %> diff --git a/priv/codegen/templates/_object.eex b/priv/codegen/templates/_object.eex new file mode 100644 index 00000000..eb7d7f1b --- /dev/null +++ b/priv/codegen/templates/_object.eex @@ -0,0 +1,19 @@ +%{ + <%= for {name, field} <- @object.fields do %> + + <%= if field[:is_link_property] do %> + "@<%= name %>": + <% else %> + <%= name %>: + <% end %> + + <%= @render_shape.( + shape: field, + render_shape: @render_shape, + render_builtin: @render_builtin, + render_object: @render_object, + render_set: @render_set + ) %>, + + <% end %> +} diff --git a/priv/codegen/templates/_schema.eex b/priv/codegen/templates/_schema.eex new file mode 100644 index 00000000..f53bba2e --- /dev/null +++ b/priv/codegen/templates/_schema.eex @@ -0,0 +1,11 @@ +[ + <%= for type <- @schema do %> + <%= case type do %> + <% {name, schema} -> %> + <%= name %>: <%= @render_schema.(schema: schema, render_schema: @render_schema) %>, + + <% name -> %> + :<%= name %>, + <% end %> + <% end %> +] diff --git a/priv/codegen/templates/_set.eex b/priv/codegen/templates/_set.eex new file mode 100644 index 00000000..27aca7d1 --- /dev/null +++ b/priv/codegen/templates/_set.eex @@ -0,0 +1,7 @@ +<%= @render_shape.( + shape: @set.shape, + render_shape: @render_shape, + render_builtin: @render_builtin, + render_object: @render_object, + render_set: @render_set +) %> diff --git a/priv/codegen/templates/_shape.eex b/priv/codegen/templates/_shape.eex new file mode 100644 index 00000000..64259941 --- /dev/null +++ b/priv/codegen/templates/_shape.eex @@ -0,0 +1,34 @@ +<%= if @shape[:is_list] do %> +[ +<% end %> + +<%= case @shape do %> + <% %{type: :builtin} = builtin -> %> + <%= @render_builtin.(builtin: builtin) %> + + <% %{type: :object} = object -> %> + <%= @render_object.( + object: object, + render_shape: @render_shape, + render_builtin: @render_builtin, + render_object: @render_object, + render_set: @render_set + ) %> + + <% %{type: :set} = set -> %> + <%= @render_set.( + set: set, + render_shape: @render_shape, + render_builtin: @render_builtin, + render_object: @render_object, + render_set: @render_set + ) %> +<% end %> + +<%= if @shape[:is_list] do %> +] +<% end %> + +<%= if @shape[:is_optional] do %> +| nil +<% end %> diff --git a/priv/codegen/templates/query.ex.eex b/priv/codegen/templates/query.ex.eex new file mode 100644 index 00000000..4d74c878 --- /dev/null +++ b/priv/codegen/templates/query.ex.eex @@ -0,0 +1,165 @@ +# 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} + ``` + """ + + <%= for {type_name, {typedoc, typespec}} <- @types do %> + @typedoc """ + ```edgeql + <%= typedoc %> + ``` + """ + @type <%= type_name %> :: <%= typespec %> + <% end %> + + <%= if @should_render_type_for_shape do %> + @type result() :: <%= @shape %> + <% 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 %> + + <%= if not is_nil(@schema) do %> + @schema <%= @schema %> + defp do_query(client, args, opts) do + opts = Keyword.merge(opts, __transform_result__: [schema: @schema]) + EdgeDB.<%= @query_function %>(client, @query, args, opts) + end + <% else %> + defp do_query(client, args, opts) do + EdgeDB.<%= @query_function %>(client, @query, args, opts) + 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/test/codegen/codegen_test.exs b/test/codegen/codegen_test.exs new file mode 100644 index 00000000..3f2c0b11 --- /dev/null +++ b/test/codegen/codegen_test.exs @@ -0,0 +1,62 @@ +defmodule Tests.CodegenTest do + use Tests.Support.EdgeDBCase + + @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} do + 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 + } = + Tests.Codegen.Queries.Standart.SelectStartartTypesNamedSimple.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..1f3356d1 --- /dev/null +++ b/test/support/codegen/edgeql/scalars/select_int_named.edgeql.ex.assert @@ -0,0 +1,64 @@ +# 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} + ``` + """ + + @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 + 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..81b27b0a --- /dev/null +++ b/test/support/codegen/edgeql/scalars/select_int_positional.edgeql.ex.assert @@ -0,0 +1,59 @@ +# 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} + ``` + """ + + @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 + 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..a74ce8ec --- /dev/null +++ b/test/support/codegen/edgeql/scalars/select_optional_string_named.edgeql.ex.assert @@ -0,0 +1,64 @@ +# 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} + ``` + """ + + @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 + 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..48f77b2f --- /dev/null +++ b/test/support/codegen/edgeql/scalars/select_optional_string_positional.edgeql.ex.assert @@ -0,0 +1,59 @@ +# 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} + ``` + """ + + @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 + 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..3ce63f8a --- /dev/null +++ b/test/support/codegen/edgeql/select_string_from_root.edgeql.ex.assert @@ -0,0 +1,54 @@ +# 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} + ``` + """ + + @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 + 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..63fcd512 --- /dev/null +++ b/test/support/codegen/edgeql/standart/select_standart_types_named.edgeql.ex.assert @@ -0,0 +1,517 @@ +# 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} + ``` + """ + + @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, __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..d6d5b52b --- /dev/null +++ b/test/support/codegen/edgeql/standart/select_standart_types_positional.edgeql.ex.assert @@ -0,0 +1,711 @@ +# 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} + ``` + """ + + @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, __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..f72c545c --- /dev/null +++ b/test/support/codegen/edgeql/standart/select_startart_types_named_simple.edgeql.ex.assert @@ -0,0 +1,86 @@ +# 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} + ``` + """ + + @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, __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..fb0f2576 --- /dev/null +++ b/test/support/codegen/edgeql/types/insert_f_named.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/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} + ``` + """ + + @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 + 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..c7ec3641 --- /dev/null +++ b/test/support/codegen/edgeql/types/insert_f_positional.edgeql.ex.assert @@ -0,0 +1,81 @@ +# 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} + ``` + """ + + @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 + 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..61d71596 --- /dev/null +++ b/test/support/codegen/edgeql/types/select_result.edgeql.ex.assert @@ -0,0 +1,988 @@ +# 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} + ``` + """ + + @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, __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/priv/scripts/drop-roles.sh b/test/support/scripts/drop-roles.sh similarity index 100% rename from priv/scripts/drop-roles.sh rename to test/support/scripts/drop-roles.sh diff --git a/priv/scripts/edgedb_docs.exs b/test/support/scripts/edgedb_docs.exs similarity index 100% rename from priv/scripts/edgedb_docs.exs rename to test/support/scripts/edgedb_docs.exs 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/priv/scripts/setup-roles.sh b/test/support/scripts/setup-roles.sh similarity index 100% rename from priv/scripts/setup-roles.sh rename to test/support/scripts/setup-roles.sh From 309944d859b71f8bb4e6e110ac169ce70898b817 Mon Sep 17 00:00:00 2001 From: Devi Prasad Date: Tue, 26 Sep 2023 07:02:30 -0500 Subject: [PATCH 02/15] feat: structure generation --- config/config.exs | 12 +- edgedb.toml | 3 +- lib/edgedb/edgeql/generator.ex | 18 +- priv/codegen/templates/_builtin.eex | 3 + priv/codegen/templates/_object.eex | 62 ++++-- priv/codegen/templates/_shape.eex | 5 +- priv/codegen/templates/query.ex.eex | 6 +- .../get_current_active_song.edgeql.ex | 183 ++++++++++++++++++ .../get_current_active_song.edgeql | 14 ++ priv/edgedb/schema/default.esdl | 171 ++++++++++++++++ priv/edgedb/schema/migrations/00001.edgeql | 47 +++++ priv/edgedb/schema/migrations/00002.edgeql | 12 ++ priv/edgedb/schema/migrations/00003.edgeql | 38 ++++ priv/edgedb/schema/migrations/00004.edgeql | 8 + priv/edgedb/schema/migrations/00005.edgeql | 8 + priv/edgedb/schema/migrations/00006.edgeql | 7 + priv/edgedb/schema/migrations/00007.edgeql | 9 + priv/edgedb/schema/migrations/00008.edgeql | 10 + priv/edgedb/schema/migrations/00009.edgeql | 9 + priv/edgedb/schema/migrations/00010.edgeql | 50 +++++ priv/edgedb/schema/migrations/00011.edgeql | 67 +++++++ priv/edgedb/schema/migrations/00012.edgeql | 16 ++ priv/edgedb/schema/migrations/00013.edgeql | 24 +++ priv/edgedb/schema/migrations/00014.edgeql | 15 ++ priv/edgedb/schema/migrations/00015.edgeql | 16 ++ priv/edgedb/schema/migrations/00016.edgeql | 12 ++ priv/edgedb/schema/migrations/00017.edgeql | 31 +++ priv/edgedb/schema/migrations/00018.edgeql | 10 + priv/edgedb/schema/migrations/00019.edgeql | 17 ++ priv/edgedb/schema/migrations/00020.edgeql | 39 ++++ 30 files changed, 884 insertions(+), 38 deletions(-) create mode 100644 priv/edgedb/codegen/queries/media_library/get_current_active_song.edgeql.ex create mode 100644 priv/edgedb/edgeql/media_library/get_current_active_song.edgeql create mode 100644 priv/edgedb/schema/default.esdl create mode 100644 priv/edgedb/schema/migrations/00001.edgeql create mode 100644 priv/edgedb/schema/migrations/00002.edgeql create mode 100644 priv/edgedb/schema/migrations/00003.edgeql create mode 100644 priv/edgedb/schema/migrations/00004.edgeql create mode 100644 priv/edgedb/schema/migrations/00005.edgeql create mode 100644 priv/edgedb/schema/migrations/00006.edgeql create mode 100644 priv/edgedb/schema/migrations/00007.edgeql create mode 100644 priv/edgedb/schema/migrations/00008.edgeql create mode 100644 priv/edgedb/schema/migrations/00009.edgeql create mode 100644 priv/edgedb/schema/migrations/00010.edgeql create mode 100644 priv/edgedb/schema/migrations/00011.edgeql create mode 100644 priv/edgedb/schema/migrations/00012.edgeql create mode 100644 priv/edgedb/schema/migrations/00013.edgeql create mode 100644 priv/edgedb/schema/migrations/00014.edgeql create mode 100644 priv/edgedb/schema/migrations/00015.edgeql create mode 100644 priv/edgedb/schema/migrations/00016.edgeql create mode 100644 priv/edgedb/schema/migrations/00017.edgeql create mode 100644 priv/edgedb/schema/migrations/00018.edgeql create mode 100644 priv/edgedb/schema/migrations/00019.edgeql create mode 100644 priv/edgedb/schema/migrations/00020.edgeql diff --git a/config/config.exs b/config/config.exs index af58acb3..b7057400 100644 --- a/config/config.exs +++ b/config/config.exs @@ -2,9 +2,17 @@ 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: "test/support/codegen/edgeql/", - output_path: "test/codegen/queries/", + 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 06b4ea8c..b9d641b0 100644 --- a/edgedb.toml +++ b/edgedb.toml @@ -2,4 +2,5 @@ server-version = "3.0" [project] -schema-dir = "./test/support/schema" +# schema-dir = "./test/support/schema" +schema-dir = "./priv/edgedb/schema" diff --git a/lib/edgedb/edgeql/generator.ex b/lib/edgedb/edgeql/generator.ex index 47f169ba..cab2dca0 100644 --- a/lib/edgedb/edgeql/generator.ex +++ b/lib/edgedb/edgeql/generator.ex @@ -182,7 +182,8 @@ defmodule EdgeDB.EdgeQL.Generator do render_shape: &render_shape/1, render_builtin: &render_builtin/1, render_object: &render_object/1, - render_set: &render_set/1 + render_set: &render_set/1, + camelize: &Macro.camelize/1 ) rendered_schema = @@ -203,8 +204,7 @@ defmodule EdgeDB.EdgeQL.Generator do shape: rendered_shape, schema: rendered_schema, query_function: @cardinality_to_function[query.result_cardinality], - should_render_type_for_shape: complex_shape?(raw_shape), - result_type: (complex_shape?(raw_shape) && "result()") || rendered_shape, + result_type: "Result.t()", query: %{ statement: query.statement, has_positional_args: positional? and length(args) != 0, @@ -431,18 +431,6 @@ defmodule EdgeDB.EdgeQL.Generator do "#{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 diff --git a/priv/codegen/templates/_builtin.eex b/priv/codegen/templates/_builtin.eex index 02ba25f9..2b3575d8 100644 --- a/priv/codegen/templates/_builtin.eex +++ b/priv/codegen/templates/_builtin.eex @@ -1 +1,4 @@ <%= @builtin.typespec %> +<%= 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 index eb7d7f1b..6f8ec2a0 100644 --- a/priv/codegen/templates/_object.eex +++ b/priv/codegen/templates/_object.eex @@ -1,19 +1,51 @@ -%{ - <%= for {name, field} <- @object.fields do %> +<%= for {name, field} <- @object.fields do %> + <%= case field do %> + <% %{type: :object} -> %> + defmodule <%= @camelize.(name) %> do + <%= @render_object.( + object: field, + render_shape: @render_shape, + render_builtin: @render_builtin, + render_object: @render_object, + render_set: @render_set, + camelize: @camelize + ) %> + end; + <% _ -> %> + <% false %> + <% end %> +<% end %> - <%= if field[:is_link_property] do %> - "@<%= name %>": - <% else %> - <%= name %>: - <% end %> +defstruct [ + <%= for {name, _} <- @object.fields do %> + :<%= name %>, + <% end %> +]; - <%= @render_shape.( - shape: field, - render_shape: @render_shape, - render_builtin: @render_builtin, - render_object: @render_object, - render_set: @render_set - ) %>, +@type t() :: %__MODULE__{ + <%= for {name, field} <- @object.fields do %> + <%= case field do %> + <% %{type: :object} -> %> + <%= name %>: <%= @camelize.(name) %>.t() + <%= if field[:is_optional] do %>| nil<% end %>, + + <% _ -> %> + <%= if field[:is_link_property] do %> + "@<%= name %>": + <% else %> + <%= name %>: + <% end %> + <%= @render_shape.( + shape: field, + render_shape: @render_shape, + render_builtin: @render_builtin, + render_object: @render_object, + render_set: @render_set, + camelize: @camelize + ) %>, + <% end %> <% end %> -} +} <%= if @object[:is_optional] do %> +| nil +<% end %>; diff --git a/priv/codegen/templates/_shape.eex b/priv/codegen/templates/_shape.eex index 64259941..d9ca2700 100644 --- a/priv/codegen/templates/_shape.eex +++ b/priv/codegen/templates/_shape.eex @@ -12,7 +12,8 @@ render_shape: @render_shape, render_builtin: @render_builtin, render_object: @render_object, - render_set: @render_set + render_set: @render_set, + camelize: @camelize ) %> <% %{type: :set} = set -> %> @@ -27,8 +28,8 @@ <%= if @shape[:is_list] do %> ] -<% end %> <%= if @shape[:is_optional] do %> | nil <% end %> +<% end %> diff --git a/priv/codegen/templates/query.ex.eex b/priv/codegen/templates/query.ex.eex index 4d74c878..8e21f89b 100644 --- a/priv/codegen/templates/query.ex.eex +++ b/priv/codegen/templates/query.ex.eex @@ -26,9 +26,9 @@ defmodule <%= @module_name %> do @type <%= type_name %> :: <%= typespec %> <% end %> - <%= if @should_render_type_for_shape do %> - @type result() :: <%= @shape %> - <% end %> + defmodule Result do + <%= @shape %> + end <%= if @query.has_positional_args do %> diff --git a/priv/edgedb/codegen/queries/media_library/get_current_active_song.edgeql.ex b/priv/edgedb/codegen/queries/media_library/get_current_active_song.edgeql.ex new file mode 100644 index 00000000..3403c46e --- /dev/null +++ b/priv/edgedb/codegen/queries/media_library/get_current_active_song.edgeql.ex @@ -0,0 +1,183 @@ +# AUTOGENERATED: DO NOT MODIFY +# Generated by Elixir client for EdgeDB via `mix edgedb.generate` from +# `priv/edgedb/edgeql/media_library/get_current_active_song.edgeql`. +defmodule Tests.Codegen.Queries.MediaLibrary.GetCurrentActiveSong do + @query """ + select Song { + *, + mp3: { + * + }, + user: { + id, + } + } + filter + .user.id = $user_id + and + .status in {SongStatus.playing, SongStatus.paused} + limit 1 + """ + + @moduledoc """ + Generated module for the EdgeQL query from + `priv/edgedb/edgeql/media_library/get_current_active_song.edgeql`. + + Query: + + ```edgeql + #{@query} + ``` + """ + + @typedoc """ + ```edgeql + std::uuid + ``` + """ + @type uuid() :: binary() + + @typedoc """ + ```edgeql + std::duration + ``` + """ + @type duration() :: Timex.Duration.t() | integer() + + @typedoc """ + ```edgeql + scalar type default::SongStatus extending enum + ``` + """ + @type default__song_status() :: String.t() | :stopped | :playing | :paused + + @typedoc """ + ```edgeql + scalar type default::inet extending std::bytes + ``` + """ + @type default__inet() :: bitstring() + + defmodule Result do + defmodule Mp3 do + defstruct [:id, :filename, :filepath, :filesize, :url] + + @type t() :: %__MODULE__{ + id: uuid(), + filename: String.t(), + filepath: String.t(), + filesize: EdgeDB.ConfigMemory.t(), + url: String.t() + } + end + + defmodule User do + defstruct [:id] + @type t() :: %__MODULE__{id: uuid()} | nil + end + + defstruct [ + :mp3, + :user, + :artist, + :title, + :attribution, + :date_recorded, + :date_released, + :paused_at, + :played_at, + :server_ip, + :position, + :id, + :inserted_at, + :updated_at, + :status, + :duration + ] + + @type t() :: + %__MODULE__{ + mp3: Mp3.t(), + user: User.t() | nil, + artist: String.t(), + title: String.t(), + attribution: String.t() | nil, + date_recorded: NaiveDateTime.t() | nil, + date_released: NaiveDateTime.t() | nil, + paused_at: DateTime.t() | nil, + played_at: DateTime.t() | nil, + server_ip: default__inet() | nil, + position: integer(), + id: uuid(), + inserted_at: NaiveDateTime.t(), + updated_at: NaiveDateTime.t(), + status: default__song_status(), + duration: duration() + } + | nil + end + + @type keyword_args() :: [{:user_id, uuid()}] + + @type map_args() :: %{ + user_id: 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.t()} + | {: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.t() + def query!(client, args, opts \\ []) do + case do_query(client, args, opts) do + {:ok, result} -> + result + + {:error, exc} -> + raise exc + end + end + + @schema [ + :updated_at, + :title, + :status, + :server_ip, + :position, + :played_at, + :paused_at, + :inserted_at, + :id, + :duration, + :date_released, + :date_recorded, + :attribution, + :artist, + user: [:id], + mp3: [:url, :id, :filesize, :filepath, :filename] + ] + defp do_query(client, args, opts) do + opts = Keyword.merge(opts, __transform_result__: [schema: @schema]) + EdgeDB.query_single(client, @query, args, opts) + end +end diff --git a/priv/edgedb/edgeql/media_library/get_current_active_song.edgeql b/priv/edgedb/edgeql/media_library/get_current_active_song.edgeql new file mode 100644 index 00000000..823d45d7 --- /dev/null +++ b/priv/edgedb/edgeql/media_library/get_current_active_song.edgeql @@ -0,0 +1,14 @@ +select Song { + *, + mp3: { + * + }, + user: { + id, + } +} +filter + .user.id = $user_id + and + .status in {SongStatus.playing, SongStatus.paused} +limit 1 diff --git a/priv/edgedb/schema/default.esdl b/priv/edgedb/schema/default.esdl new file mode 100644 index 00000000..ba085cab --- /dev/null +++ b/priv/edgedb/schema/default.esdl @@ -0,0 +1,171 @@ +module default { + required global max_songs_count := 30; + + global is_admin: bool; + + global current_user_id: uuid; + global current_user := ( + select User filter .id = global current_user_id + ); + + # cast insensitive string + scalar type cistr extending str; + + abstract type Timestamped { + required inserted_at: cal::local_datetime { + readonly := true; + rewrite insert using (cal::to_local_datetime(datetime_current(), 'UTC')) + } + + required updated_at: cal::local_datetime { + rewrite insert, update using (cal::to_local_datetime(datetime_current(), 'UTC')) + } + } + + type User extending Timestamped { + required name: str; + required username: str { + constraint exclusive; + } + + required email: cistr { + constraint regexp(r'^[^\s]+@[^\s]+$'); + constraint max_len_value(160); + + rewrite insert, update using (str_lower(__subject__.email)); + } + + profile_tagline: str; + + avatar_url: str; + external_homepage_url: str; + + property songs_count := count(."{}"; + } + + required user: User { + on target delete delete source; + } + + access policy owner_can_do_everything + allow all + using (global current_user.id ?= .user.id); + + access policy anyone_can_create + allow insert; + + index on (.provider); + constraint exclusive on ((.user, .provider)); + } + + scalar type SongStatus extending enum; + scalar type inet extending bytes; + + type MP3 { + required url: str; + required filename: str; + required filepath: str; + + required filesize: cfg::memory { + default := 0 + } + } + + type Song extending Timestamped { + required title: str; + required artist: str; + + attribution: str; + + server_ip: inet; + + required duration: duration { + default := '0 seconds'; + } + + required position: int64 { + default := 0; + } + + required status: SongStatus { + default := SongStatus.stopped; + } + + date_recorded: cal::local_datetime; + date_released: cal::local_datetime; + + played_at: datetime { + rewrite update using ( + datetime_current() + if __subject__.status = SongStatus.playing + else __old__.played_at + ) + } + + paused_at: datetime { + rewrite update using ( + datetime_current() + if __subject__.status = SongStatus.stopped + else __old__.played_at + ) + } + + required mp3: MP3 { + on source delete delete target; + } + + user: User { + # allow to keep songs until the cleaner deletes it with the real file + on target delete allow; + } + + access policy owner_can_do_everything + allow all + using (global current_user.id ?= .user.id); + + access policy admin_can_do_everything + allow all + using (global is_admin ?= true); + + access policy anyone_can_read + allow select; + + trigger ensure_user_songs_count_not_exceeded after insert, update for each do ( + assert( + __new__.user.songs_count <= global max_songs_count, + message := "Songs limit exceeded", + ) + ); + + index on (.status); + constraint exclusive on ((.user, .title, .artist)); + } +} diff --git a/priv/edgedb/schema/migrations/00001.edgeql b/priv/edgedb/schema/migrations/00001.edgeql new file mode 100644 index 00000000..8681a2fe --- /dev/null +++ b/priv/edgedb/schema/migrations/00001.edgeql @@ -0,0 +1,47 @@ +CREATE MIGRATION m1ujqlj37zkefvbigraftt72bbdxu2q6mcun4xg7hwkeyuuxtgxhrq + ONTO initial +{ + CREATE SCALAR TYPE default::cistr EXTENDING std::str; + CREATE TYPE default::User { + CREATE REQUIRED PROPERTY username -> std::str; + CREATE INDEX ON (.username); + CREATE REQUIRED PROPERTY email -> default::cistr; + CREATE INDEX ON (.email); + CREATE LINK active_profile_user -> default::User { + ON TARGET DELETE ALLOW; + }; + CREATE PROPERTY confirmed_at -> cal::local_datetime; + CREATE REQUIRED PROPERTY inserted_at -> cal::local_datetime { + SET default := (cal::to_local_datetime(std::datetime_current(), 'UTC')); + }; + CREATE PROPERTY name -> std::str; + CREATE PROPERTY profile_tagline -> std::str; + CREATE REQUIRED PROPERTY role -> std::str { + SET default := ("subscriber"); + }; + CREATE REQUIRED PROPERTY updated_at -> cal::local_datetime { + SET default := (cal::to_local_datetime(std::datetime_current(), 'UTC')); + }; + }; + CREATE TYPE default::Identity { + CREATE REQUIRED LINK user -> default::User { + ON TARGET DELETE DELETE SOURCE; + }; + CREATE REQUIRED PROPERTY provider -> std::str; + CREATE CONSTRAINT std::exclusive ON ((.user, .provider)); + CREATE INDEX ON (.provider); + CREATE REQUIRED PROPERTY inserted_at -> cal::local_datetime { + SET default := (cal::to_local_datetime(std::datetime_current(), 'UTC')); + }; + CREATE REQUIRED PROPERTY provider_email -> std::str; + CREATE REQUIRED PROPERTY provider_id -> std::str; + CREATE REQUIRED PROPERTY provider_login -> std::str; + CREATE REQUIRED PROPERTY provider_meta -> std::json { + SET default := ('{}'); + }; + CREATE REQUIRED PROPERTY provider_token -> std::str; + CREATE REQUIRED PROPERTY updated_at -> cal::local_datetime { + SET default := (cal::to_local_datetime(std::datetime_current(), 'UTC')); + }; + }; +}; diff --git a/priv/edgedb/schema/migrations/00002.edgeql b/priv/edgedb/schema/migrations/00002.edgeql new file mode 100644 index 00000000..8484be59 --- /dev/null +++ b/priv/edgedb/schema/migrations/00002.edgeql @@ -0,0 +1,12 @@ +CREATE MIGRATION m1bwaytmgkte3dpabashzohfm56w3yirzomvfbh5r7cbay5jytegaa + ONTO m1ujqlj37zkefvbigraftt72bbdxu2q6mcun4xg7hwkeyuuxtgxhrq +{ + CREATE TYPE default::Genre { + CREATE REQUIRED PROPERTY slug -> std::str { + CREATE CONSTRAINT std::exclusive; + }; + CREATE REQUIRED PROPERTY title -> std::str { + CREATE CONSTRAINT std::exclusive; + }; + }; +}; diff --git a/priv/edgedb/schema/migrations/00003.edgeql b/priv/edgedb/schema/migrations/00003.edgeql new file mode 100644 index 00000000..0bd0010e --- /dev/null +++ b/priv/edgedb/schema/migrations/00003.edgeql @@ -0,0 +1,38 @@ +CREATE MIGRATION m1qb4i57nhmluwtd7pbeornej7kthhw34aejzjwrdcr65fiekxe3nq + ONTO m1bwaytmgkte3dpabashzohfm56w3yirzomvfbh5r7cbay5jytegaa +{ + CREATE SCALAR TYPE default::SongStatus EXTENDING enum; + CREATE TYPE default::Song { + CREATE LINK user -> default::User { + ON TARGET DELETE ALLOW; + }; + CREATE REQUIRED PROPERTY artist -> std::str; + CREATE REQUIRED PROPERTY title -> std::str; + CREATE CONSTRAINT std::exclusive ON ((.user, .title, .artist)); + CREATE REQUIRED PROPERTY status -> default::SongStatus { + SET default := (default::SongStatus.Stopped); + }; + CREATE INDEX ON (.status); + CREATE LINK genre -> default::Genre { + ON TARGET DELETE ALLOW; + }; + CREATE PROPERTY album_artist -> std::str; + CREATE PROPERTY attribution -> std::str; + CREATE PROPERTY date_recorded -> cal::local_datetime; + CREATE PROPERTY date_released -> cal::local_datetime; + CREATE REQUIRED PROPERTY duration -> std::int64 { + SET default := 0; + }; + CREATE REQUIRED PROPERTY inserted_at -> cal::local_datetime { + SET default := (cal::to_local_datetime(std::datetime_current(), 'UTC')); + }; + CREATE REQUIRED PROPERTY mp3_filename -> std::str; + CREATE REQUIRED PROPERTY mp3_filepath -> std::str; + CREATE REQUIRED PROPERTY mp3_url -> std::str; + CREATE PROPERTY paused_at -> std::datetime; + CREATE PROPERTY played_at -> std::datetime; + CREATE REQUIRED PROPERTY updated_at -> cal::local_datetime { + SET default := (cal::to_local_datetime(std::datetime_current(), 'UTC')); + }; + }; +}; diff --git a/priv/edgedb/schema/migrations/00004.edgeql b/priv/edgedb/schema/migrations/00004.edgeql new file mode 100644 index 00000000..f3049999 --- /dev/null +++ b/priv/edgedb/schema/migrations/00004.edgeql @@ -0,0 +1,8 @@ +CREATE MIGRATION m147bo4znisjhp7ymyunkfc66a3hqctob7lq5jp2xy2m4gh5vkzzya + ONTO m1qb4i57nhmluwtd7pbeornej7kthhw34aejzjwrdcr65fiekxe3nq +{ + ALTER TYPE default::User { + CREATE PROPERTY avatar_url -> std::str; + CREATE PROPERTY external_homepage_url -> std::str; + }; +}; diff --git a/priv/edgedb/schema/migrations/00005.edgeql b/priv/edgedb/schema/migrations/00005.edgeql new file mode 100644 index 00000000..be4c2408 --- /dev/null +++ b/priv/edgedb/schema/migrations/00005.edgeql @@ -0,0 +1,8 @@ +CREATE MIGRATION m1hd7litg4ylc632kuyv3xqipk6bvjgcrbeoujgvoccts65yholkda + ONTO m147bo4znisjhp7ymyunkfc66a3hqctob7lq5jp2xy2m4gh5vkzzya +{ + CREATE SCALAR TYPE default::inet EXTENDING std::bytes; + ALTER TYPE default::Song { + CREATE PROPERTY server_ip -> default::inet; + }; +}; diff --git a/priv/edgedb/schema/migrations/00006.edgeql b/priv/edgedb/schema/migrations/00006.edgeql new file mode 100644 index 00000000..d84fe1e3 --- /dev/null +++ b/priv/edgedb/schema/migrations/00006.edgeql @@ -0,0 +1,7 @@ +CREATE MIGRATION m1ibh7njtapjtc6qlcv2aw6gxrebw5zwvagpx6mlxplmq7nwpzo36a + ONTO m1hd7litg4ylc632kuyv3xqipk6bvjgcrbeoujgvoccts65yholkda +{ + ALTER TYPE default::User { + CREATE PROPERTY songs_count := (std::count(. std::int64 { + SET default := 0; + }; + }; +}; diff --git a/priv/edgedb/schema/migrations/00008.edgeql b/priv/edgedb/schema/migrations/00008.edgeql new file mode 100644 index 00000000..f9f5c704 --- /dev/null +++ b/priv/edgedb/schema/migrations/00008.edgeql @@ -0,0 +1,10 @@ +CREATE MIGRATION m1zvprfqkveu4mb4kou74xgiar2yt5abpnu5ntsqhki7lbeinjznbq + ONTO m13t5esb4neq5k7pwacj6izyxsvblyaf7e7x3hndvfutgbalz72qxa +{ + CREATE FUNCTION default::to_status(status: std::str) -> OPTIONAL default::SongStatus USING (WITH + status := + std::str_title(status) + SELECT + (status IF (status IN {'Stopped', 'Playing', 'Paused'}) ELSE {}) + ); +}; diff --git a/priv/edgedb/schema/migrations/00009.edgeql b/priv/edgedb/schema/migrations/00009.edgeql new file mode 100644 index 00000000..f201bc3b --- /dev/null +++ b/priv/edgedb/schema/migrations/00009.edgeql @@ -0,0 +1,9 @@ +CREATE MIGRATION m1ec7ytvgzhdpcmpjfdumfdypk56ceoiftstllef3fzr6k5bnfesta + ONTO m1zvprfqkveu4mb4kou74xgiar2yt5abpnu5ntsqhki7lbeinjznbq +{ + ALTER TYPE default::Song { + CREATE REQUIRED PROPERTY position -> std::int64 { + SET default := 0; + }; + }; +}; diff --git a/priv/edgedb/schema/migrations/00010.edgeql b/priv/edgedb/schema/migrations/00010.edgeql new file mode 100644 index 00000000..1322be07 --- /dev/null +++ b/priv/edgedb/schema/migrations/00010.edgeql @@ -0,0 +1,50 @@ +CREATE MIGRATION m1qcv5nieywf4bygcrna7cf7ygkdarqelwig6xnjwpzdfkktdfwh3q + ONTO m1ec7ytvgzhdpcmpjfdumfdypk56ceoiftstllef3fzr6k5bnfesta +{ + ALTER TYPE default::Identity { + ALTER PROPERTY inserted_at { + RENAME TO inserted_at_legacy; + }; + }; + ALTER TYPE default::Identity { + ALTER PROPERTY updated_at { + RENAME TO updated_at_legacy; + }; + }; + ALTER TYPE default::Song { + ALTER PROPERTY inserted_at { + RENAME TO inserted_at_legacy; + }; + }; + ALTER TYPE default::Song { + ALTER PROPERTY updated_at { + RENAME TO updated_at_legacy; + }; + }; + CREATE ABSTRACT TYPE default::Timestamped { + CREATE REQUIRED PROPERTY inserted_at: cal::local_datetime { + SET readonly := true; + CREATE REWRITE + INSERT + USING (cal::to_local_datetime(std::datetime_current(), 'UTC')); + }; + CREATE REQUIRED PROPERTY updated_at: cal::local_datetime { + CREATE REWRITE + INSERT + USING (cal::to_local_datetime(std::datetime_current(), 'UTC')); + CREATE REWRITE + UPDATE + USING (cal::to_local_datetime(std::datetime_current(), 'UTC')); + }; + }; + ALTER TYPE default::User { + ALTER PROPERTY inserted_at { + RENAME TO inserted_at_legacy; + }; + }; + ALTER TYPE default::User { + ALTER PROPERTY updated_at { + RENAME TO updated_at_legacy; + }; + }; +}; diff --git a/priv/edgedb/schema/migrations/00011.edgeql b/priv/edgedb/schema/migrations/00011.edgeql new file mode 100644 index 00000000..60b3667b --- /dev/null +++ b/priv/edgedb/schema/migrations/00011.edgeql @@ -0,0 +1,67 @@ +CREATE MIGRATION m1cyoreiep3r4h2dwl3pjujbjiyly67f55rbfqxnqkmdueffvxgcba + ONTO m1qcv5nieywf4bygcrna7cf7ygkdarqelwig6xnjwpzdfkktdfwh3q +{ + ALTER TYPE default::Identity { + CREATE PROPERTY inserted_at: cal::local_datetime { + SET REQUIRED USING (.inserted_at_legacy); + }; + CREATE PROPERTY updated_at: cal::local_datetime { + SET REQUIRED USING (.updated_at_legacy); + }; + EXTENDING default::Timestamped LAST; + }; + ALTER TYPE default::Identity { + ALTER PROPERTY inserted_at { + RESET OPTIONALITY; + DROP OWNED; + RESET TYPE; + }; + ALTER PROPERTY updated_at { + RESET OPTIONALITY; + DROP OWNED; + RESET TYPE; + }; + }; + ALTER TYPE default::Song { + CREATE PROPERTY inserted_at: cal::local_datetime { + SET REQUIRED USING (.inserted_at_legacy); + }; + CREATE PROPERTY updated_at: cal::local_datetime { + SET REQUIRED USING (.updated_at_legacy); + }; + EXTENDING default::Timestamped LAST; + }; + ALTER TYPE default::Song { + ALTER PROPERTY inserted_at { + RESET OPTIONALITY; + DROP OWNED; + RESET TYPE; + }; + ALTER PROPERTY updated_at { + RESET OPTIONALITY; + DROP OWNED; + RESET TYPE; + }; + }; + ALTER TYPE default::User { + CREATE PROPERTY inserted_at: cal::local_datetime { + SET REQUIRED USING (.inserted_at_legacy); + }; + CREATE PROPERTY updated_at: cal::local_datetime { + SET REQUIRED USING (.updated_at_legacy); + }; + EXTENDING default::Timestamped LAST; + }; + ALTER TYPE default::User { + ALTER PROPERTY inserted_at { + RESET OPTIONALITY; + DROP OWNED; + RESET TYPE; + }; + ALTER PROPERTY updated_at { + RESET OPTIONALITY; + DROP OWNED; + RESET TYPE; + }; + }; +}; diff --git a/priv/edgedb/schema/migrations/00012.edgeql b/priv/edgedb/schema/migrations/00012.edgeql new file mode 100644 index 00000000..6117b216 --- /dev/null +++ b/priv/edgedb/schema/migrations/00012.edgeql @@ -0,0 +1,16 @@ +CREATE MIGRATION m1z5zo6o4ommezfxgcgne2i5o5djt5wrso5qqatzc3rwont43wzyua + ONTO m1cyoreiep3r4h2dwl3pjujbjiyly67f55rbfqxnqkmdueffvxgcba +{ + ALTER TYPE default::Identity { + DROP PROPERTY inserted_at_legacy; + DROP PROPERTY updated_at_legacy; + }; + ALTER TYPE default::Song { + DROP PROPERTY inserted_at_legacy; + DROP PROPERTY updated_at_legacy; + }; + ALTER TYPE default::User { + DROP PROPERTY inserted_at_legacy; + DROP PROPERTY updated_at_legacy; + }; +}; diff --git a/priv/edgedb/schema/migrations/00013.edgeql b/priv/edgedb/schema/migrations/00013.edgeql new file mode 100644 index 00000000..a3b5ca74 --- /dev/null +++ b/priv/edgedb/schema/migrations/00013.edgeql @@ -0,0 +1,24 @@ +CREATE MIGRATION m1it7pwkmkmpv26wjsb7meak75pa7pex2j6mya7yozolbmincbgcza + ONTO m1z5zo6o4ommezfxgcgne2i5o5djt5wrso5qqatzc3rwont43wzyua +{ + ALTER TYPE default::User { + DROP PROPERTY confirmed_at; + ALTER PROPERTY email { + CREATE CONSTRAINT std::max_len_value(160); + CREATE CONSTRAINT std::regexp(r'^[^\s]+@[^\s]+$'); + CREATE REWRITE + INSERT + USING (std::str_lower(__subject__.email)); + CREATE REWRITE + UPDATE + USING (std::str_lower(__subject__.email)); + }; + ALTER PROPERTY name { + SET REQUIRED USING (.username); + }; + DROP PROPERTY role; + ALTER PROPERTY username { + CREATE CONSTRAINT std::exclusive; + }; + }; +}; diff --git a/priv/edgedb/schema/migrations/00014.edgeql b/priv/edgedb/schema/migrations/00014.edgeql new file mode 100644 index 00000000..dfc1a89b --- /dev/null +++ b/priv/edgedb/schema/migrations/00014.edgeql @@ -0,0 +1,15 @@ +CREATE MIGRATION m1okgh4wtvnuxdcf7b65cbx6okhb3twpxdkppoc6lv5zotvhcn5ika + ONTO m1it7pwkmkmpv26wjsb7meak75pa7pex2j6mya7yozolbmincbgcza +{ + ALTER TYPE default::Identity { + ALTER PROPERTY provider_email { + SET TYPE default::cistr; + CREATE REWRITE + INSERT + USING (std::str_lower(__subject__.provider_email)); + CREATE REWRITE + UPDATE + USING (std::str_lower(__subject__.provider_email)); + }; + }; +}; diff --git a/priv/edgedb/schema/migrations/00015.edgeql b/priv/edgedb/schema/migrations/00015.edgeql new file mode 100644 index 00000000..7fda3543 --- /dev/null +++ b/priv/edgedb/schema/migrations/00015.edgeql @@ -0,0 +1,16 @@ +CREATE MIGRATION m1ta2vukbkhirlahnlekib6cdudqzlol6wu5aztvowsg5skarqmh5a + ONTO m1okgh4wtvnuxdcf7b65cbx6okhb3twpxdkppoc6lv5zotvhcn5ika +{ + DROP FUNCTION default::to_status(status: std::str); + ALTER TYPE default::Song { + DROP INDEX ON (.status); + DROP PROPERTY status; + }; + ALTER SCALAR TYPE default::SongStatus EXTENDING enum; + ALTER TYPE default::Song { + CREATE REQUIRED PROPERTY status: default::SongStatus { + SET default := (default::SongStatus.stopped); + }; + CREATE INDEX ON (.status); + }; +}; diff --git a/priv/edgedb/schema/migrations/00016.edgeql b/priv/edgedb/schema/migrations/00016.edgeql new file mode 100644 index 00000000..724335c7 --- /dev/null +++ b/priv/edgedb/schema/migrations/00016.edgeql @@ -0,0 +1,12 @@ +CREATE MIGRATION m1cf555gemqtjglvd5sthjsrnjrdecxkdeyrd3wpbkpvozjeovxyxq + ONTO m1ta2vukbkhirlahnlekib6cdudqzlol6wu5aztvowsg5skarqmh5a +{ + ALTER TYPE default::Genre { + DROP PROPERTY slug; + DROP PROPERTY title; + }; + ALTER TYPE default::Song { + DROP LINK genre; + }; + DROP TYPE default::Genre; +}; diff --git a/priv/edgedb/schema/migrations/00017.edgeql b/priv/edgedb/schema/migrations/00017.edgeql new file mode 100644 index 00000000..ea5c179a --- /dev/null +++ b/priv/edgedb/schema/migrations/00017.edgeql @@ -0,0 +1,31 @@ +CREATE MIGRATION m1bex2l6siwpxeifsgdqah5p2uh2shovtwuyd5fifvfofdafnkl6ja + ONTO m1cf555gemqtjglvd5sthjsrnjrdecxkdeyrd3wpbkpvozjeovxyxq +{ + CREATE TYPE default::MP3 { + CREATE REQUIRED PROPERTY filename: std::str; + CREATE REQUIRED PROPERTY filepath: std::str; + CREATE REQUIRED PROPERTY filesize: cfg::memory { + SET default := (0); + }; + CREATE REQUIRED PROPERTY url: std::str; + }; + ALTER TYPE default::Song { + CREATE REQUIRED LINK mp3: default::MP3 { + ON SOURCE DELETE DELETE TARGET; + SET REQUIRED USING ((INSERT + default::MP3 + { + url := default::Song.mp3_url, + filename := default::Song.mp3_filename, + filepath := default::Song.mp3_filepath, + filesize := default::Song.mp3_filesize + })); + }; + }; + ALTER TYPE default::Song { + DROP PROPERTY mp3_filename; + DROP PROPERTY mp3_filepath; + DROP PROPERTY mp3_filesize; + DROP PROPERTY mp3_url; + }; +}; diff --git a/priv/edgedb/schema/migrations/00018.edgeql b/priv/edgedb/schema/migrations/00018.edgeql new file mode 100644 index 00000000..31171719 --- /dev/null +++ b/priv/edgedb/schema/migrations/00018.edgeql @@ -0,0 +1,10 @@ +CREATE MIGRATION m12w3z4oofn5dke5mw3oirfpgbfyhi5lweuklpzb4xrybtxq3oqoeq + ONTO m1bex2l6siwpxeifsgdqah5p2uh2shovtwuyd5fifvfofdafnkl6ja +{ + ALTER TYPE default::Song { + ALTER PROPERTY duration { + SET default := ('0 seconds'); + SET TYPE std::duration USING ((std::to_str(.duration) ++ ' seconds')); + }; + }; +}; diff --git a/priv/edgedb/schema/migrations/00019.edgeql b/priv/edgedb/schema/migrations/00019.edgeql new file mode 100644 index 00000000..cfbb97ea --- /dev/null +++ b/priv/edgedb/schema/migrations/00019.edgeql @@ -0,0 +1,17 @@ +CREATE MIGRATION m16cque5xr6zlbwpuvvxwhvjbuztypf4n6yqxke6z4hqtwwool4zva + ONTO m12w3z4oofn5dke5mw3oirfpgbfyhi5lweuklpzb4xrybtxq3oqoeq +{ + ALTER TYPE default::Song { + DROP PROPERTY album_artist; + ALTER PROPERTY paused_at { + CREATE REWRITE + UPDATE + USING ((std::datetime_current() IF (__subject__.status = default::SongStatus.stopped) ELSE __old__.played_at)); + }; + ALTER PROPERTY played_at { + CREATE REWRITE + UPDATE + USING ((std::datetime_current() IF (__subject__.status = default::SongStatus.playing) ELSE __old__.played_at)); + }; + }; +}; diff --git a/priv/edgedb/schema/migrations/00020.edgeql b/priv/edgedb/schema/migrations/00020.edgeql new file mode 100644 index 00000000..4efd6976 --- /dev/null +++ b/priv/edgedb/schema/migrations/00020.edgeql @@ -0,0 +1,39 @@ +CREATE MIGRATION m123g7cikfwawoirtb6cxdywwfyh3x4r6bcyqmrl3eoaod4g5ifqnq + ONTO m16cque5xr6zlbwpuvvxwhvjbuztypf4n6yqxke6z4hqtwwool4zva +{ + CREATE GLOBAL default::current_user_id -> std::uuid; + CREATE GLOBAL default::current_user := (SELECT + default::User + FILTER + (.id = GLOBAL default::current_user_id) + ); + ALTER TYPE default::Identity { + CREATE ACCESS POLICY owner_can_do_everything + ALLOW ALL USING (((GLOBAL default::current_user).id ?= .user.id)); + CREATE ACCESS POLICY anyone_can_create + ALLOW INSERT ; + }; + ALTER TYPE default::Song { + CREATE ACCESS POLICY owner_can_do_everything + ALLOW ALL USING (((GLOBAL default::current_user).id ?= .user.id)); + }; + ALTER TYPE default::User { + CREATE ACCESS POLICY owner_can_do_everything + ALLOW ALL USING (((GLOBAL default::current_user).id ?= .id)); + CREATE ACCESS POLICY anyone_can_read_or_create + ALLOW SELECT, INSERT ; + }; + CREATE REQUIRED GLOBAL default::max_songs_count := (30); + ALTER TYPE default::Song { + CREATE TRIGGER ensure_user_songs_count_not_exceeded + AFTER UPDATE, INSERT + FOR EACH DO (std::assert((__new__.user.songs_count <= GLOBAL default::max_songs_count), message := 'Songs limit exceeded')); + }; + CREATE GLOBAL default::is_admin -> std::bool; + ALTER TYPE default::Song { + CREATE ACCESS POLICY admin_can_do_everything + ALLOW ALL USING ((GLOBAL default::is_admin ?= true)); + CREATE ACCESS POLICY anyone_can_read + ALLOW SELECT ; + }; +}; From 1e12527d7b34355ef9880c8ce5f3ad85886463f8 Mon Sep 17 00:00:00 2001 From: Devi Prasad Date: Tue, 26 Sep 2023 10:45:55 -0500 Subject: [PATCH 03/15] feat: schema transformation (non optimized) --- lib/edgedb/edgeql/generator.ex | 7 +-- priv/codegen/templates/_object.eex | 10 ++--- priv/codegen/templates/_schema.eex | 10 ++--- priv/codegen/templates/_shape.eex | 3 +- priv/codegen/templates/query.ex.eex | 9 +--- .../get_current_active_song.edgeql.ex | 44 +++++++++++-------- 6 files changed, 40 insertions(+), 43 deletions(-) diff --git a/lib/edgedb/edgeql/generator.ex b/lib/edgedb/edgeql/generator.ex index cab2dca0..437afed5 100644 --- a/lib/edgedb/edgeql/generator.ex +++ b/lib/edgedb/edgeql/generator.ex @@ -182,15 +182,15 @@ defmodule EdgeDB.EdgeQL.Generator do render_shape: &render_shape/1, render_builtin: &render_builtin/1, render_object: &render_object/1, - render_set: &render_set/1, - camelize: &Macro.camelize/1 + render_set: &render_set/1 ) rendered_schema = if raw_schema do render_schema( schema: raw_schema, - render_schema: &render_schema/1 + render_schema: &render_schema/1, + paths: [] ) else nil @@ -209,6 +209,7 @@ defmodule EdgeDB.EdgeQL.Generator do 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 } ) diff --git a/priv/codegen/templates/_object.eex b/priv/codegen/templates/_object.eex index 6f8ec2a0..4d7945d1 100644 --- a/priv/codegen/templates/_object.eex +++ b/priv/codegen/templates/_object.eex @@ -1,14 +1,13 @@ <%= for {name, field} <- @object.fields do %> <%= case field do %> <% %{type: :object} -> %> - defmodule <%= @camelize.(name) %> do + 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, - camelize: @camelize + render_set: @render_set ) %> end; <% _ -> %> @@ -26,7 +25,7 @@ defstruct [ <%= for {name, field} <- @object.fields do %> <%= case field do %> <% %{type: :object} -> %> - <%= name %>: <%= @camelize.(name) %>.t() + <%= name %>: <%= Macro.camelize(name) %>.t() <%= if field[:is_optional] do %>| nil<% end %>, <% _ -> %> @@ -41,8 +40,7 @@ defstruct [ render_shape: @render_shape, render_builtin: @render_builtin, render_object: @render_object, - render_set: @render_set, - camelize: @camelize + render_set: @render_set ) %>, <% end %> <% end %> diff --git a/priv/codegen/templates/_schema.eex b/priv/codegen/templates/_schema.eex index f53bba2e..79159dfa 100644 --- a/priv/codegen/templates/_schema.eex +++ b/priv/codegen/templates/_schema.eex @@ -1,11 +1,11 @@ -[ +{ <%= for type <- @schema do %> <%= case type do %> <% {name, schema} -> %> - <%= name %>: <%= @render_schema.(schema: schema, render_schema: @render_schema) %>, - + <%= name %>: %Result.<%= Macro.camelize(name) %> + <%= @render_schema.(schema: schema, render_schema: @render_schema, paths: @paths ++ [name]) %>, <% name -> %> - :<%= name %>, + <%= name %>: result<%= Enum.map_join(@paths, &("[\"#{&1}\"]")) %>["<%= name %>"], <% end %> <% end %> -] +} diff --git a/priv/codegen/templates/_shape.eex b/priv/codegen/templates/_shape.eex index d9ca2700..c3a9bef1 100644 --- a/priv/codegen/templates/_shape.eex +++ b/priv/codegen/templates/_shape.eex @@ -12,8 +12,7 @@ render_shape: @render_shape, render_builtin: @render_builtin, render_object: @render_object, - render_set: @render_set, - camelize: @camelize + render_set: @render_set ) %> <% %{type: :set} = set -> %> diff --git a/priv/codegen/templates/query.ex.eex b/priv/codegen/templates/query.ex.eex index 8e21f89b..e76c490f 100644 --- a/priv/codegen/templates/query.ex.eex +++ b/priv/codegen/templates/query.ex.eex @@ -151,15 +151,8 @@ defmodule <%= @module_name %> do <% end %> - <%= if not is_nil(@schema) do %> - @schema <%= @schema %> defp do_query(client, args, opts) do - opts = Keyword.merge(opts, __transform_result__: [schema: @schema]) EdgeDB.<%= @query_function %>(client, @query, args, opts) + shape = %Result<%= @schema %> end - <% else %> - defp do_query(client, args, opts) do - EdgeDB.<%= @query_function %>(client, @query, args, opts) - end - <% end %> end diff --git a/priv/edgedb/codegen/queries/media_library/get_current_active_song.edgeql.ex b/priv/edgedb/codegen/queries/media_library/get_current_active_song.edgeql.ex index 3403c46e..0d920411 100644 --- a/priv/edgedb/codegen/queries/media_library/get_current_active_song.edgeql.ex +++ b/priv/edgedb/codegen/queries/media_library/get_current_active_song.edgeql.ex @@ -158,26 +158,32 @@ defmodule Tests.Codegen.Queries.MediaLibrary.GetCurrentActiveSong do end end - @schema [ - :updated_at, - :title, - :status, - :server_ip, - :position, - :played_at, - :paused_at, - :inserted_at, - :id, - :duration, - :date_released, - :date_recorded, - :attribution, - :artist, - user: [:id], - mp3: [:url, :id, :filesize, :filepath, :filename] - ] defp do_query(client, args, opts) do - opts = Keyword.merge(opts, __transform_result__: [schema: @schema]) EdgeDB.query_single(client, @query, args, opts) + + shape = %Result{ + updated_at: result["updated_at"], + title: result["title"], + status: result["status"], + server_ip: result["server_ip"], + position: result["position"], + played_at: result["played_at"], + paused_at: result["paused_at"], + inserted_at: result["inserted_at"], + id: result["id"], + duration: result["duration"], + date_released: result["date_released"], + date_recorded: result["date_recorded"], + attribution: result["attribution"], + artist: result["artist"], + user: %Result.User{id: result["user"]["id"]}, + mp3: %Result.Mp3{ + url: result["mp3"]["url"], + id: result["mp3"]["id"], + filesize: result["mp3"]["filesize"], + filepath: result["mp3"]["filepath"], + filename: result["mp3"]["filename"] + } + } end end From 207b846604b9c4fdb6b21af82019f45910df10c8 Mon Sep 17 00:00:00 2001 From: Nik Sidnev Date: Tue, 26 Sep 2023 12:24:42 -0400 Subject: [PATCH 04/15] fix credo warnings --- .credo.exs | 8 +++++++- test/codegen/codegen_test.exs | 4 +++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/.credo.exs b/.credo.exs index 2f5a369f..faea0351 100644 --- a/.credo.exs +++ b/.credo.exs @@ -31,7 +31,13 @@ "apps/*/test/", "apps/*/web/" ], - excluded: [~r"/_build/", ~r"/deps/", ~r"/node_modules/", ~r"/test/*/codegen/"] + excluded: [ + ~r"/_build/", + ~r"/deps/", + ~r"/node_modules/", + ~r"/test/codegen/queries/", + ~r"/test/support/scripts/" + ] }, # # Load and configure plugins here: diff --git a/test/codegen/codegen_test.exs b/test/codegen/codegen_test.exs index 3f2c0b11..b8ca10f1 100644 --- a/test/codegen/codegen_test.exs +++ b/test/codegen/codegen_test.exs @@ -1,6 +1,8 @@ defmodule Tests.CodegenTest do use Tests.Support.EdgeDBCase + alias Tests.Codegen.Queries.Standart.SelectStartartTypesNamedSimple + @queries_path Application.compile_env!(:edgedb, :generation)[:queries_path] queries = @@ -38,7 +40,7 @@ defmodule Tests.CodegenTest do e: ^e, f: ^f } = - Tests.Codegen.Queries.Standart.SelectStartartTypesNamedSimple.query!(client, + SelectStartartTypesNamedSimple.query!(client, e: e, f: f ) From 62302f9f2d6cb96afaa2f712edc349f64fd6c265 Mon Sep 17 00:00:00 2001 From: Devi Prasad Date: Wed, 27 Sep 2023 00:44:45 -0500 Subject: [PATCH 05/15] feat-wip: do_query --- lib/edgedb/edgeql/generator.ex | 20 +- priv/codegen/templates/_builtin.eex | 2 + priv/codegen/templates/_object.eex | 51 ++--- priv/codegen/templates/_schema.eex | 13 +- priv/codegen/templates/_shape.eex | 12 -- priv/codegen/templates/query.ex.eex | 32 ++- .../get_current_active_song.edgeql.ex | 52 ++--- .../list_active_profiles.edgeql.ex | 190 ++++++++++++++++++ .../media_library/pause_song.edgeql.ex | 77 +++++++ .../queries/select_string_from_root.edgeql.ex | 56 ++++++ .../media_library/list_active_profiles.edgeql | 16 ++ .../edgeql/media_library/pause_song.edgeql | 5 + .../edgeql/select_string_from_root.edgeql | 1 + 13 files changed, 461 insertions(+), 66 deletions(-) create mode 100644 priv/edgedb/codegen/queries/media_library/list_active_profiles.edgeql.ex create mode 100644 priv/edgedb/codegen/queries/media_library/pause_song.edgeql.ex create mode 100644 priv/edgedb/codegen/queries/select_string_from_root.edgeql.ex create mode 100644 priv/edgedb/edgeql/media_library/list_active_profiles.edgeql create mode 100644 priv/edgedb/edgeql/media_library/pause_song.edgeql create mode 100644 priv/edgedb/edgeql/select_string_from_root.edgeql diff --git a/lib/edgedb/edgeql/generator.ex b/lib/edgedb/edgeql/generator.ex index 437afed5..a48740db 100644 --- a/lib/edgedb/edgeql/generator.ex +++ b/lib/edgedb/edgeql/generator.ex @@ -175,6 +175,7 @@ defmodule EdgeDB.EdgeQL.Generator do {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) rendered_shape = render_shape( @@ -203,8 +204,9 @@ defmodule EdgeDB.EdgeQL.Generator do types: types(), shape: rendered_shape, schema: rendered_schema, - query_function: @cardinality_to_function[query.result_cardinality], - result_type: "Result.t()", + should_render_type_for_shape: rendered_schema && complex, + cardinality_to_function: @cardinality_to_function, + result_type: (complex && "Result.t()") || rendered_shape, query: %{ statement: query.statement, has_positional_args: positional? and length(args) != 0, @@ -432,6 +434,18 @@ defmodule EdgeDB.EdgeQL.Generator do "#{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 @@ -487,7 +501,7 @@ defmodule EdgeDB.EdgeQL.Generator do nil schema -> - schema + [:builtin, schema] end end diff --git a/priv/codegen/templates/_builtin.eex b/priv/codegen/templates/_builtin.eex index 2b3575d8..6d8df055 100644 --- a/priv/codegen/templates/_builtin.eex +++ b/priv/codegen/templates/_builtin.eex @@ -1,4 +1,6 @@ +<%= if @builtin[:is_list] do %>list(<% 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 index 4d7945d1..f1cbd225 100644 --- a/priv/codegen/templates/_object.eex +++ b/priv/codegen/templates/_object.eex @@ -1,41 +1,46 @@ <%= 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 - ) %> - end; - <% _ -> %> - <% false %> + <% %{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 + ) %> + end; + <% %{type: :set} -> %> + defmodule <%= Macro.camelize(name) %> do + <%= @render_set.( + set: field, + render_shape: @render_shape, + render_builtin: @render_builtin, + render_object: @render_object, + render_set: @render_set + ) %> + end; + <% _ -> %> + <% false %> <% end %> <% end %> defstruct [ <%= for {name, _} <- @object.fields do %> - :<%= name %>, + :<%= name %>, <% end %> ]; @type t() :: %__MODULE__{ <%= for {name, field} <- @object.fields do %> <%= case field do %> - <% %{type: :object} -> %> - <%= name %>: <%= Macro.camelize(name) %>.t() - <%= if field[:is_optional] do %>| nil<% end %>, + <% %{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 %>, <% _ -> %> - <%= if field[:is_link_property] do %> - "@<%= name %>": - <% else %> - <%= name %>: - <% end %> - - <%= @render_shape.( + <%= name %>: <%= @render_shape.( shape: field, render_shape: @render_shape, render_builtin: @render_builtin, diff --git a/priv/codegen/templates/_schema.eex b/priv/codegen/templates/_schema.eex index 79159dfa..e8b422ad 100644 --- a/priv/codegen/templates/_schema.eex +++ b/priv/codegen/templates/_schema.eex @@ -1,9 +1,18 @@ { <%= 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.<%= Macro.camelize(name) %> - <%= @render_schema.(schema: schema, render_schema: @render_schema, paths: @paths ++ [name]) %>, + <%= name %>: %Result.<%= Macro.camelize(name) %><%= @render_schema.( + schema: schema, + render_schema: @render_schema, + paths: @paths ++ [name]) + %>, <% name -> %> <%= name %>: result<%= Enum.map_join(@paths, &("[\"#{&1}\"]")) %>["<%= name %>"], <% end %> diff --git a/priv/codegen/templates/_shape.eex b/priv/codegen/templates/_shape.eex index c3a9bef1..792548e9 100644 --- a/priv/codegen/templates/_shape.eex +++ b/priv/codegen/templates/_shape.eex @@ -1,7 +1,3 @@ -<%= if @shape[:is_list] do %> -[ -<% end %> - <%= case @shape do %> <% %{type: :builtin} = builtin -> %> <%= @render_builtin.(builtin: builtin) %> @@ -24,11 +20,3 @@ render_set: @render_set ) %> <% end %> - -<%= if @shape[:is_list] do %> -] - -<%= if @shape[:is_optional] do %> -| nil -<% end %> -<% end %> diff --git a/priv/codegen/templates/query.ex.eex b/priv/codegen/templates/query.ex.eex index e76c490f..023bd535 100644 --- a/priv/codegen/templates/query.ex.eex +++ b/priv/codegen/templates/query.ex.eex @@ -26,9 +26,11 @@ defmodule <%= @module_name %> do @type <%= type_name %> :: <%= typespec %> <% end %> + <%= if @should_render_type_for_shape do %> defmodule Result do <%= @shape %> end + <% end %> <%= if @query.has_positional_args do %> @@ -152,7 +154,35 @@ defmodule <%= @module_name %> do <% end %> defp do_query(client, args, opts) do - EdgeDB.<%= @query_function %>(client, @query, args, opts) + <%= 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 + case result do + [] -> nil + _ -> Enum.map(results, fn result -> + <% end %> + + <%= if @should_render_type_for_shape do %> shape = %Result<%= @schema %> + + {:ok, shape} + <% else %> + {:ok, result} + <% end %> + + <%= if @query.cardinality in [:at_least_one, :many] do %> + end); + end; + <% end %> + end end end diff --git a/priv/edgedb/codegen/queries/media_library/get_current_active_song.edgeql.ex b/priv/edgedb/codegen/queries/media_library/get_current_active_song.edgeql.ex index 0d920411..88e99ccc 100644 --- a/priv/edgedb/codegen/queries/media_library/get_current_active_song.edgeql.ex +++ b/priv/edgedb/codegen/queries/media_library/get_current_active_song.edgeql.ex @@ -159,31 +159,33 @@ defmodule Tests.Codegen.Queries.MediaLibrary.GetCurrentActiveSong do end defp do_query(client, args, opts) do - EdgeDB.query_single(client, @query, args, opts) - - shape = %Result{ - updated_at: result["updated_at"], - title: result["title"], - status: result["status"], - server_ip: result["server_ip"], - position: result["position"], - played_at: result["played_at"], - paused_at: result["paused_at"], - inserted_at: result["inserted_at"], - id: result["id"], - duration: result["duration"], - date_released: result["date_released"], - date_recorded: result["date_recorded"], - attribution: result["attribution"], - artist: result["artist"], - user: %Result.User{id: result["user"]["id"]}, - mp3: %Result.Mp3{ - url: result["mp3"]["url"], - id: result["mp3"]["id"], - filesize: result["mp3"]["filesize"], - filepath: result["mp3"]["filepath"], - filename: result["mp3"]["filename"] + with {:ok, result} when not is_nil(result) <- EdgeDB.query_single(client, @query, args, opts) do + shape = %Result{ + updated_at: result["updated_at"], + title: result["title"], + status: result["status"], + server_ip: result["server_ip"], + position: result["position"], + played_at: result["played_at"], + paused_at: result["paused_at"], + inserted_at: result["inserted_at"], + id: result["id"], + duration: result["duration"], + date_released: result["date_released"], + date_recorded: result["date_recorded"], + attribution: result["attribution"], + artist: result["artist"], + user: %Result.User{id: result["user"]["id"]}, + mp3: %Result.Mp3{ + url: result["mp3"]["url"], + id: result["mp3"]["id"], + filesize: result["mp3"]["filesize"], + filepath: result["mp3"]["filepath"], + filename: result["mp3"]["filename"] + } } - } + + {:ok, shape} + end end end diff --git a/priv/edgedb/codegen/queries/media_library/list_active_profiles.edgeql.ex b/priv/edgedb/codegen/queries/media_library/list_active_profiles.edgeql.ex new file mode 100644 index 00000000..10cd364a --- /dev/null +++ b/priv/edgedb/codegen/queries/media_library/list_active_profiles.edgeql.ex @@ -0,0 +1,190 @@ +# AUTOGENERATED: DO NOT MODIFY +# Generated by Elixir client for EdgeDB via `mix edgedb.generate` from +# `priv/edgedb/edgeql/media_library/list_active_profiles.edgeql`. +defmodule Tests.Codegen.Queries.MediaLibrary.ListActiveProfiles do + @query """ + with songs := ( + select Song + filter .status = SongStatus.playing + order by .updated_at desc + ) + select songs.user { + id, + username, + profile_tagline, + avatar_url, + external_homepage_url, + ss := (select Song {*} + filter .status = SongStatus.playing + order by .updated_at desc) + } + limit $limit + """ + + @moduledoc """ + Generated module for the EdgeQL query from + `priv/edgedb/edgeql/media_library/list_active_profiles.edgeql`. + + Query: + + ```edgeql + #{@query} + ``` + """ + + @typedoc """ + ```edgeql + std::uuid + ``` + """ + @type uuid() :: binary() + + @typedoc """ + ```edgeql + std::duration + ``` + """ + @type duration() :: Timex.Duration.t() | integer() + + @typedoc """ + ```edgeql + scalar type default::SongStatus extending enum + ``` + """ + @type default__song_status() :: String.t() | :stopped | :playing | :paused + + @typedoc """ + ```edgeql + scalar type default::inet extending std::bytes + ``` + """ + @type default__inet() :: bitstring() + + defmodule Result do + defmodule Ss do + defstruct [ + :artist, + :title, + :attribution, + :date_recorded, + :date_released, + :paused_at, + :played_at, + :server_ip, + :position, + :id, + :inserted_at, + :updated_at, + :status, + :duration + ] + + @type t() :: %__MODULE__{ + artist: String.t(), + title: String.t(), + attribution: String.t() | nil, + date_recorded: NaiveDateTime.t() | nil, + date_released: NaiveDateTime.t() | nil, + paused_at: DateTime.t() | nil, + played_at: DateTime.t() | nil, + server_ip: default__inet() | nil, + position: integer(), + id: uuid(), + inserted_at: NaiveDateTime.t(), + updated_at: NaiveDateTime.t(), + status: default__song_status(), + duration: duration() + } + end + + defstruct [:id, :username, :profile_tagline, :avatar_url, :external_homepage_url, :ss] + + @type t() :: %__MODULE__{ + id: uuid(), + username: String.t(), + profile_tagline: String.t() | nil, + avatar_url: String.t() | nil, + external_homepage_url: String.t() | nil, + ss: list(Ss.t()) + } + end + + @type keyword_args() :: [{:limit, integer()}] + + @type map_args() :: %{ + limit: 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.t()} + | {: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.t() + 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 + with {:ok, results} <- EdgeDB.query(client, @query, args, opts) do + case result do + [] -> + nil + + _ -> + Enum.map(results, fn result -> + shape = %Result{ + username: result["username"], + profile_tagline: result["profile_tagline"], + id: result["id"], + external_homepage_url: result["external_homepage_url"], + avatar_url: result["avatar_url"], + ss: %Result.Ss{ + updated_at: result["ss"]["updated_at"], + title: result["ss"]["title"], + status: result["ss"]["status"], + server_ip: result["ss"]["server_ip"], + position: result["ss"]["position"], + played_at: result["ss"]["played_at"], + paused_at: result["ss"]["paused_at"], + inserted_at: result["ss"]["inserted_at"], + id: result["ss"]["id"], + duration: result["ss"]["duration"], + date_released: result["ss"]["date_released"], + date_recorded: result["ss"]["date_recorded"], + attribution: result["ss"]["attribution"], + artist: result["ss"]["artist"] + } + } + + {:ok, shape} + end) + end + end + end +end diff --git a/priv/edgedb/codegen/queries/media_library/pause_song.edgeql.ex b/priv/edgedb/codegen/queries/media_library/pause_song.edgeql.ex new file mode 100644 index 00000000..add0c370 --- /dev/null +++ b/priv/edgedb/codegen/queries/media_library/pause_song.edgeql.ex @@ -0,0 +1,77 @@ +# AUTOGENERATED: DO NOT MODIFY +# Generated by Elixir client for EdgeDB via `mix edgedb.generate` from +# `priv/edgedb/edgeql/media_library/pause_song.edgeql`. +defmodule Tests.Codegen.Queries.MediaLibrary.PauseSong do + @query """ + update Song + filter .id = $song_id + set { + status := SongStatus.paused + } + """ + + @moduledoc """ + Generated module for the EdgeQL query from + `priv/edgedb/edgeql/media_library/pause_song.edgeql`. + + Query: + + ```edgeql + #{@query} + ``` + """ + + @typedoc """ + ```edgeql + std::uuid + ``` + """ + @type uuid() :: binary() + + @type keyword_args() :: [{:song_id, uuid()}] + + @type map_args() :: %{ + song_id: 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.t()} + | {: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.t() + 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 + with {:ok, result} when not is_nil(result) <- EdgeDB.query_single(client, @query, args, opts) do + {:ok, result} + end + end +end diff --git a/priv/edgedb/codegen/queries/select_string_from_root.edgeql.ex b/priv/edgedb/codegen/queries/select_string_from_root.edgeql.ex new file mode 100644 index 00000000..6be18ddf --- /dev/null +++ b/priv/edgedb/codegen/queries/select_string_from_root.edgeql.ex @@ -0,0 +1,56 @@ +# AUTOGENERATED: DO NOT MODIFY +# Generated by Elixir client for EdgeDB via `mix edgedb.generate` from +# `priv/edgedb/edgeql/select_string_from_root.edgeql`. +defmodule Tests.Codegen.Queries.SelectStringFromRoot do + @query """ + select 'Hello world!' + """ + + @moduledoc """ + Generated module for the EdgeQL query from + `priv/edgedb/edgeql/select_string_from_root.edgeql`. + + Query: + + ```edgeql + #{@query} + ``` + """ + + @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 + with {:ok, result} <- EdgeDB.query_required_single(client, @query, args, opts) do + {:ok, result} + end + end +end diff --git a/priv/edgedb/edgeql/media_library/list_active_profiles.edgeql b/priv/edgedb/edgeql/media_library/list_active_profiles.edgeql new file mode 100644 index 00000000..fa9b8dcb --- /dev/null +++ b/priv/edgedb/edgeql/media_library/list_active_profiles.edgeql @@ -0,0 +1,16 @@ +with songs := ( + select Song + filter .status = SongStatus.playing + order by .updated_at desc +) +select songs.user { + id, + username, + profile_tagline, + avatar_url, + external_homepage_url, + ss := (select Song {*} + filter .status = SongStatus.playing + order by .updated_at desc) +} +limit $limit diff --git a/priv/edgedb/edgeql/media_library/pause_song.edgeql b/priv/edgedb/edgeql/media_library/pause_song.edgeql new file mode 100644 index 00000000..dbf75130 --- /dev/null +++ b/priv/edgedb/edgeql/media_library/pause_song.edgeql @@ -0,0 +1,5 @@ +update Song + filter .id = $song_id + set { + status := SongStatus.paused + } \ No newline at end of file diff --git a/priv/edgedb/edgeql/select_string_from_root.edgeql b/priv/edgedb/edgeql/select_string_from_root.edgeql new file mode 100644 index 00000000..d0f78cf5 --- /dev/null +++ b/priv/edgedb/edgeql/select_string_from_root.edgeql @@ -0,0 +1 @@ +select 'Hello world!' From 0b19e660e4e0aab432aff0428ac4f86b1535d172 Mon Sep 17 00:00:00 2001 From: Devi Prasad Date: Wed, 27 Sep 2023 00:59:57 -0500 Subject: [PATCH 06/15] chore: clean up and bring to sync --- config/config.exs | 20 +- edgedb.toml | 4 +- .../get_current_active_song.edgeql.ex | 191 ------------------ .../list_active_profiles.edgeql.ex | 190 ----------------- .../media_library/pause_song.edgeql.ex | 77 ------- .../queries/select_string_from_root.edgeql.ex | 56 ----- .../get_current_active_song.edgeql | 14 -- .../media_library/list_active_profiles.edgeql | 16 -- .../edgeql/media_library/pause_song.edgeql | 5 - .../edgeql/select_string_from_root.edgeql | 1 - priv/edgedb/schema/default.esdl | 171 ---------------- priv/edgedb/schema/migrations/00001.edgeql | 47 ----- priv/edgedb/schema/migrations/00002.edgeql | 12 -- priv/edgedb/schema/migrations/00003.edgeql | 38 ---- priv/edgedb/schema/migrations/00004.edgeql | 8 - priv/edgedb/schema/migrations/00005.edgeql | 8 - priv/edgedb/schema/migrations/00006.edgeql | 7 - priv/edgedb/schema/migrations/00007.edgeql | 9 - priv/edgedb/schema/migrations/00008.edgeql | 10 - priv/edgedb/schema/migrations/00009.edgeql | 9 - priv/edgedb/schema/migrations/00010.edgeql | 50 ----- priv/edgedb/schema/migrations/00011.edgeql | 67 ------ priv/edgedb/schema/migrations/00012.edgeql | 16 -- priv/edgedb/schema/migrations/00013.edgeql | 24 --- priv/edgedb/schema/migrations/00014.edgeql | 15 -- priv/edgedb/schema/migrations/00015.edgeql | 16 -- priv/edgedb/schema/migrations/00016.edgeql | 12 -- priv/edgedb/schema/migrations/00017.edgeql | 31 --- priv/edgedb/schema/migrations/00018.edgeql | 10 - priv/edgedb/schema/migrations/00019.edgeql | 17 -- priv/edgedb/schema/migrations/00020.edgeql | 39 ---- 31 files changed, 12 insertions(+), 1178 deletions(-) delete mode 100644 priv/edgedb/codegen/queries/media_library/get_current_active_song.edgeql.ex delete mode 100644 priv/edgedb/codegen/queries/media_library/list_active_profiles.edgeql.ex delete mode 100644 priv/edgedb/codegen/queries/media_library/pause_song.edgeql.ex delete mode 100644 priv/edgedb/codegen/queries/select_string_from_root.edgeql.ex delete mode 100644 priv/edgedb/edgeql/media_library/get_current_active_song.edgeql delete mode 100644 priv/edgedb/edgeql/media_library/list_active_profiles.edgeql delete mode 100644 priv/edgedb/edgeql/media_library/pause_song.edgeql delete mode 100644 priv/edgedb/edgeql/select_string_from_root.edgeql delete mode 100644 priv/edgedb/schema/default.esdl delete mode 100644 priv/edgedb/schema/migrations/00001.edgeql delete mode 100644 priv/edgedb/schema/migrations/00002.edgeql delete mode 100644 priv/edgedb/schema/migrations/00003.edgeql delete mode 100644 priv/edgedb/schema/migrations/00004.edgeql delete mode 100644 priv/edgedb/schema/migrations/00005.edgeql delete mode 100644 priv/edgedb/schema/migrations/00006.edgeql delete mode 100644 priv/edgedb/schema/migrations/00007.edgeql delete mode 100644 priv/edgedb/schema/migrations/00008.edgeql delete mode 100644 priv/edgedb/schema/migrations/00009.edgeql delete mode 100644 priv/edgedb/schema/migrations/00010.edgeql delete mode 100644 priv/edgedb/schema/migrations/00011.edgeql delete mode 100644 priv/edgedb/schema/migrations/00012.edgeql delete mode 100644 priv/edgedb/schema/migrations/00013.edgeql delete mode 100644 priv/edgedb/schema/migrations/00014.edgeql delete mode 100644 priv/edgedb/schema/migrations/00015.edgeql delete mode 100644 priv/edgedb/schema/migrations/00016.edgeql delete mode 100644 priv/edgedb/schema/migrations/00017.edgeql delete mode 100644 priv/edgedb/schema/migrations/00018.edgeql delete mode 100644 priv/edgedb/schema/migrations/00019.edgeql delete mode 100644 priv/edgedb/schema/migrations/00020.edgeql diff --git a/config/config.exs b/config/config.exs index b7057400..9288ddcc 100644 --- a/config/config.exs +++ b/config/config.exs @@ -2,17 +2,17 @@ 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/", + 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 b9d641b0..4344650f 100644 --- a/edgedb.toml +++ b/edgedb.toml @@ -2,5 +2,5 @@ server-version = "3.0" [project] -# schema-dir = "./test/support/schema" -schema-dir = "./priv/edgedb/schema" +schema-dir = "./test/support/schema" +#schema-dir = "./priv/edgedb/schema" diff --git a/priv/edgedb/codegen/queries/media_library/get_current_active_song.edgeql.ex b/priv/edgedb/codegen/queries/media_library/get_current_active_song.edgeql.ex deleted file mode 100644 index 88e99ccc..00000000 --- a/priv/edgedb/codegen/queries/media_library/get_current_active_song.edgeql.ex +++ /dev/null @@ -1,191 +0,0 @@ -# AUTOGENERATED: DO NOT MODIFY -# Generated by Elixir client for EdgeDB via `mix edgedb.generate` from -# `priv/edgedb/edgeql/media_library/get_current_active_song.edgeql`. -defmodule Tests.Codegen.Queries.MediaLibrary.GetCurrentActiveSong do - @query """ - select Song { - *, - mp3: { - * - }, - user: { - id, - } - } - filter - .user.id = $user_id - and - .status in {SongStatus.playing, SongStatus.paused} - limit 1 - """ - - @moduledoc """ - Generated module for the EdgeQL query from - `priv/edgedb/edgeql/media_library/get_current_active_song.edgeql`. - - Query: - - ```edgeql - #{@query} - ``` - """ - - @typedoc """ - ```edgeql - std::uuid - ``` - """ - @type uuid() :: binary() - - @typedoc """ - ```edgeql - std::duration - ``` - """ - @type duration() :: Timex.Duration.t() | integer() - - @typedoc """ - ```edgeql - scalar type default::SongStatus extending enum - ``` - """ - @type default__song_status() :: String.t() | :stopped | :playing | :paused - - @typedoc """ - ```edgeql - scalar type default::inet extending std::bytes - ``` - """ - @type default__inet() :: bitstring() - - defmodule Result do - defmodule Mp3 do - defstruct [:id, :filename, :filepath, :filesize, :url] - - @type t() :: %__MODULE__{ - id: uuid(), - filename: String.t(), - filepath: String.t(), - filesize: EdgeDB.ConfigMemory.t(), - url: String.t() - } - end - - defmodule User do - defstruct [:id] - @type t() :: %__MODULE__{id: uuid()} | nil - end - - defstruct [ - :mp3, - :user, - :artist, - :title, - :attribution, - :date_recorded, - :date_released, - :paused_at, - :played_at, - :server_ip, - :position, - :id, - :inserted_at, - :updated_at, - :status, - :duration - ] - - @type t() :: - %__MODULE__{ - mp3: Mp3.t(), - user: User.t() | nil, - artist: String.t(), - title: String.t(), - attribution: String.t() | nil, - date_recorded: NaiveDateTime.t() | nil, - date_released: NaiveDateTime.t() | nil, - paused_at: DateTime.t() | nil, - played_at: DateTime.t() | nil, - server_ip: default__inet() | nil, - position: integer(), - id: uuid(), - inserted_at: NaiveDateTime.t(), - updated_at: NaiveDateTime.t(), - status: default__song_status(), - duration: duration() - } - | nil - end - - @type keyword_args() :: [{:user_id, uuid()}] - - @type map_args() :: %{ - user_id: 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.t()} - | {: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.t() - 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 - with {:ok, result} when not is_nil(result) <- EdgeDB.query_single(client, @query, args, opts) do - shape = %Result{ - updated_at: result["updated_at"], - title: result["title"], - status: result["status"], - server_ip: result["server_ip"], - position: result["position"], - played_at: result["played_at"], - paused_at: result["paused_at"], - inserted_at: result["inserted_at"], - id: result["id"], - duration: result["duration"], - date_released: result["date_released"], - date_recorded: result["date_recorded"], - attribution: result["attribution"], - artist: result["artist"], - user: %Result.User{id: result["user"]["id"]}, - mp3: %Result.Mp3{ - url: result["mp3"]["url"], - id: result["mp3"]["id"], - filesize: result["mp3"]["filesize"], - filepath: result["mp3"]["filepath"], - filename: result["mp3"]["filename"] - } - } - - {:ok, shape} - end - end -end diff --git a/priv/edgedb/codegen/queries/media_library/list_active_profiles.edgeql.ex b/priv/edgedb/codegen/queries/media_library/list_active_profiles.edgeql.ex deleted file mode 100644 index 10cd364a..00000000 --- a/priv/edgedb/codegen/queries/media_library/list_active_profiles.edgeql.ex +++ /dev/null @@ -1,190 +0,0 @@ -# AUTOGENERATED: DO NOT MODIFY -# Generated by Elixir client for EdgeDB via `mix edgedb.generate` from -# `priv/edgedb/edgeql/media_library/list_active_profiles.edgeql`. -defmodule Tests.Codegen.Queries.MediaLibrary.ListActiveProfiles do - @query """ - with songs := ( - select Song - filter .status = SongStatus.playing - order by .updated_at desc - ) - select songs.user { - id, - username, - profile_tagline, - avatar_url, - external_homepage_url, - ss := (select Song {*} - filter .status = SongStatus.playing - order by .updated_at desc) - } - limit $limit - """ - - @moduledoc """ - Generated module for the EdgeQL query from - `priv/edgedb/edgeql/media_library/list_active_profiles.edgeql`. - - Query: - - ```edgeql - #{@query} - ``` - """ - - @typedoc """ - ```edgeql - std::uuid - ``` - """ - @type uuid() :: binary() - - @typedoc """ - ```edgeql - std::duration - ``` - """ - @type duration() :: Timex.Duration.t() | integer() - - @typedoc """ - ```edgeql - scalar type default::SongStatus extending enum - ``` - """ - @type default__song_status() :: String.t() | :stopped | :playing | :paused - - @typedoc """ - ```edgeql - scalar type default::inet extending std::bytes - ``` - """ - @type default__inet() :: bitstring() - - defmodule Result do - defmodule Ss do - defstruct [ - :artist, - :title, - :attribution, - :date_recorded, - :date_released, - :paused_at, - :played_at, - :server_ip, - :position, - :id, - :inserted_at, - :updated_at, - :status, - :duration - ] - - @type t() :: %__MODULE__{ - artist: String.t(), - title: String.t(), - attribution: String.t() | nil, - date_recorded: NaiveDateTime.t() | nil, - date_released: NaiveDateTime.t() | nil, - paused_at: DateTime.t() | nil, - played_at: DateTime.t() | nil, - server_ip: default__inet() | nil, - position: integer(), - id: uuid(), - inserted_at: NaiveDateTime.t(), - updated_at: NaiveDateTime.t(), - status: default__song_status(), - duration: duration() - } - end - - defstruct [:id, :username, :profile_tagline, :avatar_url, :external_homepage_url, :ss] - - @type t() :: %__MODULE__{ - id: uuid(), - username: String.t(), - profile_tagline: String.t() | nil, - avatar_url: String.t() | nil, - external_homepage_url: String.t() | nil, - ss: list(Ss.t()) - } - end - - @type keyword_args() :: [{:limit, integer()}] - - @type map_args() :: %{ - limit: 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.t()} - | {: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.t() - 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 - with {:ok, results} <- EdgeDB.query(client, @query, args, opts) do - case result do - [] -> - nil - - _ -> - Enum.map(results, fn result -> - shape = %Result{ - username: result["username"], - profile_tagline: result["profile_tagline"], - id: result["id"], - external_homepage_url: result["external_homepage_url"], - avatar_url: result["avatar_url"], - ss: %Result.Ss{ - updated_at: result["ss"]["updated_at"], - title: result["ss"]["title"], - status: result["ss"]["status"], - server_ip: result["ss"]["server_ip"], - position: result["ss"]["position"], - played_at: result["ss"]["played_at"], - paused_at: result["ss"]["paused_at"], - inserted_at: result["ss"]["inserted_at"], - id: result["ss"]["id"], - duration: result["ss"]["duration"], - date_released: result["ss"]["date_released"], - date_recorded: result["ss"]["date_recorded"], - attribution: result["ss"]["attribution"], - artist: result["ss"]["artist"] - } - } - - {:ok, shape} - end) - end - end - end -end diff --git a/priv/edgedb/codegen/queries/media_library/pause_song.edgeql.ex b/priv/edgedb/codegen/queries/media_library/pause_song.edgeql.ex deleted file mode 100644 index add0c370..00000000 --- a/priv/edgedb/codegen/queries/media_library/pause_song.edgeql.ex +++ /dev/null @@ -1,77 +0,0 @@ -# AUTOGENERATED: DO NOT MODIFY -# Generated by Elixir client for EdgeDB via `mix edgedb.generate` from -# `priv/edgedb/edgeql/media_library/pause_song.edgeql`. -defmodule Tests.Codegen.Queries.MediaLibrary.PauseSong do - @query """ - update Song - filter .id = $song_id - set { - status := SongStatus.paused - } - """ - - @moduledoc """ - Generated module for the EdgeQL query from - `priv/edgedb/edgeql/media_library/pause_song.edgeql`. - - Query: - - ```edgeql - #{@query} - ``` - """ - - @typedoc """ - ```edgeql - std::uuid - ``` - """ - @type uuid() :: binary() - - @type keyword_args() :: [{:song_id, uuid()}] - - @type map_args() :: %{ - song_id: 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.t()} - | {: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.t() - 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 - with {:ok, result} when not is_nil(result) <- EdgeDB.query_single(client, @query, args, opts) do - {:ok, result} - end - end -end diff --git a/priv/edgedb/codegen/queries/select_string_from_root.edgeql.ex b/priv/edgedb/codegen/queries/select_string_from_root.edgeql.ex deleted file mode 100644 index 6be18ddf..00000000 --- a/priv/edgedb/codegen/queries/select_string_from_root.edgeql.ex +++ /dev/null @@ -1,56 +0,0 @@ -# AUTOGENERATED: DO NOT MODIFY -# Generated by Elixir client for EdgeDB via `mix edgedb.generate` from -# `priv/edgedb/edgeql/select_string_from_root.edgeql`. -defmodule Tests.Codegen.Queries.SelectStringFromRoot do - @query """ - select 'Hello world!' - """ - - @moduledoc """ - Generated module for the EdgeQL query from - `priv/edgedb/edgeql/select_string_from_root.edgeql`. - - Query: - - ```edgeql - #{@query} - ``` - """ - - @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 - with {:ok, result} <- EdgeDB.query_required_single(client, @query, args, opts) do - {:ok, result} - end - end -end diff --git a/priv/edgedb/edgeql/media_library/get_current_active_song.edgeql b/priv/edgedb/edgeql/media_library/get_current_active_song.edgeql deleted file mode 100644 index 823d45d7..00000000 --- a/priv/edgedb/edgeql/media_library/get_current_active_song.edgeql +++ /dev/null @@ -1,14 +0,0 @@ -select Song { - *, - mp3: { - * - }, - user: { - id, - } -} -filter - .user.id = $user_id - and - .status in {SongStatus.playing, SongStatus.paused} -limit 1 diff --git a/priv/edgedb/edgeql/media_library/list_active_profiles.edgeql b/priv/edgedb/edgeql/media_library/list_active_profiles.edgeql deleted file mode 100644 index fa9b8dcb..00000000 --- a/priv/edgedb/edgeql/media_library/list_active_profiles.edgeql +++ /dev/null @@ -1,16 +0,0 @@ -with songs := ( - select Song - filter .status = SongStatus.playing - order by .updated_at desc -) -select songs.user { - id, - username, - profile_tagline, - avatar_url, - external_homepage_url, - ss := (select Song {*} - filter .status = SongStatus.playing - order by .updated_at desc) -} -limit $limit diff --git a/priv/edgedb/edgeql/media_library/pause_song.edgeql b/priv/edgedb/edgeql/media_library/pause_song.edgeql deleted file mode 100644 index dbf75130..00000000 --- a/priv/edgedb/edgeql/media_library/pause_song.edgeql +++ /dev/null @@ -1,5 +0,0 @@ -update Song - filter .id = $song_id - set { - status := SongStatus.paused - } \ No newline at end of file diff --git a/priv/edgedb/edgeql/select_string_from_root.edgeql b/priv/edgedb/edgeql/select_string_from_root.edgeql deleted file mode 100644 index d0f78cf5..00000000 --- a/priv/edgedb/edgeql/select_string_from_root.edgeql +++ /dev/null @@ -1 +0,0 @@ -select 'Hello world!' diff --git a/priv/edgedb/schema/default.esdl b/priv/edgedb/schema/default.esdl deleted file mode 100644 index ba085cab..00000000 --- a/priv/edgedb/schema/default.esdl +++ /dev/null @@ -1,171 +0,0 @@ -module default { - required global max_songs_count := 30; - - global is_admin: bool; - - global current_user_id: uuid; - global current_user := ( - select User filter .id = global current_user_id - ); - - # cast insensitive string - scalar type cistr extending str; - - abstract type Timestamped { - required inserted_at: cal::local_datetime { - readonly := true; - rewrite insert using (cal::to_local_datetime(datetime_current(), 'UTC')) - } - - required updated_at: cal::local_datetime { - rewrite insert, update using (cal::to_local_datetime(datetime_current(), 'UTC')) - } - } - - type User extending Timestamped { - required name: str; - required username: str { - constraint exclusive; - } - - required email: cistr { - constraint regexp(r'^[^\s]+@[^\s]+$'); - constraint max_len_value(160); - - rewrite insert, update using (str_lower(__subject__.email)); - } - - profile_tagline: str; - - avatar_url: str; - external_homepage_url: str; - - property songs_count := count(."{}"; - } - - required user: User { - on target delete delete source; - } - - access policy owner_can_do_everything - allow all - using (global current_user.id ?= .user.id); - - access policy anyone_can_create - allow insert; - - index on (.provider); - constraint exclusive on ((.user, .provider)); - } - - scalar type SongStatus extending enum; - scalar type inet extending bytes; - - type MP3 { - required url: str; - required filename: str; - required filepath: str; - - required filesize: cfg::memory { - default := 0 - } - } - - type Song extending Timestamped { - required title: str; - required artist: str; - - attribution: str; - - server_ip: inet; - - required duration: duration { - default := '0 seconds'; - } - - required position: int64 { - default := 0; - } - - required status: SongStatus { - default := SongStatus.stopped; - } - - date_recorded: cal::local_datetime; - date_released: cal::local_datetime; - - played_at: datetime { - rewrite update using ( - datetime_current() - if __subject__.status = SongStatus.playing - else __old__.played_at - ) - } - - paused_at: datetime { - rewrite update using ( - datetime_current() - if __subject__.status = SongStatus.stopped - else __old__.played_at - ) - } - - required mp3: MP3 { - on source delete delete target; - } - - user: User { - # allow to keep songs until the cleaner deletes it with the real file - on target delete allow; - } - - access policy owner_can_do_everything - allow all - using (global current_user.id ?= .user.id); - - access policy admin_can_do_everything - allow all - using (global is_admin ?= true); - - access policy anyone_can_read - allow select; - - trigger ensure_user_songs_count_not_exceeded after insert, update for each do ( - assert( - __new__.user.songs_count <= global max_songs_count, - message := "Songs limit exceeded", - ) - ); - - index on (.status); - constraint exclusive on ((.user, .title, .artist)); - } -} diff --git a/priv/edgedb/schema/migrations/00001.edgeql b/priv/edgedb/schema/migrations/00001.edgeql deleted file mode 100644 index 8681a2fe..00000000 --- a/priv/edgedb/schema/migrations/00001.edgeql +++ /dev/null @@ -1,47 +0,0 @@ -CREATE MIGRATION m1ujqlj37zkefvbigraftt72bbdxu2q6mcun4xg7hwkeyuuxtgxhrq - ONTO initial -{ - CREATE SCALAR TYPE default::cistr EXTENDING std::str; - CREATE TYPE default::User { - CREATE REQUIRED PROPERTY username -> std::str; - CREATE INDEX ON (.username); - CREATE REQUIRED PROPERTY email -> default::cistr; - CREATE INDEX ON (.email); - CREATE LINK active_profile_user -> default::User { - ON TARGET DELETE ALLOW; - }; - CREATE PROPERTY confirmed_at -> cal::local_datetime; - CREATE REQUIRED PROPERTY inserted_at -> cal::local_datetime { - SET default := (cal::to_local_datetime(std::datetime_current(), 'UTC')); - }; - CREATE PROPERTY name -> std::str; - CREATE PROPERTY profile_tagline -> std::str; - CREATE REQUIRED PROPERTY role -> std::str { - SET default := ("subscriber"); - }; - CREATE REQUIRED PROPERTY updated_at -> cal::local_datetime { - SET default := (cal::to_local_datetime(std::datetime_current(), 'UTC')); - }; - }; - CREATE TYPE default::Identity { - CREATE REQUIRED LINK user -> default::User { - ON TARGET DELETE DELETE SOURCE; - }; - CREATE REQUIRED PROPERTY provider -> std::str; - CREATE CONSTRAINT std::exclusive ON ((.user, .provider)); - CREATE INDEX ON (.provider); - CREATE REQUIRED PROPERTY inserted_at -> cal::local_datetime { - SET default := (cal::to_local_datetime(std::datetime_current(), 'UTC')); - }; - CREATE REQUIRED PROPERTY provider_email -> std::str; - CREATE REQUIRED PROPERTY provider_id -> std::str; - CREATE REQUIRED PROPERTY provider_login -> std::str; - CREATE REQUIRED PROPERTY provider_meta -> std::json { - SET default := ('{}'); - }; - CREATE REQUIRED PROPERTY provider_token -> std::str; - CREATE REQUIRED PROPERTY updated_at -> cal::local_datetime { - SET default := (cal::to_local_datetime(std::datetime_current(), 'UTC')); - }; - }; -}; diff --git a/priv/edgedb/schema/migrations/00002.edgeql b/priv/edgedb/schema/migrations/00002.edgeql deleted file mode 100644 index 8484be59..00000000 --- a/priv/edgedb/schema/migrations/00002.edgeql +++ /dev/null @@ -1,12 +0,0 @@ -CREATE MIGRATION m1bwaytmgkte3dpabashzohfm56w3yirzomvfbh5r7cbay5jytegaa - ONTO m1ujqlj37zkefvbigraftt72bbdxu2q6mcun4xg7hwkeyuuxtgxhrq -{ - CREATE TYPE default::Genre { - CREATE REQUIRED PROPERTY slug -> std::str { - CREATE CONSTRAINT std::exclusive; - }; - CREATE REQUIRED PROPERTY title -> std::str { - CREATE CONSTRAINT std::exclusive; - }; - }; -}; diff --git a/priv/edgedb/schema/migrations/00003.edgeql b/priv/edgedb/schema/migrations/00003.edgeql deleted file mode 100644 index 0bd0010e..00000000 --- a/priv/edgedb/schema/migrations/00003.edgeql +++ /dev/null @@ -1,38 +0,0 @@ -CREATE MIGRATION m1qb4i57nhmluwtd7pbeornej7kthhw34aejzjwrdcr65fiekxe3nq - ONTO m1bwaytmgkte3dpabashzohfm56w3yirzomvfbh5r7cbay5jytegaa -{ - CREATE SCALAR TYPE default::SongStatus EXTENDING enum; - CREATE TYPE default::Song { - CREATE LINK user -> default::User { - ON TARGET DELETE ALLOW; - }; - CREATE REQUIRED PROPERTY artist -> std::str; - CREATE REQUIRED PROPERTY title -> std::str; - CREATE CONSTRAINT std::exclusive ON ((.user, .title, .artist)); - CREATE REQUIRED PROPERTY status -> default::SongStatus { - SET default := (default::SongStatus.Stopped); - }; - CREATE INDEX ON (.status); - CREATE LINK genre -> default::Genre { - ON TARGET DELETE ALLOW; - }; - CREATE PROPERTY album_artist -> std::str; - CREATE PROPERTY attribution -> std::str; - CREATE PROPERTY date_recorded -> cal::local_datetime; - CREATE PROPERTY date_released -> cal::local_datetime; - CREATE REQUIRED PROPERTY duration -> std::int64 { - SET default := 0; - }; - CREATE REQUIRED PROPERTY inserted_at -> cal::local_datetime { - SET default := (cal::to_local_datetime(std::datetime_current(), 'UTC')); - }; - CREATE REQUIRED PROPERTY mp3_filename -> std::str; - CREATE REQUIRED PROPERTY mp3_filepath -> std::str; - CREATE REQUIRED PROPERTY mp3_url -> std::str; - CREATE PROPERTY paused_at -> std::datetime; - CREATE PROPERTY played_at -> std::datetime; - CREATE REQUIRED PROPERTY updated_at -> cal::local_datetime { - SET default := (cal::to_local_datetime(std::datetime_current(), 'UTC')); - }; - }; -}; diff --git a/priv/edgedb/schema/migrations/00004.edgeql b/priv/edgedb/schema/migrations/00004.edgeql deleted file mode 100644 index f3049999..00000000 --- a/priv/edgedb/schema/migrations/00004.edgeql +++ /dev/null @@ -1,8 +0,0 @@ -CREATE MIGRATION m147bo4znisjhp7ymyunkfc66a3hqctob7lq5jp2xy2m4gh5vkzzya - ONTO m1qb4i57nhmluwtd7pbeornej7kthhw34aejzjwrdcr65fiekxe3nq -{ - ALTER TYPE default::User { - CREATE PROPERTY avatar_url -> std::str; - CREATE PROPERTY external_homepage_url -> std::str; - }; -}; diff --git a/priv/edgedb/schema/migrations/00005.edgeql b/priv/edgedb/schema/migrations/00005.edgeql deleted file mode 100644 index be4c2408..00000000 --- a/priv/edgedb/schema/migrations/00005.edgeql +++ /dev/null @@ -1,8 +0,0 @@ -CREATE MIGRATION m1hd7litg4ylc632kuyv3xqipk6bvjgcrbeoujgvoccts65yholkda - ONTO m147bo4znisjhp7ymyunkfc66a3hqctob7lq5jp2xy2m4gh5vkzzya -{ - CREATE SCALAR TYPE default::inet EXTENDING std::bytes; - ALTER TYPE default::Song { - CREATE PROPERTY server_ip -> default::inet; - }; -}; diff --git a/priv/edgedb/schema/migrations/00006.edgeql b/priv/edgedb/schema/migrations/00006.edgeql deleted file mode 100644 index d84fe1e3..00000000 --- a/priv/edgedb/schema/migrations/00006.edgeql +++ /dev/null @@ -1,7 +0,0 @@ -CREATE MIGRATION m1ibh7njtapjtc6qlcv2aw6gxrebw5zwvagpx6mlxplmq7nwpzo36a - ONTO m1hd7litg4ylc632kuyv3xqipk6bvjgcrbeoujgvoccts65yholkda -{ - ALTER TYPE default::User { - CREATE PROPERTY songs_count := (std::count(. std::int64 { - SET default := 0; - }; - }; -}; diff --git a/priv/edgedb/schema/migrations/00008.edgeql b/priv/edgedb/schema/migrations/00008.edgeql deleted file mode 100644 index f9f5c704..00000000 --- a/priv/edgedb/schema/migrations/00008.edgeql +++ /dev/null @@ -1,10 +0,0 @@ -CREATE MIGRATION m1zvprfqkveu4mb4kou74xgiar2yt5abpnu5ntsqhki7lbeinjznbq - ONTO m13t5esb4neq5k7pwacj6izyxsvblyaf7e7x3hndvfutgbalz72qxa -{ - CREATE FUNCTION default::to_status(status: std::str) -> OPTIONAL default::SongStatus USING (WITH - status := - std::str_title(status) - SELECT - (status IF (status IN {'Stopped', 'Playing', 'Paused'}) ELSE {}) - ); -}; diff --git a/priv/edgedb/schema/migrations/00009.edgeql b/priv/edgedb/schema/migrations/00009.edgeql deleted file mode 100644 index f201bc3b..00000000 --- a/priv/edgedb/schema/migrations/00009.edgeql +++ /dev/null @@ -1,9 +0,0 @@ -CREATE MIGRATION m1ec7ytvgzhdpcmpjfdumfdypk56ceoiftstllef3fzr6k5bnfesta - ONTO m1zvprfqkveu4mb4kou74xgiar2yt5abpnu5ntsqhki7lbeinjznbq -{ - ALTER TYPE default::Song { - CREATE REQUIRED PROPERTY position -> std::int64 { - SET default := 0; - }; - }; -}; diff --git a/priv/edgedb/schema/migrations/00010.edgeql b/priv/edgedb/schema/migrations/00010.edgeql deleted file mode 100644 index 1322be07..00000000 --- a/priv/edgedb/schema/migrations/00010.edgeql +++ /dev/null @@ -1,50 +0,0 @@ -CREATE MIGRATION m1qcv5nieywf4bygcrna7cf7ygkdarqelwig6xnjwpzdfkktdfwh3q - ONTO m1ec7ytvgzhdpcmpjfdumfdypk56ceoiftstllef3fzr6k5bnfesta -{ - ALTER TYPE default::Identity { - ALTER PROPERTY inserted_at { - RENAME TO inserted_at_legacy; - }; - }; - ALTER TYPE default::Identity { - ALTER PROPERTY updated_at { - RENAME TO updated_at_legacy; - }; - }; - ALTER TYPE default::Song { - ALTER PROPERTY inserted_at { - RENAME TO inserted_at_legacy; - }; - }; - ALTER TYPE default::Song { - ALTER PROPERTY updated_at { - RENAME TO updated_at_legacy; - }; - }; - CREATE ABSTRACT TYPE default::Timestamped { - CREATE REQUIRED PROPERTY inserted_at: cal::local_datetime { - SET readonly := true; - CREATE REWRITE - INSERT - USING (cal::to_local_datetime(std::datetime_current(), 'UTC')); - }; - CREATE REQUIRED PROPERTY updated_at: cal::local_datetime { - CREATE REWRITE - INSERT - USING (cal::to_local_datetime(std::datetime_current(), 'UTC')); - CREATE REWRITE - UPDATE - USING (cal::to_local_datetime(std::datetime_current(), 'UTC')); - }; - }; - ALTER TYPE default::User { - ALTER PROPERTY inserted_at { - RENAME TO inserted_at_legacy; - }; - }; - ALTER TYPE default::User { - ALTER PROPERTY updated_at { - RENAME TO updated_at_legacy; - }; - }; -}; diff --git a/priv/edgedb/schema/migrations/00011.edgeql b/priv/edgedb/schema/migrations/00011.edgeql deleted file mode 100644 index 60b3667b..00000000 --- a/priv/edgedb/schema/migrations/00011.edgeql +++ /dev/null @@ -1,67 +0,0 @@ -CREATE MIGRATION m1cyoreiep3r4h2dwl3pjujbjiyly67f55rbfqxnqkmdueffvxgcba - ONTO m1qcv5nieywf4bygcrna7cf7ygkdarqelwig6xnjwpzdfkktdfwh3q -{ - ALTER TYPE default::Identity { - CREATE PROPERTY inserted_at: cal::local_datetime { - SET REQUIRED USING (.inserted_at_legacy); - }; - CREATE PROPERTY updated_at: cal::local_datetime { - SET REQUIRED USING (.updated_at_legacy); - }; - EXTENDING default::Timestamped LAST; - }; - ALTER TYPE default::Identity { - ALTER PROPERTY inserted_at { - RESET OPTIONALITY; - DROP OWNED; - RESET TYPE; - }; - ALTER PROPERTY updated_at { - RESET OPTIONALITY; - DROP OWNED; - RESET TYPE; - }; - }; - ALTER TYPE default::Song { - CREATE PROPERTY inserted_at: cal::local_datetime { - SET REQUIRED USING (.inserted_at_legacy); - }; - CREATE PROPERTY updated_at: cal::local_datetime { - SET REQUIRED USING (.updated_at_legacy); - }; - EXTENDING default::Timestamped LAST; - }; - ALTER TYPE default::Song { - ALTER PROPERTY inserted_at { - RESET OPTIONALITY; - DROP OWNED; - RESET TYPE; - }; - ALTER PROPERTY updated_at { - RESET OPTIONALITY; - DROP OWNED; - RESET TYPE; - }; - }; - ALTER TYPE default::User { - CREATE PROPERTY inserted_at: cal::local_datetime { - SET REQUIRED USING (.inserted_at_legacy); - }; - CREATE PROPERTY updated_at: cal::local_datetime { - SET REQUIRED USING (.updated_at_legacy); - }; - EXTENDING default::Timestamped LAST; - }; - ALTER TYPE default::User { - ALTER PROPERTY inserted_at { - RESET OPTIONALITY; - DROP OWNED; - RESET TYPE; - }; - ALTER PROPERTY updated_at { - RESET OPTIONALITY; - DROP OWNED; - RESET TYPE; - }; - }; -}; diff --git a/priv/edgedb/schema/migrations/00012.edgeql b/priv/edgedb/schema/migrations/00012.edgeql deleted file mode 100644 index 6117b216..00000000 --- a/priv/edgedb/schema/migrations/00012.edgeql +++ /dev/null @@ -1,16 +0,0 @@ -CREATE MIGRATION m1z5zo6o4ommezfxgcgne2i5o5djt5wrso5qqatzc3rwont43wzyua - ONTO m1cyoreiep3r4h2dwl3pjujbjiyly67f55rbfqxnqkmdueffvxgcba -{ - ALTER TYPE default::Identity { - DROP PROPERTY inserted_at_legacy; - DROP PROPERTY updated_at_legacy; - }; - ALTER TYPE default::Song { - DROP PROPERTY inserted_at_legacy; - DROP PROPERTY updated_at_legacy; - }; - ALTER TYPE default::User { - DROP PROPERTY inserted_at_legacy; - DROP PROPERTY updated_at_legacy; - }; -}; diff --git a/priv/edgedb/schema/migrations/00013.edgeql b/priv/edgedb/schema/migrations/00013.edgeql deleted file mode 100644 index a3b5ca74..00000000 --- a/priv/edgedb/schema/migrations/00013.edgeql +++ /dev/null @@ -1,24 +0,0 @@ -CREATE MIGRATION m1it7pwkmkmpv26wjsb7meak75pa7pex2j6mya7yozolbmincbgcza - ONTO m1z5zo6o4ommezfxgcgne2i5o5djt5wrso5qqatzc3rwont43wzyua -{ - ALTER TYPE default::User { - DROP PROPERTY confirmed_at; - ALTER PROPERTY email { - CREATE CONSTRAINT std::max_len_value(160); - CREATE CONSTRAINT std::regexp(r'^[^\s]+@[^\s]+$'); - CREATE REWRITE - INSERT - USING (std::str_lower(__subject__.email)); - CREATE REWRITE - UPDATE - USING (std::str_lower(__subject__.email)); - }; - ALTER PROPERTY name { - SET REQUIRED USING (.username); - }; - DROP PROPERTY role; - ALTER PROPERTY username { - CREATE CONSTRAINT std::exclusive; - }; - }; -}; diff --git a/priv/edgedb/schema/migrations/00014.edgeql b/priv/edgedb/schema/migrations/00014.edgeql deleted file mode 100644 index dfc1a89b..00000000 --- a/priv/edgedb/schema/migrations/00014.edgeql +++ /dev/null @@ -1,15 +0,0 @@ -CREATE MIGRATION m1okgh4wtvnuxdcf7b65cbx6okhb3twpxdkppoc6lv5zotvhcn5ika - ONTO m1it7pwkmkmpv26wjsb7meak75pa7pex2j6mya7yozolbmincbgcza -{ - ALTER TYPE default::Identity { - ALTER PROPERTY provider_email { - SET TYPE default::cistr; - CREATE REWRITE - INSERT - USING (std::str_lower(__subject__.provider_email)); - CREATE REWRITE - UPDATE - USING (std::str_lower(__subject__.provider_email)); - }; - }; -}; diff --git a/priv/edgedb/schema/migrations/00015.edgeql b/priv/edgedb/schema/migrations/00015.edgeql deleted file mode 100644 index 7fda3543..00000000 --- a/priv/edgedb/schema/migrations/00015.edgeql +++ /dev/null @@ -1,16 +0,0 @@ -CREATE MIGRATION m1ta2vukbkhirlahnlekib6cdudqzlol6wu5aztvowsg5skarqmh5a - ONTO m1okgh4wtvnuxdcf7b65cbx6okhb3twpxdkppoc6lv5zotvhcn5ika -{ - DROP FUNCTION default::to_status(status: std::str); - ALTER TYPE default::Song { - DROP INDEX ON (.status); - DROP PROPERTY status; - }; - ALTER SCALAR TYPE default::SongStatus EXTENDING enum; - ALTER TYPE default::Song { - CREATE REQUIRED PROPERTY status: default::SongStatus { - SET default := (default::SongStatus.stopped); - }; - CREATE INDEX ON (.status); - }; -}; diff --git a/priv/edgedb/schema/migrations/00016.edgeql b/priv/edgedb/schema/migrations/00016.edgeql deleted file mode 100644 index 724335c7..00000000 --- a/priv/edgedb/schema/migrations/00016.edgeql +++ /dev/null @@ -1,12 +0,0 @@ -CREATE MIGRATION m1cf555gemqtjglvd5sthjsrnjrdecxkdeyrd3wpbkpvozjeovxyxq - ONTO m1ta2vukbkhirlahnlekib6cdudqzlol6wu5aztvowsg5skarqmh5a -{ - ALTER TYPE default::Genre { - DROP PROPERTY slug; - DROP PROPERTY title; - }; - ALTER TYPE default::Song { - DROP LINK genre; - }; - DROP TYPE default::Genre; -}; diff --git a/priv/edgedb/schema/migrations/00017.edgeql b/priv/edgedb/schema/migrations/00017.edgeql deleted file mode 100644 index ea5c179a..00000000 --- a/priv/edgedb/schema/migrations/00017.edgeql +++ /dev/null @@ -1,31 +0,0 @@ -CREATE MIGRATION m1bex2l6siwpxeifsgdqah5p2uh2shovtwuyd5fifvfofdafnkl6ja - ONTO m1cf555gemqtjglvd5sthjsrnjrdecxkdeyrd3wpbkpvozjeovxyxq -{ - CREATE TYPE default::MP3 { - CREATE REQUIRED PROPERTY filename: std::str; - CREATE REQUIRED PROPERTY filepath: std::str; - CREATE REQUIRED PROPERTY filesize: cfg::memory { - SET default := (0); - }; - CREATE REQUIRED PROPERTY url: std::str; - }; - ALTER TYPE default::Song { - CREATE REQUIRED LINK mp3: default::MP3 { - ON SOURCE DELETE DELETE TARGET; - SET REQUIRED USING ((INSERT - default::MP3 - { - url := default::Song.mp3_url, - filename := default::Song.mp3_filename, - filepath := default::Song.mp3_filepath, - filesize := default::Song.mp3_filesize - })); - }; - }; - ALTER TYPE default::Song { - DROP PROPERTY mp3_filename; - DROP PROPERTY mp3_filepath; - DROP PROPERTY mp3_filesize; - DROP PROPERTY mp3_url; - }; -}; diff --git a/priv/edgedb/schema/migrations/00018.edgeql b/priv/edgedb/schema/migrations/00018.edgeql deleted file mode 100644 index 31171719..00000000 --- a/priv/edgedb/schema/migrations/00018.edgeql +++ /dev/null @@ -1,10 +0,0 @@ -CREATE MIGRATION m12w3z4oofn5dke5mw3oirfpgbfyhi5lweuklpzb4xrybtxq3oqoeq - ONTO m1bex2l6siwpxeifsgdqah5p2uh2shovtwuyd5fifvfofdafnkl6ja -{ - ALTER TYPE default::Song { - ALTER PROPERTY duration { - SET default := ('0 seconds'); - SET TYPE std::duration USING ((std::to_str(.duration) ++ ' seconds')); - }; - }; -}; diff --git a/priv/edgedb/schema/migrations/00019.edgeql b/priv/edgedb/schema/migrations/00019.edgeql deleted file mode 100644 index cfbb97ea..00000000 --- a/priv/edgedb/schema/migrations/00019.edgeql +++ /dev/null @@ -1,17 +0,0 @@ -CREATE MIGRATION m16cque5xr6zlbwpuvvxwhvjbuztypf4n6yqxke6z4hqtwwool4zva - ONTO m12w3z4oofn5dke5mw3oirfpgbfyhi5lweuklpzb4xrybtxq3oqoeq -{ - ALTER TYPE default::Song { - DROP PROPERTY album_artist; - ALTER PROPERTY paused_at { - CREATE REWRITE - UPDATE - USING ((std::datetime_current() IF (__subject__.status = default::SongStatus.stopped) ELSE __old__.played_at)); - }; - ALTER PROPERTY played_at { - CREATE REWRITE - UPDATE - USING ((std::datetime_current() IF (__subject__.status = default::SongStatus.playing) ELSE __old__.played_at)); - }; - }; -}; diff --git a/priv/edgedb/schema/migrations/00020.edgeql b/priv/edgedb/schema/migrations/00020.edgeql deleted file mode 100644 index 4efd6976..00000000 --- a/priv/edgedb/schema/migrations/00020.edgeql +++ /dev/null @@ -1,39 +0,0 @@ -CREATE MIGRATION m123g7cikfwawoirtb6cxdywwfyh3x4r6bcyqmrl3eoaod4g5ifqnq - ONTO m16cque5xr6zlbwpuvvxwhvjbuztypf4n6yqxke6z4hqtwwool4zva -{ - CREATE GLOBAL default::current_user_id -> std::uuid; - CREATE GLOBAL default::current_user := (SELECT - default::User - FILTER - (.id = GLOBAL default::current_user_id) - ); - ALTER TYPE default::Identity { - CREATE ACCESS POLICY owner_can_do_everything - ALLOW ALL USING (((GLOBAL default::current_user).id ?= .user.id)); - CREATE ACCESS POLICY anyone_can_create - ALLOW INSERT ; - }; - ALTER TYPE default::Song { - CREATE ACCESS POLICY owner_can_do_everything - ALLOW ALL USING (((GLOBAL default::current_user).id ?= .user.id)); - }; - ALTER TYPE default::User { - CREATE ACCESS POLICY owner_can_do_everything - ALLOW ALL USING (((GLOBAL default::current_user).id ?= .id)); - CREATE ACCESS POLICY anyone_can_read_or_create - ALLOW SELECT, INSERT ; - }; - CREATE REQUIRED GLOBAL default::max_songs_count := (30); - ALTER TYPE default::Song { - CREATE TRIGGER ensure_user_songs_count_not_exceeded - AFTER UPDATE, INSERT - FOR EACH DO (std::assert((__new__.user.songs_count <= GLOBAL default::max_songs_count), message := 'Songs limit exceeded')); - }; - CREATE GLOBAL default::is_admin -> std::bool; - ALTER TYPE default::Song { - CREATE ACCESS POLICY admin_can_do_everything - ALLOW ALL USING ((GLOBAL default::is_admin ?= true)); - CREATE ACCESS POLICY anyone_can_read - ALLOW SELECT ; - }; -}; From 9d1f7da23f3d1b590aa74eba211947f23fca43b8 Mon Sep 17 00:00:00 2001 From: Devi Prasad Date: Thu, 28 Sep 2023 21:29:00 -0500 Subject: [PATCH 07/15] wip: full typed module name, better result type --- lib/edgedb/edgeql/generator.ex | 26 ++++++++++++++++---------- priv/codegen/templates/_builtin.eex | 2 +- priv/codegen/templates/_object.eex | 10 +++++++--- priv/codegen/templates/_set.eex | 3 ++- priv/codegen/templates/_shape.eex | 8 +++++--- priv/codegen/templates/query.ex.eex | 7 +++---- 6 files changed, 34 insertions(+), 22 deletions(-) diff --git a/lib/edgedb/edgeql/generator.ex b/lib/edgedb/edgeql/generator.ex index a48740db..f0a90e7b 100644 --- a/lib/edgedb/edgeql/generator.ex +++ b/lib/edgedb/edgeql/generator.ex @@ -176,6 +176,8 @@ defmodule EdgeDB.EdgeQL.Generator do 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( @@ -183,7 +185,8 @@ defmodule EdgeDB.EdgeQL.Generator do render_shape: &render_shape/1, render_builtin: &render_builtin/1, render_object: &render_object/1, - render_set: &render_set/1 + render_set: &render_set/1, + module_name: module_name ) rendered_schema = @@ -201,12 +204,14 @@ defmodule EdgeDB.EdgeQL.Generator do generate_query_module( query_file: query_file, module_name: module_name, - types: types(), + 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 && "Result.t()") || rendered_shape, + 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, @@ -298,7 +303,8 @@ defmodule EdgeDB.EdgeQL.Generator do is_list: list?, is_optional: optional?, is_link_property: link_property?, - index: index + index: index, + registered: false }, codec_to_shape(codec, codec_storage) ) @@ -320,14 +326,14 @@ defmodule EdgeDB.EdgeQL.Generator do typename = "uuid()" uuid_typespec = @builtin_scalars_to_typespecs[Codecs.UUID] register_typespec(typename, uuid_typespec) - %{type: :builtin, typespec: typename} + %{type: :builtin, typespec: typename, 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} + %{type: :builtin, typespec: typename, registered: true} end defp codec_to_shape(%Codecs.Duration{}, _codec_storage) do @@ -345,14 +351,14 @@ defmodule EdgeDB.EdgeQL.Generator do register_typespec(typename, duration_typespec) end - %{type: :builtin, typespec: typename} + %{type: :builtin, typespec: typename, 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} + %{type: :builtin, typespec: typename, registered: true} end defp codec_to_shape(%codec_name{}, _codec_storage) when codec_name in @scalar_codecs do @@ -374,14 +380,14 @@ defmodule EdgeDB.EdgeQL.Generator do register_typespec(full_type_name, {typedoc, subcodec_typespec}) - %{type: :builtin, typespec: full_type_name} + %{type: :builtin, typespec: full_type_name, 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, &":#{&1}")]}) - %{type: :builtin, typespec: full_type_name} + %{type: :builtin, typespec: full_type_name, registered: true} end defp codec_to_shape(%Codecs.Array{codec: subcodec}, codec_storage) do diff --git a/priv/codegen/templates/_builtin.eex b/priv/codegen/templates/_builtin.eex index 6d8df055..b5f2354c 100644 --- a/priv/codegen/templates/_builtin.eex +++ b/priv/codegen/templates/_builtin.eex @@ -1,5 +1,5 @@ <%= if @builtin[:is_list] do %>list(<% end %> -<%= @builtin.typespec %> +<%= if @builtin[:registered] do %><%= @module_name %>.<% end %><%= @builtin.typespec %> <%= if @builtin[:is_list] do %>)<% end %> <%= if @builtin[:is_optional] do %> | nil diff --git a/priv/codegen/templates/_object.eex b/priv/codegen/templates/_object.eex index f1cbd225..5225d297 100644 --- a/priv/codegen/templates/_object.eex +++ b/priv/codegen/templates/_object.eex @@ -7,7 +7,8 @@ render_shape: @render_shape, render_builtin: @render_builtin, render_object: @render_object, - render_set: @render_set + render_set: @render_set, + module_name: @module_name ) %> end; <% %{type: :set} -> %> @@ -17,7 +18,8 @@ render_shape: @render_shape, render_builtin: @render_builtin, render_object: @render_object, - render_set: @render_set + render_set: @render_set, + module_name: @module_name ) %> end; <% _ -> %> @@ -25,6 +27,7 @@ <% end %> <% end %> +@derive Jason.Encoder; defstruct [ <%= for {name, _} <- @object.fields do %> :<%= name %>, @@ -45,7 +48,8 @@ defstruct [ render_shape: @render_shape, render_builtin: @render_builtin, render_object: @render_object, - render_set: @render_set + render_set: @render_set, + module_name: @module_name ) %>, <% end %> <% end %> diff --git a/priv/codegen/templates/_set.eex b/priv/codegen/templates/_set.eex index 27aca7d1..0f5bd364 100644 --- a/priv/codegen/templates/_set.eex +++ b/priv/codegen/templates/_set.eex @@ -3,5 +3,6 @@ render_shape: @render_shape, render_builtin: @render_builtin, render_object: @render_object, - render_set: @render_set + render_set: @render_set, + module_name: @module_name ) %> diff --git a/priv/codegen/templates/_shape.eex b/priv/codegen/templates/_shape.eex index 792548e9..f233d4a2 100644 --- a/priv/codegen/templates/_shape.eex +++ b/priv/codegen/templates/_shape.eex @@ -1,6 +1,6 @@ <%= case @shape do %> <% %{type: :builtin} = builtin -> %> - <%= @render_builtin.(builtin: builtin) %> + <%= @render_builtin.(builtin: builtin, module_name: @module_name) %> <% %{type: :object} = object -> %> <%= @render_object.( @@ -8,7 +8,8 @@ render_shape: @render_shape, render_builtin: @render_builtin, render_object: @render_object, - render_set: @render_set + render_set: @render_set, + module_name: @module_name ) %> <% %{type: :set} = set -> %> @@ -17,6 +18,7 @@ render_shape: @render_shape, render_builtin: @render_builtin, render_object: @render_object, - render_set: @render_set + 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 index 023bd535..abbb3ba5 100644 --- a/priv/codegen/templates/query.ex.eex +++ b/priv/codegen/templates/query.ex.eex @@ -166,15 +166,13 @@ defmodule <%= @module_name %> do <% _ -> %> with {:ok, results} <- EdgeDB.query(client, @query, args, opts) do - case result do + results = case results do [] -> nil _ -> Enum.map(results, fn result -> <% end %> <%= if @should_render_type_for_shape do %> - shape = %Result<%= @schema %> - - {:ok, shape} + %Result<%= @schema %> <% else %> {:ok, result} <% end %> @@ -182,6 +180,7 @@ defmodule <%= @module_name %> do <%= if @query.cardinality in [:at_least_one, :many] do %> end); end; + {:ok, results}; <% end %> end end From f43bba27bb1fd59fec9330c9c10eb2fbaa1f84b1 Mon Sep 17 00:00:00 2001 From: Devi Prasad Date: Fri, 29 Sep 2023 01:27:22 -0500 Subject: [PATCH 08/15] feat: set improvements --- lib/edgedb/edgeql/generator.ex | 22 +++++++++++----------- priv/codegen/templates/_builtin.eex | 2 +- priv/codegen/templates/_object.eex | 1 + priv/codegen/templates/_schema.eex | 2 +- 4 files changed, 14 insertions(+), 13 deletions(-) diff --git a/lib/edgedb/edgeql/generator.ex b/lib/edgedb/edgeql/generator.ex index f0a90e7b..649e8e13 100644 --- a/lib/edgedb/edgeql/generator.ex +++ b/lib/edgedb/edgeql/generator.ex @@ -175,8 +175,8 @@ defmodule EdgeDB.EdgeQL.Generator do {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] + complex? = complex_shape?(raw_shape) + final_list? = query.result_cardinality in [:many, :at_least_one] types = types() rendered_shape = @@ -207,10 +207,10 @@ defmodule EdgeDB.EdgeQL.Generator do types: types, shape: rendered_shape, schema: rendered_schema, - should_render_type_for_shape: rendered_schema && complex, + 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()") || + (complex? && final_list? && "list(Result.t())") || (complex? && "Result.t()") || rendered_shape, query: %{ statement: query.statement, @@ -304,7 +304,7 @@ defmodule EdgeDB.EdgeQL.Generator do is_optional: optional?, is_link_property: link_property?, index: index, - registered: false + is_registered: false }, codec_to_shape(codec, codec_storage) ) @@ -326,14 +326,14 @@ defmodule EdgeDB.EdgeQL.Generator do typename = "uuid()" uuid_typespec = @builtin_scalars_to_typespecs[Codecs.UUID] register_typespec(typename, uuid_typespec) - %{type: :builtin, typespec: typename, registered: true} + %{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, registered: true} + %{type: :builtin, typespec: typename, is_registered: true} end defp codec_to_shape(%Codecs.Duration{}, _codec_storage) do @@ -351,14 +351,14 @@ defmodule EdgeDB.EdgeQL.Generator do register_typespec(typename, duration_typespec) end - %{type: :builtin, typespec: typename, registered: true} + %{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, registered: true} + %{type: :builtin, typespec: typename, is_registered: true} end defp codec_to_shape(%codec_name{}, _codec_storage) when codec_name in @scalar_codecs do @@ -380,14 +380,14 @@ defmodule EdgeDB.EdgeQL.Generator do register_typespec(full_type_name, {typedoc, subcodec_typespec}) - %{type: :builtin, typespec: full_type_name, registered: true} + %{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, &":#{&1}")]}) - %{type: :builtin, typespec: full_type_name, registered: true} + %{type: :builtin, typespec: full_type_name, is_registered: true} end defp codec_to_shape(%Codecs.Array{codec: subcodec}, codec_storage) do diff --git a/priv/codegen/templates/_builtin.eex b/priv/codegen/templates/_builtin.eex index b5f2354c..9fb6cb7d 100644 --- a/priv/codegen/templates/_builtin.eex +++ b/priv/codegen/templates/_builtin.eex @@ -1,5 +1,5 @@ <%= if @builtin[:is_list] do %>list(<% end %> -<%= if @builtin[:registered] do %><%= @module_name %>.<% end %><%= @builtin.typespec %> +<%= if @builtin[:is_registered] do %><%= @module_name %>.<% end %><%= @builtin.typespec %> <%= if @builtin[:is_list] do %>)<% end %> <%= if @builtin[:is_optional] do %> | nil diff --git a/priv/codegen/templates/_object.eex b/priv/codegen/templates/_object.eex index 5225d297..0afd7033 100644 --- a/priv/codegen/templates/_object.eex +++ b/priv/codegen/templates/_object.eex @@ -13,6 +13,7 @@ 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, diff --git a/priv/codegen/templates/_schema.eex b/priv/codegen/templates/_schema.eex index e8b422ad..0f73ec5b 100644 --- a/priv/codegen/templates/_schema.eex +++ b/priv/codegen/templates/_schema.eex @@ -8,7 +8,7 @@ paths: @paths ++ [name]) %>, <% {name, schema} -> %> - <%= name %>: %Result.<%= Macro.camelize(name) %><%= @render_schema.( + <%= name %>: %Result.<%= Enum.map_join(@paths ++ [name],".", &(Macro.camelize(&1))) %><%= @render_schema.( schema: schema, render_schema: @render_schema, paths: @paths ++ [name]) From eafab89e2e9b7a27a8024cd779a3ec901a67770d Mon Sep 17 00:00:00 2001 From: Nik Sidnev Date: Thu, 25 Aug 2022 18:29:48 +0300 Subject: [PATCH 09/15] implement generation of EdgeQL queries modules --- .credo.exs | 4 +- .gitignore | 2 +- CHANGELOG.md | 6 + config/config.exs | 7 + edgedb.toml | 2 +- lib/edgedb.ex | 2 +- lib/edgedb/connection.ex | 44 +- lib/edgedb/edgeql/generator.ex | 550 ++++++++++ lib/edgedb/protocol.ex | 37 +- lib/edgedb/protocol/codecs/enum.ex | 23 +- lib/edgedb/protocol/codecs/scalar.ex | 3 +- lib/edgedb/query.ex | 2 + lib/edgedb/result.ex | 172 ++- lib/edgedb/types/named_tuple.ex | 12 +- lib/mix/edgedb/generate.ex | 120 +++ mix.exs | 23 +- mix.lock | 1 + pages/md/codegen.md | 87 ++ pages/md/main.md | 5 - priv/codegen/templates/_builtin.eex | 1 + priv/codegen/templates/_object.eex | 19 + priv/codegen/templates/_schema.eex | 11 + priv/codegen/templates/_set.eex | 7 + priv/codegen/templates/_shape.eex | 34 + priv/codegen/templates/query.ex.eex | 165 +++ priv/edgedb/schema/migrations/00003.edgeql | 6 - test/codegen/codegen_test.exs | 62 ++ test/edgedb/types/named_tuple_test.exs | 4 +- .../edgeql/scalars/select_int_named.edgeql | 1 + .../scalars/select_int_named.edgeql.ex.assert | 64 ++ .../scalars/select_int_positional.edgeql | 1 + .../select_int_positional.edgeql.ex.assert | 59 ++ .../select_optional_string_named.edgeql | 1 + ...ect_optional_string_named.edgeql.ex.assert | 64 ++ .../select_optional_string_positional.edgeql | 1 + ...ptional_string_positional.edgeql.ex.assert | 59 ++ .../edgeql/select_string_from_root.edgeql | 1 + .../select_string_from_root.edgeql.ex.assert | 54 + .../select_standart_types_named.edgeql | 95 ++ ...lect_standart_types_named.edgeql.ex.assert | 517 +++++++++ .../select_standart_types_positional.edgeql | 95 ++ ...standart_types_positional.edgeql.ex.assert | 711 +++++++++++++ .../select_startart_types_named_simple.edgeql | 11 + ...artart_types_named_simple.edgeql.ex.assert | 86 ++ .../edgeql/types/insert_f_named.edgeql | 11 + .../types/insert_f_named.edgeql.ex.assert | 88 ++ .../edgeql/types/insert_f_positional.edgeql | 11 + .../insert_f_positional.edgeql.ex.assert | 81 ++ .../codegen/edgeql/types/select_result.edgeql | 355 +++++++ .../types/select_result.edgeql.ex.assert | 988 ++++++++++++++++++ test/support/schema/codegen.esdl | 333 ++++++ .../support}/schema/default.esdl | 44 +- .../support}/schema/migrations/00001.edgeql | 0 .../support}/schema/migrations/00002.edgeql | 0 test/support/schema/migrations/00003.edgeql | 228 ++++ {priv => test/support}/scripts/drop-roles.sh | 0 .../support}/scripts/edgedb_docs.exs | 0 .../support}/scripts/edgeql/drop-roles.edgeql | 0 .../scripts/edgeql/setup-roles.edgeql | 0 {priv => test/support}/scripts/setup-roles.sh | 0 60 files changed, 5285 insertions(+), 85 deletions(-) create mode 100644 lib/edgedb/edgeql/generator.ex create mode 100644 lib/mix/edgedb/generate.ex create mode 100644 pages/md/codegen.md create mode 100644 priv/codegen/templates/_builtin.eex create mode 100644 priv/codegen/templates/_object.eex create mode 100644 priv/codegen/templates/_schema.eex create mode 100644 priv/codegen/templates/_set.eex create mode 100644 priv/codegen/templates/_shape.eex create mode 100644 priv/codegen/templates/query.ex.eex delete mode 100644 priv/edgedb/schema/migrations/00003.edgeql create mode 100644 test/codegen/codegen_test.exs create mode 100644 test/support/codegen/edgeql/scalars/select_int_named.edgeql create mode 100644 test/support/codegen/edgeql/scalars/select_int_named.edgeql.ex.assert create mode 100644 test/support/codegen/edgeql/scalars/select_int_positional.edgeql create mode 100644 test/support/codegen/edgeql/scalars/select_int_positional.edgeql.ex.assert create mode 100644 test/support/codegen/edgeql/scalars/select_optional_string_named.edgeql create mode 100644 test/support/codegen/edgeql/scalars/select_optional_string_named.edgeql.ex.assert create mode 100644 test/support/codegen/edgeql/scalars/select_optional_string_positional.edgeql create mode 100644 test/support/codegen/edgeql/scalars/select_optional_string_positional.edgeql.ex.assert create mode 100644 test/support/codegen/edgeql/select_string_from_root.edgeql create mode 100644 test/support/codegen/edgeql/select_string_from_root.edgeql.ex.assert create mode 100644 test/support/codegen/edgeql/standart/select_standart_types_named.edgeql create mode 100644 test/support/codegen/edgeql/standart/select_standart_types_named.edgeql.ex.assert create mode 100644 test/support/codegen/edgeql/standart/select_standart_types_positional.edgeql create mode 100644 test/support/codegen/edgeql/standart/select_standart_types_positional.edgeql.ex.assert create mode 100644 test/support/codegen/edgeql/standart/select_startart_types_named_simple.edgeql create mode 100644 test/support/codegen/edgeql/standart/select_startart_types_named_simple.edgeql.ex.assert create mode 100644 test/support/codegen/edgeql/types/insert_f_named.edgeql create mode 100644 test/support/codegen/edgeql/types/insert_f_named.edgeql.ex.assert create mode 100644 test/support/codegen/edgeql/types/insert_f_positional.edgeql create mode 100644 test/support/codegen/edgeql/types/insert_f_positional.edgeql.ex.assert create mode 100644 test/support/codegen/edgeql/types/select_result.edgeql create mode 100644 test/support/codegen/edgeql/types/select_result.edgeql.ex.assert create mode 100644 test/support/schema/codegen.esdl rename {priv/edgedb => test/support}/schema/default.esdl (70%) rename {priv/edgedb => test/support}/schema/migrations/00001.edgeql (100%) rename {priv/edgedb => test/support}/schema/migrations/00002.edgeql (100%) create mode 100644 test/support/schema/migrations/00003.edgeql rename {priv => test/support}/scripts/drop-roles.sh (100%) rename {priv => test/support}/scripts/edgedb_docs.exs (100%) rename {priv => test/support}/scripts/edgeql/drop-roles.edgeql (100%) rename {priv => test/support}/scripts/edgeql/setup-roles.edgeql (100%) rename {priv => test/support}/scripts/setup-roles.sh (100%) diff --git a/.credo.exs b/.credo.exs index 16c6df25..2f5a369f 100644 --- a/.credo.exs +++ b/.credo.exs @@ -31,7 +31,7 @@ "apps/*/test/", "apps/*/web/" ], - excluded: [~r"/_build/", ~r"/deps/", ~r"/node_modules/"] + excluded: [~r"/_build/", ~r"/deps/", ~r"/node_modules/", ~r"/test/*/codegen/"] }, # # Load and configure plugins here: @@ -131,7 +131,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/.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..cf069291 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,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..af58acb3 100644 --- a/config/config.exs +++ b/config/config.exs @@ -1,3 +1,10 @@ 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 + ] diff --git a/edgedb.toml b/edgedb.toml index 17811b37..06b4ea8c 100644 --- a/edgedb.toml +++ b/edgedb.toml @@ -2,4 +2,4 @@ server-version = "3.0" [project] -schema-dir = "./priv/edgedb/schema" +schema-dir = "./test/support/schema" diff --git a/lib/edgedb.ex b/lib/edgedb.ex index 8dfc4c5d..2aae461d 100644 --- a/lib/edgedb.ex +++ b/lib/edgedb.ex @@ -789,7 +789,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..47f169ba --- /dev/null +++ b/lib/edgedb/edgeql/generator.ex @@ -0,0 +1,550 @@ +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} + 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) + + 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 + ) + + rendered_schema = + if raw_schema do + render_schema( + schema: raw_schema, + render_schema: &render_schema/1 + ) + else + nil + end + + generated_module = + generate_query_module( + query_file: query_file, + module_name: module_name, + types: types(), + shape: rendered_shape, + schema: rendered_schema, + query_function: @cardinality_to_function[query.result_cardinality], + should_render_type_for_shape: complex_shape?(raw_shape), + result_type: (complex_shape?(raw_shape) && "result()") || rendered_shape, + query: %{ + statement: query.statement, + has_positional_args: positional? and length(args) != 0, + has_named_args: not positional? and length(args) != 0, + 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 + }, + 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} + 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} + end + + defp codec_to_shape(%Codecs.Duration{}, _codec_storage) do + timex? = Application.get_env(:edgedb, :timex_duration, true) + + typename = "duration()" + + case Code.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} + 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} + 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} + 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, &":#{&1}")]}) + %{type: :builtin, typespec: full_type_name} + 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 -> + 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/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..467b8e25 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: [], @@ -33,6 +34,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(), 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..dc2563bd --- /dev/null +++ b/lib/mix/edgedb/generate.ex @@ -0,0 +1,120 @@ +# 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}: #{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..c4766fbb 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 priv/test/support/scripts/setup-roles.sh" ], "edgedb.roles.reset": [ - "cmd priv/scripts/drop-roles.sh", - "cmd priv/scripts/setup-roles.sh" + "cmd priv/test/support/scripts/drop-roles.sh", + "cmd priv/test/support/scripts/setup-roles.sh" ], "edgedb.docs": [ - "run priv/scripts/edgedb_docs.exs" + "run priv/test/suppport/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/priv/codegen/templates/_builtin.eex b/priv/codegen/templates/_builtin.eex new file mode 100644 index 00000000..02ba25f9 --- /dev/null +++ b/priv/codegen/templates/_builtin.eex @@ -0,0 +1 @@ +<%= @builtin.typespec %> diff --git a/priv/codegen/templates/_object.eex b/priv/codegen/templates/_object.eex new file mode 100644 index 00000000..eb7d7f1b --- /dev/null +++ b/priv/codegen/templates/_object.eex @@ -0,0 +1,19 @@ +%{ + <%= for {name, field} <- @object.fields do %> + + <%= if field[:is_link_property] do %> + "@<%= name %>": + <% else %> + <%= name %>: + <% end %> + + <%= @render_shape.( + shape: field, + render_shape: @render_shape, + render_builtin: @render_builtin, + render_object: @render_object, + render_set: @render_set + ) %>, + + <% end %> +} diff --git a/priv/codegen/templates/_schema.eex b/priv/codegen/templates/_schema.eex new file mode 100644 index 00000000..f53bba2e --- /dev/null +++ b/priv/codegen/templates/_schema.eex @@ -0,0 +1,11 @@ +[ + <%= for type <- @schema do %> + <%= case type do %> + <% {name, schema} -> %> + <%= name %>: <%= @render_schema.(schema: schema, render_schema: @render_schema) %>, + + <% name -> %> + :<%= name %>, + <% end %> + <% end %> +] diff --git a/priv/codegen/templates/_set.eex b/priv/codegen/templates/_set.eex new file mode 100644 index 00000000..27aca7d1 --- /dev/null +++ b/priv/codegen/templates/_set.eex @@ -0,0 +1,7 @@ +<%= @render_shape.( + shape: @set.shape, + render_shape: @render_shape, + render_builtin: @render_builtin, + render_object: @render_object, + render_set: @render_set +) %> diff --git a/priv/codegen/templates/_shape.eex b/priv/codegen/templates/_shape.eex new file mode 100644 index 00000000..64259941 --- /dev/null +++ b/priv/codegen/templates/_shape.eex @@ -0,0 +1,34 @@ +<%= if @shape[:is_list] do %> +[ +<% end %> + +<%= case @shape do %> + <% %{type: :builtin} = builtin -> %> + <%= @render_builtin.(builtin: builtin) %> + + <% %{type: :object} = object -> %> + <%= @render_object.( + object: object, + render_shape: @render_shape, + render_builtin: @render_builtin, + render_object: @render_object, + render_set: @render_set + ) %> + + <% %{type: :set} = set -> %> + <%= @render_set.( + set: set, + render_shape: @render_shape, + render_builtin: @render_builtin, + render_object: @render_object, + render_set: @render_set + ) %> +<% end %> + +<%= if @shape[:is_list] do %> +] +<% end %> + +<%= if @shape[:is_optional] do %> +| nil +<% end %> diff --git a/priv/codegen/templates/query.ex.eex b/priv/codegen/templates/query.ex.eex new file mode 100644 index 00000000..4d74c878 --- /dev/null +++ b/priv/codegen/templates/query.ex.eex @@ -0,0 +1,165 @@ +# 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} + ``` + """ + + <%= for {type_name, {typedoc, typespec}} <- @types do %> + @typedoc """ + ```edgeql + <%= typedoc %> + ``` + """ + @type <%= type_name %> :: <%= typespec %> + <% end %> + + <%= if @should_render_type_for_shape do %> + @type result() :: <%= @shape %> + <% 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 %> + + <%= if not is_nil(@schema) do %> + @schema <%= @schema %> + defp do_query(client, args, opts) do + opts = Keyword.merge(opts, __transform_result__: [schema: @schema]) + EdgeDB.<%= @query_function %>(client, @query, args, opts) + end + <% else %> + defp do_query(client, args, opts) do + EdgeDB.<%= @query_function %>(client, @query, args, opts) + 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/test/codegen/codegen_test.exs b/test/codegen/codegen_test.exs new file mode 100644 index 00000000..3f2c0b11 --- /dev/null +++ b/test/codegen/codegen_test.exs @@ -0,0 +1,62 @@ +defmodule Tests.CodegenTest do + use Tests.Support.EdgeDBCase + + @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} do + 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 + } = + Tests.Codegen.Queries.Standart.SelectStartartTypesNamedSimple.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..1f3356d1 --- /dev/null +++ b/test/support/codegen/edgeql/scalars/select_int_named.edgeql.ex.assert @@ -0,0 +1,64 @@ +# 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} + ``` + """ + + @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 + 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..81b27b0a --- /dev/null +++ b/test/support/codegen/edgeql/scalars/select_int_positional.edgeql.ex.assert @@ -0,0 +1,59 @@ +# 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} + ``` + """ + + @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 + 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..a74ce8ec --- /dev/null +++ b/test/support/codegen/edgeql/scalars/select_optional_string_named.edgeql.ex.assert @@ -0,0 +1,64 @@ +# 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} + ``` + """ + + @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 + 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..48f77b2f --- /dev/null +++ b/test/support/codegen/edgeql/scalars/select_optional_string_positional.edgeql.ex.assert @@ -0,0 +1,59 @@ +# 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} + ``` + """ + + @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 + 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..3ce63f8a --- /dev/null +++ b/test/support/codegen/edgeql/select_string_from_root.edgeql.ex.assert @@ -0,0 +1,54 @@ +# 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} + ``` + """ + + @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 + 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..63fcd512 --- /dev/null +++ b/test/support/codegen/edgeql/standart/select_standart_types_named.edgeql.ex.assert @@ -0,0 +1,517 @@ +# 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} + ``` + """ + + @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, __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..d6d5b52b --- /dev/null +++ b/test/support/codegen/edgeql/standart/select_standart_types_positional.edgeql.ex.assert @@ -0,0 +1,711 @@ +# 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} + ``` + """ + + @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, __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..f72c545c --- /dev/null +++ b/test/support/codegen/edgeql/standart/select_startart_types_named_simple.edgeql.ex.assert @@ -0,0 +1,86 @@ +# 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} + ``` + """ + + @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, __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..fb0f2576 --- /dev/null +++ b/test/support/codegen/edgeql/types/insert_f_named.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/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} + ``` + """ + + @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 + 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..c7ec3641 --- /dev/null +++ b/test/support/codegen/edgeql/types/insert_f_positional.edgeql.ex.assert @@ -0,0 +1,81 @@ +# 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} + ``` + """ + + @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 + 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..61d71596 --- /dev/null +++ b/test/support/codegen/edgeql/types/select_result.edgeql.ex.assert @@ -0,0 +1,988 @@ +# 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} + ``` + """ + + @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, __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/priv/scripts/drop-roles.sh b/test/support/scripts/drop-roles.sh similarity index 100% rename from priv/scripts/drop-roles.sh rename to test/support/scripts/drop-roles.sh diff --git a/priv/scripts/edgedb_docs.exs b/test/support/scripts/edgedb_docs.exs similarity index 100% rename from priv/scripts/edgedb_docs.exs rename to test/support/scripts/edgedb_docs.exs 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/priv/scripts/setup-roles.sh b/test/support/scripts/setup-roles.sh similarity index 100% rename from priv/scripts/setup-roles.sh rename to test/support/scripts/setup-roles.sh From 198229a2981de2c52814144fa0e4cfdfa8d6ba59 Mon Sep 17 00:00:00 2001 From: Nik Sidnev Date: Tue, 26 Sep 2023 12:24:42 -0400 Subject: [PATCH 10/15] fix credo warnings --- .credo.exs | 8 +++++++- test/codegen/codegen_test.exs | 4 +++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/.credo.exs b/.credo.exs index 2f5a369f..faea0351 100644 --- a/.credo.exs +++ b/.credo.exs @@ -31,7 +31,13 @@ "apps/*/test/", "apps/*/web/" ], - excluded: [~r"/_build/", ~r"/deps/", ~r"/node_modules/", ~r"/test/*/codegen/"] + excluded: [ + ~r"/_build/", + ~r"/deps/", + ~r"/node_modules/", + ~r"/test/codegen/queries/", + ~r"/test/support/scripts/" + ] }, # # Load and configure plugins here: diff --git a/test/codegen/codegen_test.exs b/test/codegen/codegen_test.exs index 3f2c0b11..b8ca10f1 100644 --- a/test/codegen/codegen_test.exs +++ b/test/codegen/codegen_test.exs @@ -1,6 +1,8 @@ defmodule Tests.CodegenTest do use Tests.Support.EdgeDBCase + alias Tests.Codegen.Queries.Standart.SelectStartartTypesNamedSimple + @queries_path Application.compile_env!(:edgedb, :generation)[:queries_path] queries = @@ -38,7 +40,7 @@ defmodule Tests.CodegenTest do e: ^e, f: ^f } = - Tests.Codegen.Queries.Standart.SelectStartartTypesNamedSimple.query!(client, + SelectStartartTypesNamedSimple.query!(client, e: e, f: f ) From 1034cea0def47fed1b0c45bdbe8299ee37981d77 Mon Sep 17 00:00:00 2001 From: Nik Sidnev Date: Fri, 29 Sep 2023 20:16:28 -0400 Subject: [PATCH 11/15] update CI --- .github/workflows/tests.yml | 4 +- CHANGELOG.md | 12 ++-- lib/edgedb/edgeql/generator.ex | 4 +- mix.exs | 8 +-- pages/rst/api/edgedb-types.rst | 4 +- pages/rst/codegen.rst | 92 ++++++++++++++++++++++++++++ pages/rst/index.rst | 8 +-- test/codegen/codegen_test.exs | 18 +++--- test/support/scripts/drop-roles.sh | 2 +- test/support/scripts/edgedb_docs.exs | 6 ++ test/support/scripts/setup-roles.sh | 2 +- 11 files changed, 129 insertions(+), 31 deletions(-) create mode 100644 pages/rst/codegen.rst 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/CHANGELOG.md b/CHANGELOG.md index cf069291..b5aad27f 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,12 +26,6 @@ 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/lib/edgedb/edgeql/generator.ex b/lib/edgedb/edgeql/generator.ex index 47f169ba..db0ac00d 100644 --- a/lib/edgedb/edgeql/generator.ex +++ b/lib/edgedb/edgeql/generator.ex @@ -61,7 +61,7 @@ defmodule EdgeDB.EdgeQL.Generator do 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()} + @spec generate(Keyword.t()) :: {:ok, %{Path.t() => Path.t()}} | {:error, term()} def generate(opts) do silent? = Keyword.get(opts, :silent, false) @@ -332,7 +332,7 @@ defmodule EdgeDB.EdgeQL.Generator do typename = "duration()" - case Code.loaded?(Timex) do + 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]}) diff --git a/mix.exs b/mix.exs index c4766fbb..8b86f187 100644 --- a/mix.exs +++ b/mix.exs @@ -167,14 +167,14 @@ defmodule EdgeDB.MixProject do defp aliases do [ "edgedb.roles.setup": [ - "cmd priv/test/support/scripts/setup-roles.sh" + "cmd test/support/scripts/setup-roles.sh" ], "edgedb.roles.reset": [ - "cmd priv/test/support/scripts/drop-roles.sh", - "cmd priv/test/support/scripts/setup-roles.sh" + "cmd test/support/scripts/drop-roles.sh", + "cmd test/support/scripts/setup-roles.sh" ], "edgedb.docs": [ - "run priv/test/suppport/scripts/edgedb_docs.exs" + "run test/support/scripts/edgedb_docs.exs" ] ] end 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/test/codegen/codegen_test.exs b/test/codegen/codegen_test.exs index b8ca10f1..a8e0e786 100644 --- a/test/codegen/codegen_test.exs +++ b/test/codegen/codegen_test.exs @@ -1,7 +1,7 @@ defmodule Tests.CodegenTest do use Tests.Support.EdgeDBCase - alias Tests.Codegen.Queries.Standart.SelectStartartTypesNamedSimple + skip_before(version: 3, scope: :module) @queries_path Application.compile_env!(:edgedb, :generation)[:queries_path] @@ -25,7 +25,15 @@ defmodule Tests.CodegenTest do %{files: files} end - test "codegen returns a complex shape as atomized maps", %{client: client} do + 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 @@ -39,11 +47,7 @@ defmodule Tests.CodegenTest do d: [4, 5, 6], e: ^e, f: ^f - } = - SelectStartartTypesNamedSimple.query!(client, - e: e, - f: f - ) + } = mod.query!(client, e: e, f: f) end for query_path <- queries do diff --git a/test/support/scripts/drop-roles.sh b/test/support/scripts/drop-roles.sh index 6f27712f..facdd066 100755 --- a/test/support/scripts/drop-roles.sh +++ b/test/support/scripts/drop-roles.sh @@ -2,4 +2,4 @@ set -e -edgedb query --file priv/scripts/edgeql/drop-roles.edgeql +edgedb query --file test/support/scripts/edgeql/drop-roles.edgeql diff --git a/test/support/scripts/edgedb_docs.exs b/test/support/scripts/edgedb_docs.exs index f6f95708..335f5cd9 100644 --- a/test/support/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/test/support/scripts/setup-roles.sh b/test/support/scripts/setup-roles.sh index 3fc5b897..59191154 100755 --- a/test/support/scripts/setup-roles.sh +++ b/test/support/scripts/setup-roles.sh @@ -2,4 +2,4 @@ set -e -edgedb query --file priv/scripts/edgeql/setup-roles.edgeql +edgedb query --file test/support/scripts/edgeql/setup-roles.edgeql From 368207ce0da8d8944edd52f84416393428201b64 Mon Sep 17 00:00:00 2001 From: Devi Prasad Date: Fri, 6 Oct 2023 23:47:55 -0500 Subject: [PATCH 12/15] chore: clean up merge --- lib/edgedb/edgeql/generator.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/edgedb/edgeql/generator.ex b/lib/edgedb/edgeql/generator.ex index 649e8e13..db4e8e0c 100644 --- a/lib/edgedb/edgeql/generator.ex +++ b/lib/edgedb/edgeql/generator.ex @@ -341,7 +341,7 @@ defmodule EdgeDB.EdgeQL.Generator do typename = "duration()" - case Code.loaded?(Timex) do + 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]}) From 56af269fbd1a0e43b08e642f51f88506926c28e1 Mon Sep 17 00:00:00 2001 From: Nik Sidnev Date: Mon, 9 Oct 2023 20:08:20 -0400 Subject: [PATCH 13/15] use error renderer for codegen --- lib/edgedb.ex | 37 +++++++++++-------- lib/edgedb/edgeql/generator.ex | 8 +++- lib/edgedb/error.ex | 5 ++- lib/edgedb/query.ex | 6 ++- lib/mix/edgedb/generate.ex | 5 +-- priv/codegen/templates/query.ex.eex | 5 ++- .../scalars/select_int_named.edgeql.ex.assert | 3 ++ .../select_int_positional.edgeql.ex.assert | 3 ++ ...ect_optional_string_named.edgeql.ex.assert | 3 ++ ...ptional_string_positional.edgeql.ex.assert | 3 ++ .../select_string_from_root.edgeql.ex.assert | 3 ++ ...lect_standart_types_named.edgeql.ex.assert | 4 +- ...standart_types_positional.edgeql.ex.assert | 4 +- ...artart_types_named_simple.edgeql.ex.assert | 4 +- .../types/insert_f_named.edgeql.ex.assert | 3 ++ .../insert_f_positional.edgeql.ex.assert | 3 ++ .../types/select_result.edgeql.ex.assert | 4 +- 17 files changed, 75 insertions(+), 28 deletions(-) diff --git a/lib/edgedb.ex b/lib/edgedb.ex index 2aae461d..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) diff --git a/lib/edgedb/edgeql/generator.ex b/lib/edgedb/edgeql/generator.ex index db0ac00d..05d4513b 100644 --- a/lib/edgedb/edgeql/generator.ex +++ b/lib/edgedb/edgeql/generator.ex @@ -154,7 +154,13 @@ defmodule EdgeDB.EdgeQL.Generator do List.flatten([query_parts, query_name]) end - query = %EdgeDB.Query{statement: statement, required: true, inline_type_names: true} + 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{}), diff --git a/lib/edgedb/error.ex b/lib/edgedb/error.ex index 94e4b060..ad464ef1 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,7 @@ 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 +274,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/query.ex b/lib/edgedb/query.ex index 467b8e25..a2091139 100644 --- a/lib/edgedb/query.ex +++ b/lib/edgedb/query.ex @@ -23,7 +23,8 @@ defmodule EdgeDB.Query do output_codec: nil, codec_storage: nil, cached: false, - params: [] + params: [], + __file__: nil, ] @type t() :: %__MODULE__{ @@ -42,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/mix/edgedb/generate.ex b/lib/mix/edgedb/generate.ex index dc2563bd..559e8ec8 100644 --- a/lib/mix/edgedb/generate.ex +++ b/lib/mix/edgedb/generate.ex @@ -94,9 +94,8 @@ defmodule Mix.Tasks.Edgedb.Generate do ) {:error, {query_file, %EdgeDB.Error{} = error}} -> - Mix.shell().error( - "Error while generating module for query from #{query_file}: #{Exception.message(error)}" - ) + Mix.shell().error("Error while generating module for query from #{query_file}!") + Mix.shell().error(Exception.message(error)) end end diff --git a/priv/codegen/templates/query.ex.eex b/priv/codegen/templates/query.ex.eex index 4d74c878..5a3162cb 100644 --- a/priv/codegen/templates/query.ex.eex +++ b/priv/codegen/templates/query.ex.eex @@ -17,6 +17,8 @@ defmodule <%= @module_name %> do ``` """ + @query_file "<%= @query_file %>" + <%= for {type_name, {typedoc, typespec}} <- @types do %> @typedoc """ ```edgeql @@ -154,11 +156,12 @@ defmodule <%= @module_name %> do <%= if not is_nil(@schema) do %> @schema <%= @schema %> defp do_query(client, args, opts) do - opts = Keyword.merge(opts, __transform_result__: [schema: @schema]) + opts = Keyword.merge(opts, __file__: @query_file, __transform_result__: [schema: @schema]) EdgeDB.<%= @query_function %>(client, @query, args, opts) end <% else %> defp do_query(client, args, opts) do + opts = Keyword.merge(opts, __file__: @query_file) EdgeDB.<%= @query_function %>(client, @query, args, opts) end <% end %> 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 index 1f3356d1..75b682b6 100644 --- a/test/support/codegen/edgeql/scalars/select_int_named.edgeql.ex.assert +++ b/test/support/codegen/edgeql/scalars/select_int_named.edgeql.ex.assert @@ -17,6 +17,8 @@ defmodule Tests.Codegen.Queries.Scalars.SelectIntNamed do ``` """ + @query_file "test/support/codegen/edgeql/scalars/select_int_named.edgeql" + @type keyword_args() :: [{:cp_int, integer()}] @type map_args() :: %{ @@ -59,6 +61,7 @@ defmodule Tests.Codegen.Queries.Scalars.SelectIntNamed do 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.ex.assert b/test/support/codegen/edgeql/scalars/select_int_positional.edgeql.ex.assert index 81b27b0a..ca4066b5 100644 --- a/test/support/codegen/edgeql/scalars/select_int_positional.edgeql.ex.assert +++ b/test/support/codegen/edgeql/scalars/select_int_positional.edgeql.ex.assert @@ -17,6 +17,8 @@ defmodule Tests.Codegen.Queries.Scalars.SelectIntPositional do ``` """ + @query_file "test/support/codegen/edgeql/scalars/select_int_positional.edgeql" + @doc """ Run the query. """ @@ -54,6 +56,7 @@ defmodule Tests.Codegen.Queries.Scalars.SelectIntPositional do 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.ex.assert b/test/support/codegen/edgeql/scalars/select_optional_string_named.edgeql.ex.assert index a74ce8ec..3a67054b 100644 --- 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 @@ -17,6 +17,8 @@ defmodule Tests.Codegen.Queries.Scalars.SelectOptionalStringNamed do ``` """ + @query_file "test/support/codegen/edgeql/scalars/select_optional_string_named.edgeql" + @type keyword_args() :: [{:cp_str, String.t() | nil}] @type map_args() :: %{ @@ -59,6 +61,7 @@ defmodule Tests.Codegen.Queries.Scalars.SelectOptionalStringNamed do 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.ex.assert b/test/support/codegen/edgeql/scalars/select_optional_string_positional.edgeql.ex.assert index 48f77b2f..cc069fe4 100644 --- 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 @@ -17,6 +17,8 @@ defmodule Tests.Codegen.Queries.Scalars.SelectOptionalStringPositional do ``` """ + @query_file "test/support/codegen/edgeql/scalars/select_optional_string_positional.edgeql" + @doc """ Run the query. """ @@ -54,6 +56,7 @@ defmodule Tests.Codegen.Queries.Scalars.SelectOptionalStringPositional do 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.ex.assert b/test/support/codegen/edgeql/select_string_from_root.edgeql.ex.assert index 3ce63f8a..2fc23660 100644 --- a/test/support/codegen/edgeql/select_string_from_root.edgeql.ex.assert +++ b/test/support/codegen/edgeql/select_string_from_root.edgeql.ex.assert @@ -17,6 +17,8 @@ defmodule Tests.Codegen.Queries.SelectStringFromRoot do ``` """ + @query_file "test/support/codegen/edgeql/select_string_from_root.edgeql" + @doc """ Run the query. """ @@ -49,6 +51,7 @@ defmodule Tests.Codegen.Queries.SelectStringFromRoot do 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.ex.assert b/test/support/codegen/edgeql/standart/select_standart_types_named.edgeql.ex.assert index 63fcd512..4b7ea6b3 100644 --- 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 @@ -111,6 +111,8 @@ defmodule Tests.Codegen.Queries.Standart.SelectStandartTypesNamed do ``` """ + @query_file "test/support/codegen/edgeql/standart/select_standart_types_named.edgeql" + @typedoc """ ```edgeql std::uuid @@ -511,7 +513,7 @@ defmodule Tests.Codegen.Queries.Standart.SelectStandartTypesNamed do :cp_array_int64 ] defp do_query(client, args, opts) do - opts = Keyword.merge(opts, __transform_result__: [schema: @schema]) + 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.ex.assert b/test/support/codegen/edgeql/standart/select_standart_types_positional.edgeql.ex.assert index d6d5b52b..15f0c530 100644 --- 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 @@ -111,6 +111,8 @@ defmodule Tests.Codegen.Queries.Standart.SelectStandartTypesPositional do ``` """ + @query_file "test/support/codegen/edgeql/standart/select_standart_types_positional.edgeql" + @typedoc """ ```edgeql std::uuid @@ -705,7 +707,7 @@ defmodule Tests.Codegen.Queries.Standart.SelectStandartTypesPositional do :cp_array_int64 ] defp do_query(client, args, opts) do - opts = Keyword.merge(opts, __transform_result__: [schema: @schema]) + 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.ex.assert b/test/support/codegen/edgeql/standart/select_startart_types_named_simple.edgeql.ex.assert index f72c545c..21c8bd0f 100644 --- 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 @@ -27,6 +27,8 @@ defmodule Tests.Codegen.Queries.Standart.SelectStartartTypesNamedSimple do ``` """ + @query_file "test/support/codegen/edgeql/standart/select_startart_types_named_simple.edgeql" + @type result() :: %{ a: integer(), b: %{b_a: integer(), b_b: integer()}, @@ -80,7 +82,7 @@ defmodule Tests.Codegen.Queries.Standart.SelectStartartTypesNamedSimple do @schema [:f, :e, :d, :c, :a, b: [:b_b, :b_a]] defp do_query(client, args, opts) do - opts = Keyword.merge(opts, __transform_result__: [schema: @schema]) + 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.ex.assert b/test/support/codegen/edgeql/types/insert_f_named.edgeql.ex.assert index fb0f2576..1850fe64 100644 --- a/test/support/codegen/edgeql/types/insert_f_named.edgeql.ex.assert +++ b/test/support/codegen/edgeql/types/insert_f_named.edgeql.ex.assert @@ -27,6 +27,8 @@ defmodule Tests.Codegen.Queries.Types.InsertFNamed do ``` """ + @query_file "test/support/codegen/edgeql/types/insert_f_named.edgeql" + @type result() :: %{} @type keyword_args() :: [ @@ -83,6 +85,7 @@ defmodule Tests.Codegen.Queries.Types.InsertFNamed do 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.ex.assert b/test/support/codegen/edgeql/types/insert_f_positional.edgeql.ex.assert index c7ec3641..7d4fdfc0 100644 --- a/test/support/codegen/edgeql/types/insert_f_positional.edgeql.ex.assert +++ b/test/support/codegen/edgeql/types/insert_f_positional.edgeql.ex.assert @@ -27,6 +27,8 @@ defmodule Tests.Codegen.Queries.Types.InsertFPositional do ``` """ + @query_file "test/support/codegen/edgeql/types/insert_f_positional.edgeql" + @type result() :: %{} @doc """ @@ -76,6 +78,7 @@ defmodule Tests.Codegen.Queries.Types.InsertFPositional do 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.ex.assert b/test/support/codegen/edgeql/types/select_result.edgeql.ex.assert index 61d71596..5b8b6f57 100644 --- a/test/support/codegen/edgeql/types/select_result.edgeql.ex.assert +++ b/test/support/codegen/edgeql/types/select_result.edgeql.ex.assert @@ -371,6 +371,8 @@ defmodule Tests.Codegen.Queries.Types.SelectResult do ``` """ + @query_file "test/support/codegen/edgeql/types/select_result.edgeql" + @typedoc """ ```edgeql std::uuid @@ -982,7 +984,7 @@ defmodule Tests.Codegen.Queries.Types.SelectResult do ] ] defp do_query(client, args, opts) do - opts = Keyword.merge(opts, __transform_result__: [schema: @schema]) + opts = Keyword.merge(opts, __file__: @query_file, __transform_result__: [schema: @schema]) EdgeDB.query(client, @query, args, opts) end end From f3687c353613312077ee24eea2592d67707a6ca7 Mon Sep 17 00:00:00 2001 From: Nik Sidnev Date: Mon, 9 Oct 2023 20:13:45 -0400 Subject: [PATCH 14/15] wrap enum values into quotes --- lib/edgedb/edgeql/generator.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/edgedb/edgeql/generator.ex b/lib/edgedb/edgeql/generator.ex index 05d4513b..7d53677a 100644 --- a/lib/edgedb/edgeql/generator.ex +++ b/lib/edgedb/edgeql/generator.ex @@ -383,7 +383,7 @@ defmodule EdgeDB.EdgeQL.Generator do 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, &":#{&1}")]}) + register_typespec(full_type_name, {typedoc, ["String.t()" | Enum.map(members, &":#{inspect(&1)}")]}) %{type: :builtin, typespec: full_type_name} end From f73480ccfe0e4861f55aa0bce1266702a1031a95 Mon Sep 17 00:00:00 2001 From: Nik Sidnev Date: Mon, 9 Oct 2023 20:17:03 -0400 Subject: [PATCH 15/15] apply formatter --- lib/edgedb/edgeql/generator.ex | 7 ++++++- lib/edgedb/error.ex | 6 +++++- lib/edgedb/query.ex | 2 +- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/lib/edgedb/edgeql/generator.ex b/lib/edgedb/edgeql/generator.ex index 7d53677a..c0bb839a 100644 --- a/lib/edgedb/edgeql/generator.ex +++ b/lib/edgedb/edgeql/generator.ex @@ -383,7 +383,12 @@ defmodule EdgeDB.EdgeQL.Generator do 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)}")]}) + + register_typespec( + full_type_name, + {typedoc, ["String.t()" | Enum.map(members, &":#{inspect(&1)}")]} + ) + %{type: :builtin, typespec: full_type_name} end diff --git a/lib/edgedb/error.ex b/lib/edgedb/error.ex index ad464ef1..0ef5640b 100644 --- a/lib/edgedb/error.ex +++ b/lib/edgedb/error.ex @@ -249,7 +249,11 @@ defmodule EdgeDB.Error do "#{exception.name}: #{exception.message}" end - defp generate_render_config(%__MODULE__{query: %EdgeDB.Query{}} = 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, ""} -> diff --git a/lib/edgedb/query.ex b/lib/edgedb/query.ex index a2091139..ec8884b6 100644 --- a/lib/edgedb/query.ex +++ b/lib/edgedb/query.ex @@ -24,7 +24,7 @@ defmodule EdgeDB.Query do codec_storage: nil, cached: false, params: [], - __file__: nil, + __file__: nil ] @type t() :: %__MODULE__{