From 37cc01957d34381bfaee0438125a68e46ff1b4ae Mon Sep 17 00:00:00 2001 From: Zach Daniel Date: Wed, 27 Mar 2024 16:52:28 -0400 Subject: [PATCH] improvement!: 3.0 (#227) * WIP * chore: fix mix.lock merge issues * improvement: upgrade to 3.0 * chore: remove `repo.to_tenant` * chore: continue removal of unnecessary helper * chore: use `Ash.ToTenant` --- .github/ISSUE_TEMPLATE/feature_request.md | 7 +- .github/workflows/elixir.yml | 2 +- CHANGELOG.md | 3093 +++++++---------- README.md | 2 +- benchmarks/bulk_create.exs | 16 +- config/config.exs | 12 +- .../how_to/join-manual-relationships.md | 2 +- documentation/topics/migrations_and_tasks.md | 14 +- documentation/topics/polymorphic_resources.md | 10 +- .../tutorials/get-started-with-postgres.md | 4 +- lib/aggregate.ex | 110 +- lib/calculation.ex | 9 +- lib/data_layer.ex | 176 +- lib/data_layer/info.ex | 15 + lib/expr.ex | 49 +- lib/functions/fragment.ex | 72 - .../migration_generator.ex | 10 +- lib/mix/helpers.ex | 46 +- lib/mix/tasks/ash_postgres.create.ex | 10 +- lib/mix/tasks/ash_postgres.drop.ex | 10 +- .../tasks/ash_postgres.generate_migrations.ex | 8 +- lib/mix/tasks/ash_postgres.migrate.ex | 12 +- lib/mix/tasks/ash_postgres.rollback.ex | 8 +- lib/repo.ex | 9 +- .../ensure_table_or_polymorphic.ex | 16 +- ...te_multitenancy_and_non_full_match_type.ex | 16 +- ...event_multidimensional_array_aggregates.ex | 14 +- .../validate_references.ex | 14 +- lib/verifiers/verify_postgres_version.ex | 37 + mix.exs | 8 +- mix.lock | 12 +- test/aggregate_test.exs | 646 ++-- test/ash_postgres_test.exs | 12 +- test/atomics_test.exs | 32 +- test/bulk_create_test.exs | 34 +- test/bulk_destroy_test.exs | 30 +- test/bulk_update_test.exs | 60 +- test/calculation_test.exs | 334 +- test/complex_calculations_test.exs | 108 +- test/composite_type_test.exs | 14 +- test/constraint_test.exs | 6 +- test/custom_index_test.exs | 14 +- test/distinct_test.exs | 58 +- test/embeddable_resource_test.exs | 20 +- test/enum_test.exs | 6 +- test/error_expr_test.exs | 20 +- test/filter_field_policy_test.exs | 12 +- test/filter_test.exs | 502 ++- test/load_test.exs | 162 +- test/lock_test.exs | 8 +- test/manual_relationships_test.exs | 242 +- test/manual_update_test.exs | 10 +- test/migration_generator_test.exs | 435 +-- test/multitenancy_test.exs | 84 +- test/polymorphism_test.exs | 10 +- test/primary_key_test.exs | 17 +- test/references_test.exs | 25 +- test/rel_with_parent_filter_test.exs | 14 +- test/schema_test.exs | 24 +- test/select_test.exs | 8 +- test/sort_test.exs | 102 +- test/support/api.ex | 8 - test/support/complex_calculations/api.ex | 8 - test/support/complex_calculations/domain.ex | 17 + test/support/complex_calculations/registry.ex | 13 - .../resources/certification.ex | 9 +- .../complex_calculations/resources/channel.ex | 18 +- .../resources/channel_member.ex | 11 +- .../resources/dm_channel.ex | 10 +- .../resources/documentation.ex | 17 +- .../complex_calculations/resources/skill.ex | 14 +- test/support/concat.ex | 10 +- test/support/domain.ex | 27 + test/support/multitenancy/api.ex | 8 - test/support/multitenancy/domain.ex | 10 + test/support/multitenancy/registry.ex | 10 - test/support/multitenancy/resources/org.ex | 16 +- test/support/multitenancy/resources/post.ex | 17 +- test/support/multitenancy/resources/user.ex | 11 +- test/support/registry.ex | 23 - .../comments_containing_title.ex | 2 +- test/support/resources/account.ex | 12 +- test/support/resources/author.ex | 23 +- test/support/resources/bio.ex | 9 +- test/support/resources/comment.ex | 21 +- test/support/resources/entity.ex | 7 +- test/support/resources/integer_post.ex | 5 +- test/support/resources/manager.ex | 12 +- test/support/resources/organization.ex | 19 +- test/support/resources/post.ex | 88 +- test/support/resources/post_follower.ex | 5 + test/support/resources/post_link.ex | 6 + test/support/resources/post_views.ex | 9 +- test/support/resources/profile.ex | 9 +- test/support/resources/rating.ex | 7 +- test/support/resources/record.ex | 8 +- test/support/resources/subquery/access.ex | 13 +- test/support/resources/subquery/child.ex | 8 +- .../{child_api.ex => child_domain.ex} | 8 +- test/support/resources/subquery/parent.ex | 18 +- .../{parent_api.ex => parent_domain.ex} | 8 +- test/support/resources/subquery/through.ex | 13 +- test/support/resources/temp_entity.ex | 7 +- test/support/resources/user.ex | 15 +- test/support/test_no_sandbox_repo.ex | 6 +- test/support/test_repo.ex | 6 +- test/support/types/money.ex | 2 + test/transaction_test.exs | 16 +- test/type_test.exs | 18 +- test/unique_identity_test.exs | 27 +- test/upsert_test.exs | 10 +- test_snapshot_path/extensions.json | 10 - 112 files changed, 3581 insertions(+), 3975 deletions(-) delete mode 100644 lib/functions/fragment.ex rename lib/{transformers => verifiers}/ensure_table_or_polymorphic.ex (51%) rename lib/{transformers => verifiers}/prevent_attribute_multitenancy_and_non_full_match_type.ex (81%) rename lib/{transformers => verifiers}/prevent_multidimensional_array_aggregates.ex (80%) rename lib/{transformers => verifiers}/validate_references.ex (65%) create mode 100644 lib/verifiers/verify_postgres_version.ex delete mode 100644 test/support/api.ex delete mode 100644 test/support/complex_calculations/api.ex create mode 100644 test/support/complex_calculations/domain.ex delete mode 100644 test/support/complex_calculations/registry.ex create mode 100644 test/support/domain.ex delete mode 100644 test/support/multitenancy/api.ex create mode 100644 test/support/multitenancy/domain.ex delete mode 100644 test/support/multitenancy/registry.ex delete mode 100644 test/support/registry.ex rename test/support/resources/subquery/{child_api.ex => child_domain.ex} (57%) rename test/support/resources/subquery/{parent_api.ex => parent_domain.ex} (57%) delete mode 100644 test_snapshot_path/extensions.json diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index f347dcb..a6442e0 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -1,10 +1,9 @@ --- name: Proposal about: Suggest an idea for this project -title: '' +title: "" labels: enhancement, needs review -assignees: '' - +assignees: "" --- **Is your feature request related to a problem? Please describe.** @@ -29,7 +28,7 @@ For example Or ```elixir - Api.read(:resource, bar: 10) # <- Adding `bar` here would cause + Ash.read(Resource, bar: 10) # <- Adding `bar` here would cause ``` **Additional context** diff --git a/.github/workflows/elixir.yml b/.github/workflows/elixir.yml index 29352c7..4590fca 100644 --- a/.github/workflows/elixir.yml +++ b/.github/workflows/elixir.yml @@ -11,7 +11,7 @@ jobs: strategy: fail-fast: false matrix: - postgres-version: ["10", "12", "14", "16"] + postgres-version: ["14", "15", "16"] uses: ash-project/ash/.github/workflows/ash-ci.yml@main with: postgres: true diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ea052f..adea6ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,4268 +7,3543 @@ See [Conventional Commits](Https://conventionalcommits.org) for commit guideline ## [v1.5.22](https://github.com/ash-project/ash_postgres/compare/v1.5.21...v1.5.22) (2024-03-20) - - - ### Bug Fixes: -* don't fail on aggregate query generation +- don't fail on aggregate query generation ## [v1.5.21](https://github.com/ash-project/ash_postgres/compare/v1.5.20...v1.5.21) (2024-03-20) - - - ### Bug Fixes: -* properly format migrations +- properly format migrations -* ensure exists aggregates have filters included +- ensure exists aggregates have filters included ## [v1.5.20](https://github.com/ash-project/ash_postgres/compare/v1.5.19...v1.5.20) (2024-03-20) - - - ### Bug Fixes: -* undo default of nulls_distinct option to true (#223) +- undo default of nulls_distinct option to true (#223) -* generate correct custom index name in down migration function (#222) +- generate correct custom index name in down migration function (#222) ## [v1.5.19](https://github.com/ash-project/ash_postgres/compare/v1.5.18...v1.5.19) (2024-03-19) - - - ### Bug Fixes: -* encode maps on update using fragments +- encode maps on update using fragments ### Improvements: -* Add nulls_distinct option to CustomIndex (#221) +- Add nulls_distinct option to CustomIndex (#221) ## [v1.5.18](https://github.com/ash-project/ash_postgres/compare/v1.5.17...v1.5.18) (2024-03-19) - - - ### Bug Fixes: -* don't reuse binding in many to many aggregate joins +- don't reuse binding in many to many aggregate joins -* typo in extension generator creates invalid drop +- typo in extension generator creates invalid drop -* merge base_filter and custom index's where correctly (#219) +- merge base_filter and custom index's where correctly (#219) ### Improvements: -* properly format generated migrations +- properly format generated migrations -* don't select fields in exists subquery +- don't select fields in exists subquery ## [v1.5.17](https://github.com/ash-project/ash_postgres/compare/v1.5.16...v1.5.17) (2024-03-06) - - - ### Bug Fixes: -* prevent ecto/pg from getting confused about the type of maps +- prevent ecto/pg from getting confused about the type of maps ## [v1.5.16](https://github.com/ash-project/ash_postgres/compare/v1.5.15...v1.5.16) (2024-03-05) - - - ### Bug Fixes: -* always exclude `:order_by` on bulk updateable query +- always exclude `:order_by` on bulk updateable query -* don't apply join relationship sort for lateral join +- don't apply join relationship sort for lateral join ## [v1.5.15](https://github.com/ash-project/ash_postgres/compare/v1.5.14...v1.5.15) (2024-03-01) - - - ### Improvements: -* don't double cast to the same type +- don't double cast to the same type -* detect more types +- detect more types ## [v1.5.14](https://github.com/ash-project/ash_postgres/compare/v1.5.13...v1.5.14) (2024-03-01) - - - ### Improvements: -* no need for subquery for simple table aliases +- no need for subquery for simple table aliases ## [v1.5.13](https://github.com/ash-project/ash_postgres/compare/v1.5.12...v1.5.13) (2024-02-29) - - - ### Bug Fixes: -* properly handle multiple sorts in aggregate +- properly handle multiple sorts in aggregate ## [v1.5.12](https://github.com/ash-project/ash_postgres/compare/v1.5.11...v1.5.12) (2024-02-29) - - - ### Bug Fixes: -* ensure that `from_many?` joins are properly limited +- ensure that `from_many?` joins are properly limited -* ensure that lateral joins are properly filtered +- ensure that lateral joins are properly filtered ## [v1.5.11](https://github.com/ash-project/ash_postgres/compare/v1.5.10...v1.5.11) (2024-02-29) - - - ### Bug Fixes: -* simplify(and fix) exists subquery generation +- simplify(and fix) exists subquery generation -* properly leverage subqueries throughout relationship joining +- properly leverage subqueries throughout relationship joining -* migration generator extensions in multiple repos (#214) +- migration generator extensions in multiple repos (#214) -* Migration generator for extensions in multiple repos +- Migration generator for extensions in multiple repos ### Improvements: -* optimize more cases for simple join aggregates +- optimize more cases for simple join aggregates ## [v1.5.10](https://github.com/ash-project/ash_postgres/compare/v1.5.9...v1.5.10) (2024-02-26) - - - ### Bug Fixes: -* fix error when encoding vectors +- fix error when encoding vectors -* ensure select is applied (or not) properly in bulk update/destroys +- ensure select is applied (or not) properly in bulk update/destroys ## [v1.5.9](https://github.com/ash-project/ash_postgres/compare/v1.5.8...v1.5.9) (2024-02-25) - - - ### Bug Fixes: -* handle more subquery filter cases for aggregates +- handle more subquery filter cases for aggregates -* only apply filters inside aggregate subquery +- only apply filters inside aggregate subquery ### Improvements: -* add test for aggregates +- add test for aggregates ## [v1.5.8](https://github.com/ash-project/ash_postgres/compare/v1.5.7...v1.5.8) (2024-02-24) - - - ### Bug Fixes: -* properly handle complex types in lists +- properly handle complex types in lists ## [v1.5.7](https://github.com/ash-project/ash_postgres/compare/v1.5.6...v1.5.7) (2024-02-22) - - - ### Bug Fixes: -* properly apply lateral join conditions to left lateral joins +- properly apply lateral join conditions to left lateral joins ## [v1.5.6](https://github.com/ash-project/ash_postgres/compare/v1.5.5...v1.5.6) (2024-02-21) - - - ### Bug Fixes: -* ensure select is properly set on delete_all +- ensure select is properly set on delete_all ### Improvements: -* optimize aggregate query filtering +- optimize aggregate query filtering ## [v1.5.5](https://github.com/ash-project/ash_postgres/compare/v1.5.4...v1.5.5) (2024-02-21) - - - ### Bug Fixes: -* ensure proper return value for single aggregate runs +- ensure proper return value for single aggregate runs ## [v1.5.4](https://github.com/ash-project/ash_postgres/compare/v1.5.3...v1.5.4) (2024-02-21) - - - ### Bug Fixes: -* don't sort a query that will be used with `delete_all` +- don't sort a query that will be used with `delete_all` -* ensure that `exists?` aggregates use `repo.exists?` +- ensure that `exists?` aggregates use `repo.exists?` -* properly handle to_many joins in aggregates +- properly handle to_many joins in aggregates -* honor aggregate query filters +- honor aggregate query filters -* use proper tables in joins originating from polymorphic resource (#211) +- use proper tables in joins originating from polymorphic resource (#211) -* properly transfer table names to non-inner wrapper queries (#210) +- properly transfer table names to non-inner wrapper queries (#210) ## [v1.5.3](https://github.com/ash-project/ash_postgres/compare/v1.5.2...v1.5.3) (2024-02-19) - - - ### Bug Fixes: -* handle non-inner joins in delete_all +- handle non-inner joins in delete_all -* handle non-inner joins in update +- handle non-inner joins in update ## [v1.5.2](https://github.com/ash-project/ash_postgres/compare/v1.5.1...v1.5.2) (2024-02-19) - - - ### Bug Fixes: -* don't update_all or delete_all with `order_by` +- don't update_all or delete_all with `order_by` -* handle updating from queries w/ non-inner initial joins +- handle updating from queries w/ non-inner initial joins ## [v1.5.1](https://github.com/ash-project/ash_postgres/compare/v1.5.0...v1.5.1) (2024-02-19) - - - ### Bug Fixes: -* joining to `from_many?: true` relationships not honoring limit +- joining to `from_many?: true` relationships not honoring limit ## [v1.5.0](https://github.com/ash-project/ash_postgres/compare/v1.4.0...v1.5.0) (2024-02-16) - - - ### Features: -* Make MigrationGenerator accept atoms (#201) +- Make MigrationGenerator accept atoms (#201) ### Bug Fixes: -* allow subquerying a `through` while aggregating a many to many +- allow subquerying a `through` while aggregating a many to many -* don't subquery if we need to reference `parent_as` +- don't subquery if we need to reference `parent_as` -* avoid double wrapping in subqueries +- avoid double wrapping in subqueries -* properly set 0 binding on joined subquery creation +- properly set 0 binding on joined subquery creation -* properly alter renaming attributes in migration generator +- properly alter renaming attributes in migration generator -* handle original data not available in destroy_query +- handle original data not available in destroy_query -* use primary key of source as join key +- use primary key of source as join key -* use pkey if error fields is empty +- use pkey if error fields is empty -* forgot to bind keys to a variable 🤦🏻 +- forgot to bind keys to a variable 🤦🏻 -* ensure identity keys is never missing +- ensure identity keys is never missing -* properly build subqueries when required for relationship queries +- properly build subqueries when required for relationship queries -* only migrate/rollback one repo at a time +- only migrate/rollback one repo at a time -* proper return types for updates from queries +- proper return types for updates from queries -* allow atomics to return `nil` +- allow atomics to return `nil` -* Correct the matching used in building a distinct expression (#196) +- Correct the matching used in building a distinct expression (#196) -* only rollback to savepoint on specific errors +- only rollback to savepoint on specific errors -* keep fields of `custom_index` in format that they were provided (#195) +- keep fields of `custom_index` in format that they were provided (#195) -* remap selected fields, don't subquery in aggregate joins +- remap selected fields, don't subquery in aggregate joins -* include explicit schema in snapshot folder name +- include explicit schema in snapshot folder name -* Support all_tenants? in custom index (#194) +- Support all_tenants? in custom index (#194) ### Improvements: -* update to latest ash +- update to latest ash -* mark (i)like functions as predicates (#205) +- mark (i)like functions as predicates (#205) -* detect bigserial when altering attributes +- detect bigserial when altering attributes -* Include modules in installed_extensions return type (#202) +- Include modules in installed_extensions return type (#202) -* don't drop primary key in case of removal +- don't drop primary key in case of removal -* handle if select is present on query +- handle if select is present on query -* support `Ash.Changeset.OriginalDataNotAvailable` +- support `Ash.Changeset.OriginalDataNotAvailable` -* support `count_nils` expression +- support `count_nils` expression -* `error_fields` for `custom_index` +- `error_fields` for `custom_index` -* support latest ash changes +- support latest ash changes ## [v1.4.0](https://github.com/ash-project/ash_postgres/compare/v1.3.68...v1.4.0) (2024-01-12) - - - ### Features: -* Add unit test to check lateral joins +- Add unit test to check lateral joins ### Bug Fixes: -* unset sort/distinct on related queries +- unset sort/distinct on related queries -* subquery relationships that have filters +- subquery relationships that have filters -* don't overwrite manually set schema on lateral join query +- don't overwrite manually set schema on lateral join query -* properly configure `polymorphic_name` option +- properly configure `polymorphic_name` option -* honor configured schema on bulk create +- honor configured schema on bulk create ### Improvements: -* support `all_tenants?` option for identities +- support `all_tenants?` option for identities -* support `all_tenants?` option for custom indexes +- support `all_tenants?` option for custom indexes -* support join_filters on aggregates +- support join_filters on aggregates -* use the target action when generating related queries +- use the target action when generating related queries ## [v1.3.68](https://github.com/ash-project/ash_postgres/compare/v1.3.67...v1.3.68) (2024-01-04) - - - ### Bug Fixes: -* properly gather types for operator & function overloads +- properly gather types for operator & function overloads ## [v1.3.67](https://github.com/ash-project/ash_postgres/compare/v1.3.66...v1.3.67) (2024-01-04) - - - ### Bug Fixes: -* support encoding errors with expressions in them +- support encoding errors with expressions in them ### Improvements: -* support latest ash version & operator overrides +- support latest ash version & operator overrides -* support new bulk operations +- support new bulk operations ## [v1.3.66](https://github.com/ash-project/ash_postgres/compare/v1.3.65...v1.3.66) (2023-12-30) - - - ### Improvements: -* support new `return_query/2` callback +- support new `return_query/2` callback -* support new `:no_rollback` error signal +- support new `:no_rollback` error signal -* require `name` when generating migrations +- require `name` when generating migrations -* support directly referencing aggregates from aggregates +- support directly referencing aggregates from aggregates -* support aggregates as `get_path` subject +- support aggregates as `get_path` subject ## [v1.3.65](https://github.com/ash-project/ash_postgres/compare/v1.3.64...v1.3.65) (2023-12-23) - - - ### Bug Fixes: -* various fixes for unnecessary aggregate additions +- various fixes for unnecessary aggregate additions -* use lateral joins when joining to subquery w/ parent reference +- use lateral joins when joining to subquery w/ parent reference -* replace upsert field with source in EXCLUDED fragment (#187) +- replace upsert field with source in EXCLUDED fragment (#187) -* handle strings in get_path +- handle strings in get_path -* reenable mix tasks that need calling +- reenable mix tasks that need calling ### Improvements: -* support aggregates using other aggregates +- support aggregates using other aggregates -* support string_length and string_trim +- support string_length and string_trim -* only start savepoints when necessary +- only start savepoints when necessary -* clean up nested if statements to single case statements +- clean up nested if statements to single case statements -* support for `error/2` expression +- support for `error/2` expression ## [v1.3.64](https://github.com/ash-project/ash_postgres/compare/v1.3.63...v1.3.64) (2023-12-04) - - - ### Bug Fixes: -* properly cast lazy update defaults to target type +- properly cast lazy update defaults to target type ## [v1.3.63](https://github.com/ash-project/ash_postgres/compare/v1.3.62...v1.3.63) (2023-12-03) - - - ### Bug Fixes: -* use maps for composite_type instead of tuples +- use maps for composite_type instead of tuples -* avoid empty error on upserts with `:nothing` +- avoid empty error on upserts with `:nothing` -* simplify aggregate bindings & calculation reference building +- simplify aggregate bindings & calculation reference building -* hydrate aggregate refs when adding for calculations +- hydrate aggregate refs when adding for calculations -* apply limit to `from_many?` relationship joins +- apply limit to `from_many?` relationship joins -* properly add filters for exists aggregates +- properly add filters for exists aggregates -* properly expand calculation values across aggregate invocations +- properly expand calculation values across aggregate invocations -* don't add filter for `no_attributes?` relationships +- don't add filter for `no_attributes?` relationships -* handle `no_attributes?` flag on aggregates better +- handle `no_attributes?` flag on aggregates better -* properly handle sorted relationships in aggregates +- properly handle sorted relationships in aggregates ### Improvements: -* support `composite_type/2` expression +- support `composite_type/2` expression -* support composite types +- support composite types -* optimize relationships with identity on other end +- optimize relationships with identity on other end -* allow specifying multi-column foreign keys (#180) +- allow specifying multi-column foreign keys (#180) -* add match_with option on references +- add match_with option on references -* add match_type option on references +- add match_type option on references ## [v1.3.62](https://github.com/ash-project/ash_postgres/compare/v1.3.61...v1.3.62) (2023-11-16) - - - ### Bug Fixes: -* use `synonymous_relationship_path` when looking up ref bindings +- use `synonymous_relationship_path` when looking up ref bindings -* add calculation context to calculation expressions +- add calculation context to calculation expressions ## [v1.3.61](https://github.com/ash-project/ash_postgres/compare/v1.3.60...v1.3.61) (2023-11-15) - - - ### Bug Fixes: -* don't append update_defaults automatically if `upsert_fields` was set +- don't append update_defaults automatically if `upsert_fields` was set -* don't ensure repo compiled at compile time +- don't ensure repo compiled at compile time -* handle additional case for new functional repo callback +- handle additional case for new functional repo callback -* get resource from proper bindings on `exists` query +- get resource from proper bindings on `exists` query ### Improvements: -* support a 2 argument function for the repo option +- support a 2 argument function for the repo option -* spport `CURRENT_DATE` default +- spport `CURRENT_DATE` default ## [v1.3.60](https://github.com/ash-project/ash_postgres/compare/v1.3.59...v1.3.60) (2023-10-27) - - - ### Improvements: -* support `parent` in sort expressions +- support `parent` in sort expressions ## [v1.3.59](https://github.com/ash-project/ash_postgres/compare/v1.3.58...v1.3.59) (2023-10-25) - - - ### Improvements: -* join relationships for aggregate filters +- join relationships for aggregate filters ## [v1.3.58](https://github.com/ash-project/ash_postgres/compare/v1.3.57...v1.3.58) (2023-10-24) - - - ### Bug Fixes: -* don't traverse new types for storage type +- don't traverse new types for storage type -* properly join to related references in relationship filters +- properly join to related references in relationship filters ## [v1.3.57](https://github.com/ash-project/ash_postgres/compare/v1.3.56...v1.3.57) (2023-10-17) - - - ### Improvements: -* allow for combining `AshPostgres.Repo` with other repos +- allow for combining `AshPostgres.Repo` with other repos ## [v1.3.56](https://github.com/ash-project/ash_postgres/compare/v1.3.55...v1.3.56) (2023-10-11) - - - ### Bug Fixes: -* don't raise all errors +- don't raise all errors ## [v1.3.55](https://github.com/ash-project/ash_postgres/compare/v1.3.54...v1.3.55) (2023-10-11) - - - ### Improvements: -* support atomics on upserts +- support atomics on upserts ## [v1.3.54](https://github.com/ash-project/ash_postgres/compare/v1.3.53...v1.3.54) (2023-10-10) - - - ### Bug Fixes: -* fix type specification for foreign_key_names +- fix type specification for foreign_key_names ## [v1.3.53](https://github.com/ash-project/ash_postgres/compare/v1.3.52...v1.3.53) (2023-10-10) - - - ### Bug Fixes: -* don't run main query if only `exists` aggs are specified +- don't run main query if only `exists` aggs are specified -* subquery aggregate if limit is applied +- subquery aggregate if limit is applied ### Improvements: -* update ash dependency +- update ash dependency -* support `:ci_string` as a storage_type +- support `:ci_string` as a storage_type -* support to-one references in calculations +- support to-one references in calculations ## [v1.3.52](https://github.com/ash-project/ash_postgres/compare/v1.3.51...v1.3.52) (2023-09-26) - - - ### Bug Fixes: -* use `:wrap_list` type instead of custom validaitons (#167) +- use `:wrap_list` type instead of custom validaitons (#167) ### Improvements: -* fix `upsert_fields` behavior for upserts +- fix `upsert_fields` behavior for upserts -* support data_layer_context option on transactions +- support data_layer_context option on transactions ## [v1.3.51](https://github.com/ash-project/ash_postgres/compare/v1.3.50...v1.3.51) (2023-09-20) - - - ### Improvements: -* add `AshPostgres.Tsvector` +- add `AshPostgres.Tsvector` -* add AshPostgres.Tsquery +- add AshPostgres.Tsquery -* support vector types and `vector_cosine_distance` +- support vector types and `vector_cosine_distance` ## [v1.3.50](https://github.com/ash-project/ash_postgres/compare/v1.3.49...v1.3.50) (2023-09-06) - - - ### Improvements: -* Allow resources to opt out of the primary key requirement. (#166) +- Allow resources to opt out of the primary key requirement. (#166) ## [v1.3.49](https://github.com/ash-project/ash_postgres/compare/v1.3.48...v1.3.49) (2023-09-04) - - - ### Improvements: -* implement ash lifecycle tasks +- implement ash lifecycle tasks ## [v1.3.48](https://github.com/ash-project/ash_postgres/compare/v1.3.47...v1.3.48) (2023-09-04) - - - ### Improvements: -* better error message for missing table config +- better error message for missing table config ## [v1.3.47](https://github.com/ash-project/ash_postgres/compare/v1.3.46...v1.3.47) (2023-08-31) - - - ### Bug Fixes: -* ensure we always select at least one field, and change one field +- ensure we always select at least one field, and change one field ## [v1.3.46](https://github.com/ash-project/ash_postgres/compare/v1.3.45...v1.3.46) (2023-08-31) - - - ### Bug Fixes: -* use provided values for updates +- use provided values for updates ## [v1.3.45](https://github.com/ash-project/ash_postgres/compare/v1.3.44...v1.3.45) (2023-08-31) - - - ### Bug Fixes: -* don't clobber loaded data on update +- don't clobber loaded data on update ## [v1.3.44](https://github.com/ash-project/ash_postgres/compare/v1.3.43...v1.3.44) (2023-08-31) - - - ### Bug Fixes: -* properly handle ensure nsted calls to `get_path` are jsonb +- properly handle ensure nsted calls to `get_path` are jsonb ### Improvements: -* support atomics (#165) +- support atomics (#165) ## [v1.3.43](https://github.com/ash-project/ash_postgres/compare/v1.3.42...v1.3.43) (2023-08-22) - - - ### Bug Fixes: -* properly provide constraints on all type casting +- properly provide constraints on all type casting ## [v1.3.42](https://github.com/ash-project/ash_postgres/compare/v1.3.41...v1.3.42) (2023-08-22) - - - ### Bug Fixes: -* support non-atom named aggregates +- support non-atom named aggregates -* handle case where multiple grouped aggregates depend on further aggregates +- handle case where multiple grouped aggregates depend on further aggregates ### Improvements: -* support in-line aggregates +- support in-line aggregates -* specify @behaviour in AshPostgres.Type +- specify @behaviour in AshPostgres.Type -* add `value_to_postgres_default/3` and `AshPostgres.Type` +- add `value_to_postgres_default/3` and `AshPostgres.Type` -* handle non-cast-in-type queries +- handle non-cast-in-type queries ## [v1.3.41](https://github.com/ash-project/ash_postgres/compare/v1.3.40...v1.3.41) (2023-08-08) - - - ### Bug Fixes: -* handle interaction between distinct, join filters and sort +- handle interaction between distinct, join filters and sort ### Improvements: -* custom-extension implementation (#162) +- custom-extension implementation (#162) -* custom-extension implementation +- custom-extension implementation -* allow adding custom-extension by module's reference and fixes formatting +- allow adding custom-extension by module's reference and fixes formatting -* support new `from_many?` option +- support new `from_many?` option -* subquery after distinct to handle distinct +- subquery after distinct to handle distinct ## [v1.3.40](https://github.com/ash-project/ash_postgres/compare/v1.3.39...v1.3.40) (2023-08-01) - - - ### Bug Fixes: -* properly detect optimizable first aggregates +- properly detect optimizable first aggregates ## [v1.3.39](https://github.com/ash-project/ash_postgres/compare/v1.3.38...v1.3.39) (2023-08-01) - - - ### Bug Fixes: -* properly alter deferrability on attribute alter +- properly alter deferrability on attribute alter ### Improvements: -* update ash +- update ash -* handle empty maps in migration defaults automatically +- handle empty maps in migration defaults automatically -* handle empty lists in migraiton defaults automatically +- handle empty lists in migraiton defaults automatically -* apply sort in subqueries properly +- apply sort in subqueries properly -* handle `no_attributes?` better in more places +- handle `no_attributes?` better in more places -* support the new `parent/1` expr in relationships +- support the new `parent/1` expr in relationships -* explicitly lock the source row +- explicitly lock the source row ## [v1.3.38](https://github.com/ash-project/ash_postgres/compare/v1.3.37...v1.3.38) (2023-07-21) - - - ### Bug Fixes: -* un-break aggregates referencing calculations +- un-break aggregates referencing calculations ### Improvements: -* properly handle context for referenced calculations +- properly handle context for referenced calculations ## [v1.3.37](https://github.com/ash-project/ash_postgres/compare/v1.3.36...v1.3.37) (2023-07-19) - - - ### Improvements: -* support new `distinct_sort` option +- support new `distinct_sort` option ## [v1.3.36](https://github.com/ash-project/ash_postgres/compare/v1.3.35...v1.3.36) (2023-07-19) - - - ### Bug Fixes: -* type casting improvements, handle manual relationships in `exists` +- type casting improvements, handle manual relationships in `exists` -* protected names in conflict_target (#158) +- protected names in conflict_target (#158) ## [v1.3.35](https://github.com/ash-project/ash_postgres/compare/v1.3.34...v1.3.35) (2023-07-18) - - - ### Improvements: -* support new `distinct` features from ash core +- support new `distinct` features from ash core ## [v1.3.34](https://github.com/ash-project/ash_postgres/compare/v1.3.33...v1.3.34) (2023-07-18) - - - ### Improvements: -* support unary `-/1` operator +- support unary `-/1` operator ## [v1.3.33](https://github.com/ash-project/ash_postgres/compare/v1.3.32...v1.3.33) (2023-07-14) - - - ### Bug Fixes: -* convert `Ash.Resource.Aggregate` to `Ash.Query.Aggregate` when adding +- convert `Ash.Resource.Aggregate` to `Ash.Query.Aggregate` when adding ### Improvements: -* support `deferrable` option in migration generator +- support `deferrable` option in migration generator -* support `exists` aggregates +- support `exists` aggregates ## [v1.3.32](https://github.com/ash-project/ash_postgres/compare/v1.3.31...v1.3.32) (2023-07-12) - - - ### Improvements: -* support `at/2` expression +- support `at/2` expression ## [v1.3.31](https://github.com/ash-project/ash_postgres/compare/v1.3.30...v1.3.31) (2023-07-12) - - - ### Bug Fixes: -* raise better error on invalid filter values +- raise better error on invalid filter values -* Fixes multiple schema identities migrations (#156) +- Fixes multiple schema identities migrations (#156) -* fix Logger deprecations for elixir 1.15 (#155) +- fix Logger deprecations for elixir 1.15 (#155) -* interpolate table names with `inspect` in generated migrations (#152) +- interpolate table names with `inspect` in generated migrations (#152) ### Improvements: -* better `ash_functions` message +- better `ash_functions` message -* support `string_split` +- support `string_split` -* add postgres expressions guide +- add postgres expressions guide -* add `simple_join_first_aggregates` option +- add `simple_join_first_aggregates` option ## [v1.3.30](https://github.com/ash-project/ash_postgres/compare/v1.3.29...v1.3.30) (2023-06-06) - - - ### Bug Fixes: -* handle changing custom index names better +- handle changing custom index names better -* validate custom index names +- validate custom index names ## [v1.3.29](https://github.com/ash-project/ash_postgres/compare/v1.3.28...v1.3.29) (2023-06-05) - - - ### Bug Fixes: -* properly handle nested aggregate references +- properly handle nested aggregate references ## [v1.3.28](https://github.com/ash-project/ash_postgres/compare/v1.3.27...v1.3.28) (2023-05-23) - - - ### Bug Fixes: -* handle raised errors in bulk actions +- handle raised errors in bulk actions ## [v1.3.27](https://github.com/ash-project/ash_postgres/compare/v1.3.26...v1.3.27) (2023-05-17) - - - ### Improvements: -* raise better errors on conflicting locks +- raise better errors on conflicting locks ## [v1.3.26](https://github.com/ash-project/ash_postgres/compare/v1.3.25...v1.3.26) (2023-05-16) - - - ### Bug Fixes: -* use proper lock list again +- use proper lock list again -* use proper list of row level locks +- use proper list of row level locks -* check `changeset.action_type` not `changeset.action.type` +- check `changeset.action_type` not `changeset.action.type` ### Improvements: -* support more lock types +- support more lock types ## [v1.3.25](https://github.com/ash-project/ash_postgres/compare/v1.3.24...v1.3.25) (2023-05-08) - - - ### Improvements: -* support changeset.filters (for optimistic locking) +- support changeset.filters (for optimistic locking) ## [v1.3.24](https://github.com/ash-project/ash_postgres/compare/v1.3.23...v1.3.24) (2023-05-03) - - - ### Improvements: -* support bulk upserts +- support bulk upserts ## [v1.3.23](https://github.com/ash-project/ash_postgres/compare/v1.3.22...v1.3.23) (2023-05-01) - - - ### Bug Fixes: -* don't incorrectly mark references as primary key references +- don't incorrectly mark references as primary key references -* go back to old migration sorting algorithm +- go back to old migration sorting algorithm ## [v1.3.22](https://github.com/ash-project/ash_postgres/compare/v1.3.21...v1.3.22) (2023-04-28) - - - ### Improvements: -* support locking +- support locking ## [v1.3.21](https://github.com/ash-project/ash_postgres/compare/v1.3.20...v1.3.21) (2023-04-27) - - - ### Improvements: -* handle new spark versions better, more explicit snapshots +- handle new spark versions better, more explicit snapshots ## [v1.3.20](https://github.com/ash-project/ash_postgres/compare/v1.3.19...v1.3.20) (2023-04-22) - - - ### Bug Fixes: -* subquery aggregates when a distinct is being added +- subquery aggregates when a distinct is being added -* don't call `.table` on `nil` +- don't call `.table` on `nil` -* wrap `datetime_add` in parenthesis +- wrap `datetime_add` in parenthesis -* handle primary key changes properly +- handle primary key changes properly ### Improvements: -* update ash +- update ash -* don't call `.table` on `nil` `snapshot` +- don't call `.table` on `nil` `snapshot` -* use digraph for operation ordering +- use digraph for operation ordering ## [v1.3.19](https://github.com/ash-project/ash_postgres/compare/v1.3.18...v1.3.19) (2023-04-07) - - - ### Bug Fixes: -* properly handle newtypes, add test +- properly handle newtypes, add test -* honor newtypes when determining migration type +- honor newtypes when determining migration type -* handle nil ash_functions_version in another place +- handle nil ash_functions_version in another place -* handle nil ash_functions_version +- handle nil ash_functions_version ### Improvements: -* update ash +- update ash ## [v1.3.18](https://github.com/ash-project/ash_postgres/compare/v1.3.17...v1.3.18) (2023-03-23) - - - ## [v1.3.17](https://github.com/ash-project/ash_postgres/compare/v1.3.16...v1.3.17) (2023-03-20) - - - ### Bug Fixes: -* properly map `parent` bindings in `exists` +- properly map `parent` bindings in `exists` ## [v1.3.16](https://github.com/ash-project/ash_postgres/compare/v1.3.15...v1.3.16) (2023-03-03) - - - ### Improvements: -* support new date expressions +- support new date expressions ## [v1.3.15](https://github.com/ash-project/ash_postgres/compare/v1.3.14...v1.3.15) (2023-02-23) - - - ### Improvements: -* add aggregates used by sorts +- add aggregates used by sorts ## [v1.3.14](https://github.com/ash-project/ash_postgres/compare/v1.3.13...v1.3.14) (2023-02-21) - - - ### Improvements: -* Implement string_join expr (#132) +- Implement string_join expr (#132) ## [v1.3.13](https://github.com/ash-project/ash_postgres/compare/v1.3.12...v1.3.13) (2023-02-17) - - - ### Bug Fixes: -* don't use `:distinct` when `uniq?` is not `true` +- don't use `:distinct` when `uniq?` is not `true` ## [v1.3.12](https://github.com/ash-project/ash_postgres/compare/v1.3.11...v1.3.12) (2023-02-16) - - - ### Bug Fixes: -* exclude `order_by` when building aggregates +- exclude `order_by` when building aggregates ## [v1.3.11](https://github.com/ash-project/ash_postgres/compare/v1.3.10...v1.3.11) (2023-02-16) - - - ### Bug Fixes: -* properly find migration directories in umbrella apps +- properly find migration directories in umbrella apps -* don't double-cast to array for list aggregates +- don't double-cast to array for list aggregates ### Improvements: -* significantly optimize aggregate queries +- significantly optimize aggregate queries -* better type casting for concat operator +- better type casting for concat operator ## [v1.3.10](https://github.com/ash-project/ash_postgres/compare/v1.3.9...v1.3.10) (2023-02-09) - - - ### Bug Fixes: -* sorting on optimized first aggregates +- sorting on optimized first aggregates ## [v1.3.9](https://github.com/ash-project/ash_postgres/compare/v1.3.8...v1.3.9) (2023-02-09) - - - ### Bug Fixes: -* do limit/offset outside of query if distinct is required +- do limit/offset outside of query if distinct is required -* load by __order__ ascending +- load by **order** ascending ### Improvements: -* support new `uniq?` option on count/list aggregates +- support new `uniq?` option on count/list aggregates -* optimized `first` aggregates where possible +- optimized `first` aggregates where possible ## [v1.3.8](https://github.com/ash-project/ash_postgres/compare/v1.3.7...v1.3.8) (2023-02-06) - - - ### Bug Fixes: -* Actually use `AshPostgres.Repo` behaviour (#129) +- Actually use `AshPostgres.Repo` behaviour (#129) ### Improvements: -* authorization filters are now attached by ash core +- authorization filters are now attached by ash core ## [v1.3.7](https://github.com/ash-project/ash_postgres/compare/v1.3.6...v1.3.7) (2023-02-06) - - - ### Bug Fixes: -* Actually use `AshPostgres.Repo` behaviour (#129) +- Actually use `AshPostgres.Repo` behaviour (#129) ### Improvements: -* authorization filters are now attached by ash core +- authorization filters are now attached by ash core ## [v1.3.6](https://github.com/ash-project/ash_postgres/compare/v1.3.5...v1.3.6) (2023-02-03) - - - ### Bug Fixes: -* properly set next migration name +- properly set next migration name -* override `insert` function for proper ecto interop +- override `insert` function for proper ecto interop ### Improvements: -* add `migration_ignore_attributes` +- add `migration_ignore_attributes` ## [v1.3.5](https://github.com/ash-project/ash_postgres/compare/v1.3.4...v1.3.5) (2023-01-29) - - - ### Bug Fixes: -* properly convert to/from ecto, only when necessary +- properly convert to/from ecto, only when necessary ## [v1.3.4](https://github.com/ash-project/ash_postgres/compare/v1.3.3...v1.3.4) (2023-01-28) - - - ### Bug Fixes: -* support latest ecto interop changes in ash core +- support latest ecto interop changes in ash core ### Improvements: -* properly cast division to floats for elixir-y behavior +- properly cast division to floats for elixir-y behavior -* support for dynamically set repo +- support for dynamically set repo -* update ash +- update ash ## [v1.3.3](https://github.com/ash-project/ash_postgres/compare/v1.3.2...v1.3.3) (2023-01-18) - - - ### Improvements: -* update to new docs patterns +- update to new docs patterns ## [v1.3.2](https://github.com/ash-project/ash_postgres/compare/v1.3.1...v1.3.2) (2023-01-17) - - - ### Bug Fixes: -* nest subqueries when required for distinct +- nest subqueries when required for distinct -* replace `{:in, ...}` type with `{:array, ...}` +- replace `{:in, ...}` type with `{:array, ...}` ## [v1.3.1](https://github.com/ash-project/ash_postgres/compare/v1.3.0...v1.3.1) (2023-01-11) - - - ### Bug Fixes: -* allow for non attribute aggregate references for first/list +- allow for non attribute aggregate references for first/list ## [v1.3.0](https://github.com/ash-project/ash_postgres/compare/v1.3.0-rc.4...v1.3.0) (2023-01-11) - - - ### Improvements: -* update to latest ash +- update to latest ash ## [v1.3.0-rc.4](https://github.com/ash-project/ash_postgres/compare/v1.3.0-rc.3...v1.3.0-rc.4) (2023-01-09) - - - ### Bug Fixes: -* properly join to all required relationships +- properly join to all required relationships ## [v1.3.0-rc.3](https://github.com/ash-project/ash_postgres/compare/v1.3.0-rc.2...v1.3.0-rc.3) (2023-01-09) - - - ### Bug Fixes: -* properly type cast in fragments (and elsewhere) +- properly type cast in fragments (and elsewhere) ## [v1.3.0-rc.2](https://github.com/ash-project/ash_postgres/compare/v1.3.0-rc.1...v1.3.0-rc.2) (2023-01-06) - - - ### Bug Fixes: -* undo changes that caused type casting bugs +- undo changes that caused type casting bugs ## [v1.3.0-rc.1](https://github.com/ash-project/ash_postgres/compare/v1.3.0-rc.0...v1.3.0-rc.1) (2023-01-06) - - - ### Bug Fixes: -* undo changes that caused type casting bugs +- undo changes that caused type casting bugs ## [v1.3.0-rc.1](https://github.com/ash-project/ash_postgres/compare/v1.3.0-rc.0...v1.3.0-rc.1) (2023-01-06) - - - ### Bug Fixes: -* use `parent_expr` instead of `this` +- use `parent_expr` instead of `this` -* various expression & type building fixes +- various expression & type building fixes ## [v1.3.0-rc.0](https://github.com/ash-project/ash_postgres/compare/v1.2.6...v1.3.0-rc.0) (2023-01-04) - - - ### Features: -* support latest ash +- support latest ash ### Bug Fixes: -* honor calculation constraints +- honor calculation constraints -* handle lists with expressions inside +- handle lists with expressions inside ### Improvements: -* support calc constraints +- support calc constraints -* support new `cast_in_query?/2` +- support new `cast_in_query?/2` -* support calculations as aggregate targets +- support calculations as aggregate targets ## [v1.2.6](https://github.com/ash-project/ash_postgres/compare/v1.2.5...v1.2.6) (2022-12-27) - - - ### Bug Fixes: -* properly set `migrations_path` default in umbrellas +- properly set `migrations_path` default in umbrellas -* don't subquery unless we have to +- don't subquery unless we have to ## [v1.2.5](https://github.com/ash-project/ash_postgres/compare/v1.2.4...v1.2.5) (2022-12-21) - - - ### Bug Fixes: -* don't group aggregates that reference relationships in their filters +- don't group aggregates that reference relationships in their filters -* properly skip unique indexes when configured +- properly skip unique indexes when configured ### Improvements: -* add like and ilike +- add like and ilike ## [v1.2.4](https://github.com/ash-project/ash_postgres/compare/v1.2.3...v1.2.4) (2022-12-18) - - - ### Bug Fixes: -* properly add aggregates to query when referenced from calculations +- properly add aggregates to query when referenced from calculations ### Improvements: -* distinct on source of query, not relationship destination +- distinct on source of query, not relationship destination ## [v1.2.3](https://github.com/ash-project/ash_postgres/compare/v1.2.2...v1.2.3) (2022-12-15) - - - ### Bug Fixes: -* properly combine sort + to many join filter +- properly combine sort + to many join filter ## [v1.2.2](https://github.com/ash-project/ash_postgres/compare/v1.2.1...v1.2.2) (2022-12-15) - - - ### Improvements: -* udpate to latest ash, fix array issues +- udpate to latest ash, fix array issues ## [v1.2.1](https://github.com/ash-project/ash_postgres/compare/v1.2.0...v1.2.1) (2022-12-13) - - - ### Bug Fixes: -* pattern match error in `lazy_non_matching_defaults/1` +- pattern match error in `lazy_non_matching_defaults/1` -* use attribute name not attribute for default funs +- use attribute name not attribute for default funs -* *actually* fix `default_fun` upserts +- _actually_ fix `default_fun` upserts -* fix upserting update_defaults +- fix upserting update_defaults ## [v1.2.0](https://github.com/ash-project/ash_postgres/compare/v1.2.0-rc.1...v1.2.0) (2022-12-13) - - - ### Bug Fixes: -* make migration generator work better for umbrellas +- make migration generator work better for umbrellas ## [v1.2.0-rc.1](https://github.com/ash-project/ash_postgres/compare/v1.2.0-rc.0...v1.2.0-rc.1) (2022-12-10) - - - ### Bug Fixes: -* don't make migration generation recursive +- don't make migration generation recursive -* nevermind, can't make migrate recursive +- nevermind, can't make migrate recursive ### Improvements: -* make migrate task recursive as well +- make migrate task recursive as well -* mark generate_migrations as recursive for umbrellas +- mark generate_migrations as recursive for umbrellas ## [v1.2.0-rc.0](https://github.com/ash-project/ash_postgres/compare/v1.1.3...v1.2.0-rc.0) (2022-12-10) - - - ### Features: -* avg/min/max/custom aggregate support +- avg/min/max/custom aggregate support ### Bug Fixes: -* various broken behavior from new aggregate work +- various broken behavior from new aggregate work -* forgot a +- forgot a -* fix various problems with the model behind aggregates +- fix various problems with the model behind aggregates -* properly set binding names for many to many join filters +- properly set binding names for many to many join filters ### Improvements: -* better error messages from mix tasks +- better error messages from mix tasks -* validate that references refer to relationships +- validate that references refer to relationships -* avg/min/max/custom aggregate support +- avg/min/max/custom aggregate support -* upgrade and depend on ash version +- upgrade and depend on ash version -* fix lateral many to many joins +- fix lateral many to many joins -* inform users about postgres incompatibility with multidimensional arrays +- inform users about postgres incompatibility with multidimensional arrays ## [v1.1.3](https://github.com/ash-project/ash_postgres/compare/v1.1.2...v1.1.3) (2022-12-01) - - - ### Bug Fixes: -* properly turn custom index keys into atoms +- properly turn custom index keys into atoms ### Improvements: -* update ash, add test for transaction hooks +- update ash, add test for transaction hooks -* support new transaction info with hooks +- support new transaction info with hooks -* add unique constraints to changeset for custom unique indexes +- add unique constraints to changeset for custom unique indexes -* separate out concurrent index creations and do them in a separate transaction +- separate out concurrent index creations and do them in a separate transaction ## [v1.1.2](https://github.com/ash-project/ash_postgres/compare/v1.1.1...v1.1.2) (2022-11-21) - - - ### Bug Fixes: -* don't use hard-coded join assoc name (#118) +- don't use hard-coded join assoc name (#118) ### Improvements: -* add `migration_defaults` for customizing default values +- add `migration_defaults` for customizing default values ## [v1.1.1](https://github.com/ash-project/ash_postgres/compare/v1.1.0...v1.1.1) (2022-10-25) - - - ### Bug Fixes: -* && operator in expressions to point to ash_elixir_and (#115) +- && operator in expressions to point to ash_elixir_and (#115) ### Improvements: -* add check for unsupported expression +- add check for unsupported expression ## [v1.1.0](https://github.com/ash-project/ash_postgres/compare/v1.0.0...v1.1.0) (2022-10-20) - - - ### Features: -* support `now()` in latest Ash +- support `now()` in latest Ash ## [v1.0.0](https://github.com/ash-project/ash_postgres/compare/v0.43.0...v1.0.0) (2022-10-17) - ### Bug Fixes: -* no unnecessary type cast on count/sum aggregates +- no unnecessary type cast on count/sum aggregates -* don't apply `filter` to `array_agg` +- don't apply `filter` to `array_agg` ### Improvements: -* update to Ash 2.0 +- update to Ash 2.0 -* handle UUID types better +- handle UUID types better -* set lateral join source for latest ash +- set lateral join source for latest ash -* use `prepend?: true` option when applying relationship sorts +- use `prepend?: true` option when applying relationship sorts ## [v1.0.0-rc.9](https://github.com/ash-project/ash_postgres/compare/v1.0.0-rc.8...v1.0.0-rc.9) (2022-10-07) - - - ### Bug Fixes: -* handle custom calculation selects properly +- handle custom calculation selects properly -* use attribute source for identity fields +- use attribute source for identity fields ### Improvements: -* update to the latest ash +- update to the latest ash -* remove the need to dynamically expand fragments +- remove the need to dynamically expand fragments -* when casting string to uuid, dump to binary +- when casting string to uuid, dump to binary -* update to latest ash +- update to latest ash ## [v1.0.0-rc.8](https://github.com/ash-project/ash_postgres/compare/v1.0.0-rc.7...v1.0.0-rc.8) (2022-09-29) - - - ### Bug Fixes: -* never attempt to group custom operations +- never attempt to group custom operations -* wrap case statement in parens +- wrap case statement in parens ### Improvements: -* `exists` filters necessitate multiple aggregate joins (for now) +- `exists` filters necessitate multiple aggregate joins (for now) ## [v1.0.0-rc.7](https://github.com/ash-project/ash_postgres/compare/v1.0.0-rc.6...v1.0.0-rc.7) (2022-09-28) - - - ### Bug Fixes: -* properly type cast top level fragments +- properly type cast top level fragments ### Improvements: -* update to the latest ash +- update to the latest ash -* upgrade to new `exists` usage +- upgrade to new `exists` usage ## [v1.0.0-rc.6](https://github.com/ash-project/ash_postgres/compare/v1.0.0-rc.5...v1.0.0-rc.6) (2022-09-21) - - - ### Improvements: -* support latest ash +- support latest ash ## [v1.0.0-rc.5](https://github.com/ash-project/ash_postgres/compare/v1.0.0-rc.4...v1.0.0-rc.5) (2022-09-15) - - - ### Improvements: -* update to latest ash +- update to latest ash -* implement Length function (#111) +- implement Length function (#111) -* upgrade to latest ash +- upgrade to latest ash ## [v1.0.0-rc.4](https://github.com/ash-project/ash_postgres/compare/v1.0.0-rc.3...v1.0.0-rc.4) (2022-09-14) - - - ### Improvements: -* support latest ash +- support latest ash -* support manual relationships with joins +- support manual relationships with joins ## [v1.0.0-rc.3](https://github.com/ash-project/ash_postgres/compare/v1.0.0-rc.2...v1.0.0-rc.3) (2022-09-12) - - - ### Bug Fixes: -* keep unique index keys in order in migrations +- keep unique index keys in order in migrations ## [v1.0.0-rc.2](https://github.com/ash-project/ash_postgres/compare/v1.0.0-rc.1...v1.0.0-rc.2) (2022-09-06) - - - ### Improvements: -* support latest ash `exists/2` expr +- support latest ash `exists/2` expr ## [v1.0.0-rc.1](https://github.com/ash-project/ash_postgres/compare/v1.0.0-rc.0...v1.0.0-rc.1) (2022-09-04) - - - ## [v0.43.0](https://github.com/ash-project/ash_postgres/compare/v0.42.0-rc.7...v0.43.0) (2022-08-05) - - - ### Bug Fixes: -* properly order check constraints +- properly order check constraints -* remove check constraints before adding them +- remove check constraints before adding them ### Improvements: -* fix typecasting for calculations & embed access +- fix typecasting for calculations & embed access -* add custom_statements to migration generator +- add custom_statements to migration generator -* support `||` and `&&` +- support `||` and `&&` ## [v0.42.0-rc.7](https://github.com/ash-project/ash_postgres/compare/v0.42.0-rc.6...v0.42.0-rc.7) (2022-07-14) - - - ### Features: -* support `cast_in_query?/0` and `source` +- support `cast_in_query?/0` and `source` ### Bug Fixes: -* use new doc_index patterns +- use new doc_index patterns -* support upsert_identity with base_filter +- support upsert_identity with base_filter -* support upsert_identity with base filters +- support upsert_identity with base filters -* handle various join bugs +- handle various join bugs -* use attribute.name if attribute.source is nil +- use attribute.name if attribute.source is nil -* set attribute source properly +- set attribute source properly -* ensure source is always set on attributes in snapshots +- ensure source is always set on attributes in snapshots -* handle paths for aggregates w/ > 2 relationships +- handle paths for aggregates w/ > 2 relationships -* rename attributes correctly in down migration (#98) +- rename attributes correctly in down migration (#98) -* don't generate modify commands for attributes due to schema changes +- don't generate modify commands for attributes due to schema changes -* default schema to primary schema +- default schema to primary schema -* test and confirm behavior of schemas +- test and confirm behavior of schemas -* use correct bindings for filtered relationships +- use correct bindings for filtered relationships -* cast calcs in query expressions +- cast calcs in query expressions -* explicitly type cast aggregate/calc selects +- explicitly type cast aggregate/calc selects -* don't try and match reference schema to table schema +- don't try and match reference schema to table schema -* don't use `table` where we should use `schema` in migration generator +- don't use `table` where we should use `schema` in migration generator -* handle combinations of distinct & sort +- handle combinations of distinct & sort -* ensure all single actions are explicitly marked as primary? (#95) +- ensure all single actions are explicitly marked as primary? (#95) -* only rename schema when necessary +- only rename schema when necessary -* inspect un-defaultable value in error message +- inspect un-defaultable value in error message -* select custom aggregates properly +- select custom aggregates properly -* don't add reference when renaming column if unnecessary +- don't add reference when renaming column if unnecessary -* don't cast `nil` to `""` +- don't cast `nil` to `""` -* `!is_atom/1` -> `!is_boolean/1` +- `!is_atom/1` -> `!is_boolean/1` -* sanitize lists to stringify atoms +- sanitize lists to stringify atoms -* cast embedded atoms to strings first +- cast embedded atoms to strings first -* don't cast `{:in, :any}` types +- don't cast `{:in, :any}` types -* more don't cast any types +- more don't cast any types -* don't cast if there is no type +- don't cast if there is no type -* properly handle relationship filter bindings +- properly handle relationship filter bindings -* don't consider fields changed with only source -> name changes +- don't consider fields changed with only source -> name changes -* handle name -> source change in more places +- handle name -> source change in more places -* handle name -> source rename in operation ordering +- handle name -> source rename in operation ordering -* fix aggregate/base filters +- fix aggregate/base filters -* don't select more fields than necessary +- don't select more fields than necessary -* don't call `ecto_type` twice when resolving types +- don't call `ecto_type` twice when resolving types -* place expressions in the proper order in selects +- place expressions in the proper order in selects -* match on count in expr +- match on count in expr -* remove incorrect param count tracking +- remove incorrect param count tracking -* properly track param count +- properly track param count -* properly reverse parameters before/after expansion +- properly reverse parameters before/after expansion -* don't use the base ecto type +- don't use the base ecto type -* don't sort when joining +- don't sort when joining -* ensure repo is compiled (#80) +- ensure repo is compiled (#80) -* properly construct nested join relationships +- properly construct nested join relationships -* use `CiStringWrapper` type in ash_postgres +- use `CiStringWrapper` type in ash_postgres -* ensure we are returning * on upserts (#79) +- ensure we are returning \* on upserts (#79) -* handle new if types +- handle new if types -* copy query prefix to newly created query (#74) +- copy query prefix to newly created query (#74) ### Improvements: -* add default guide, and empty ash postgres guide +- add default guide, and empty ash postgres guide -* set `update_defaults` on upsert results +- set `update_defaults` on upsert results -* handle fallback ecto migration default elegantly (#94) +- handle fallback ecto migration default elegantly (#94) -* add `ignore?` option to `references` +- add `ignore?` option to `references` -* check_migrations, rename to `--check` +- check_migrations, rename to `--check` -* add explicit timeout capability declaration +- add explicit timeout capability declaration -* add static schema specification in DSL +- add static schema specification in DSL -* support static schema specification in migration generator +- support static schema specification in migration generator -* implement decimal ecto migration default (#91) +- implement decimal ecto migration default (#91) -* support float as Ecto migration default (#89) +- support float as Ecto migration default (#89) -* update ecto +- update ecto -* add atom impl for `EctoMigrationDefault` +- add atom impl for `EctoMigrationDefault` -* Add EctoMigrationDefault protocol and implement defaults (#87) +- Add EctoMigrationDefault protocol and implement defaults (#87) -* update ecto, fix dialyzer +- update ecto, fix dialyzer -* support new timeouts +- support new timeouts -* make select unique before running query +- make select unique before running query -* add doc_index +- add doc_index -* add exclusion_constraint_names (#83) +- add exclusion_constraint_names (#83) -* support referencing aggregates from aggregate filters +- support referencing aggregates from aggregate filters -* support access syntax +- support access syntax -* don't upsert defaults on conflict (#77) +- don't upsert defaults on conflict (#77) -* relax ash version requirement +- relax ash version requirement -* add custom migration types, and repo level override +- add custom migration types, and repo level override -* update to latest version of ash +- update to latest version of ash ## [v0.42.0-rc.6](https://github.com/ash-project/ash_postgres/compare/v0.42.0-rc.5...v0.42.0-rc.6) (2022-07-10) - - - ### Features: -* support `cast_in_query?/0` and `source` +- support `cast_in_query?/0` and `source` ### Bug Fixes: -* use new doc_index patterns +- use new doc_index patterns -* support upsert_identity with base_filter +- support upsert_identity with base_filter -* support upsert_identity with base filters +- support upsert_identity with base filters -* handle various join bugs +- handle various join bugs -* use attribute.name if attribute.source is nil +- use attribute.name if attribute.source is nil -* set attribute source properly +- set attribute source properly -* ensure source is always set on attributes in snapshots +- ensure source is always set on attributes in snapshots -* handle paths for aggregates w/ > 2 relationships +- handle paths for aggregates w/ > 2 relationships -* rename attributes correctly in down migration (#98) +- rename attributes correctly in down migration (#98) -* don't generate modify commands for attributes due to schema changes +- don't generate modify commands for attributes due to schema changes -* default schema to primary schema +- default schema to primary schema -* test and confirm behavior of schemas +- test and confirm behavior of schemas -* use correct bindings for filtered relationships +- use correct bindings for filtered relationships -* cast calcs in query expressions +- cast calcs in query expressions -* explicitly type cast aggregate/calc selects +- explicitly type cast aggregate/calc selects -* don't try and match reference schema to table schema +- don't try and match reference schema to table schema -* don't use `table` where we should use `schema` in migration generator +- don't use `table` where we should use `schema` in migration generator -* handle combinations of distinct & sort +- handle combinations of distinct & sort -* ensure all single actions are explicitly marked as primary? (#95) +- ensure all single actions are explicitly marked as primary? (#95) -* only rename schema when necessary +- only rename schema when necessary -* inspect un-defaultable value in error message +- inspect un-defaultable value in error message -* select custom aggregates properly +- select custom aggregates properly -* don't add reference when renaming column if unnecessary +- don't add reference when renaming column if unnecessary -* don't cast `nil` to `""` +- don't cast `nil` to `""` -* `!is_atom/1` -> `!is_boolean/1` +- `!is_atom/1` -> `!is_boolean/1` -* sanitize lists to stringify atoms +- sanitize lists to stringify atoms -* cast embedded atoms to strings first +- cast embedded atoms to strings first -* don't cast `{:in, :any}` types +- don't cast `{:in, :any}` types -* more don't cast any types +- more don't cast any types -* don't cast if there is no type +- don't cast if there is no type -* properly handle relationship filter bindings +- properly handle relationship filter bindings -* don't consider fields changed with only source -> name changes +- don't consider fields changed with only source -> name changes -* handle name -> source change in more places +- handle name -> source change in more places -* handle name -> source rename in operation ordering +- handle name -> source rename in operation ordering -* fix aggregate/base filters +- fix aggregate/base filters -* don't select more fields than necessary +- don't select more fields than necessary -* don't call `ecto_type` twice when resolving types +- don't call `ecto_type` twice when resolving types -* place expressions in the proper order in selects +- place expressions in the proper order in selects -* match on count in expr +- match on count in expr -* remove incorrect param count tracking +- remove incorrect param count tracking -* properly track param count +- properly track param count -* properly reverse parameters before/after expansion +- properly reverse parameters before/after expansion -* don't use the base ecto type +- don't use the base ecto type -* don't sort when joining +- don't sort when joining -* ensure repo is compiled (#80) +- ensure repo is compiled (#80) -* properly construct nested join relationships +- properly construct nested join relationships -* use `CiStringWrapper` type in ash_postgres +- use `CiStringWrapper` type in ash_postgres -* ensure we are returning * on upserts (#79) +- ensure we are returning \* on upserts (#79) -* handle new if types +- handle new if types -* copy query prefix to newly created query (#74) +- copy query prefix to newly created query (#74) ### Improvements: -* set `update_defaults` on upsert results +- set `update_defaults` on upsert results -* handle fallback ecto migration default elegantly (#94) +- handle fallback ecto migration default elegantly (#94) -* add `ignore?` option to `references` +- add `ignore?` option to `references` -* check_migrations, rename to `--check` +- check_migrations, rename to `--check` -* add explicit timeout capability declaration +- add explicit timeout capability declaration -* add static schema specification in DSL +- add static schema specification in DSL -* support static schema specification in migration generator +- support static schema specification in migration generator -* implement decimal ecto migration default (#91) +- implement decimal ecto migration default (#91) -* support float as Ecto migration default (#89) +- support float as Ecto migration default (#89) -* update ecto +- update ecto -* add atom impl for `EctoMigrationDefault` +- add atom impl for `EctoMigrationDefault` -* Add EctoMigrationDefault protocol and implement defaults (#87) +- Add EctoMigrationDefault protocol and implement defaults (#87) -* update ecto, fix dialyzer +- update ecto, fix dialyzer -* support new timeouts +- support new timeouts -* make select unique before running query +- make select unique before running query -* add doc_index +- add doc_index -* add exclusion_constraint_names (#83) +- add exclusion_constraint_names (#83) -* support referencing aggregates from aggregate filters +- support referencing aggregates from aggregate filters -* support access syntax +- support access syntax -* don't upsert defaults on conflict (#77) +- don't upsert defaults on conflict (#77) -* relax ash version requirement +- relax ash version requirement -* add custom migration types, and repo level override +- add custom migration types, and repo level override -* update to latest version of ash +- update to latest version of ash ## [v0.42.0-rc.5](https://github.com/ash-project/ash_postgres/compare/v0.42.0-rc.4...v0.42.0-rc.5) (2022-07-06) - - - ### Features: -* support `cast_in_query?/0` and `source` +- support `cast_in_query?/0` and `source` ### Bug Fixes: -* support upsert_identity with base_filter +- support upsert_identity with base_filter -* support upsert_identity with base filters +- support upsert_identity with base filters -* handle various join bugs +- handle various join bugs -* use attribute.name if attribute.source is nil +- use attribute.name if attribute.source is nil -* set attribute source properly +- set attribute source properly -* ensure source is always set on attributes in snapshots +- ensure source is always set on attributes in snapshots -* handle paths for aggregates w/ > 2 relationships +- handle paths for aggregates w/ > 2 relationships -* rename attributes correctly in down migration (#98) +- rename attributes correctly in down migration (#98) -* don't generate modify commands for attributes due to schema changes +- don't generate modify commands for attributes due to schema changes -* default schema to primary schema +- default schema to primary schema -* test and confirm behavior of schemas +- test and confirm behavior of schemas -* use correct bindings for filtered relationships +- use correct bindings for filtered relationships -* cast calcs in query expressions +- cast calcs in query expressions -* explicitly type cast aggregate/calc selects +- explicitly type cast aggregate/calc selects -* don't try and match reference schema to table schema +- don't try and match reference schema to table schema -* don't use `table` where we should use `schema` in migration generator +- don't use `table` where we should use `schema` in migration generator -* handle combinations of distinct & sort +- handle combinations of distinct & sort -* ensure all single actions are explicitly marked as primary? (#95) +- ensure all single actions are explicitly marked as primary? (#95) -* only rename schema when necessary +- only rename schema when necessary -* inspect un-defaultable value in error message +- inspect un-defaultable value in error message -* select custom aggregates properly +- select custom aggregates properly -* don't add reference when renaming column if unnecessary +- don't add reference when renaming column if unnecessary -* don't cast `nil` to `""` +- don't cast `nil` to `""` -* `!is_atom/1` -> `!is_boolean/1` +- `!is_atom/1` -> `!is_boolean/1` -* sanitize lists to stringify atoms +- sanitize lists to stringify atoms -* cast embedded atoms to strings first +- cast embedded atoms to strings first -* don't cast `{:in, :any}` types +- don't cast `{:in, :any}` types -* more don't cast any types +- more don't cast any types -* don't cast if there is no type +- don't cast if there is no type -* properly handle relationship filter bindings +- properly handle relationship filter bindings -* don't consider fields changed with only source -> name changes +- don't consider fields changed with only source -> name changes -* handle name -> source change in more places +- handle name -> source change in more places -* handle name -> source rename in operation ordering +- handle name -> source rename in operation ordering -* fix aggregate/base filters +- fix aggregate/base filters -* don't select more fields than necessary +- don't select more fields than necessary -* don't call `ecto_type` twice when resolving types +- don't call `ecto_type` twice when resolving types -* place expressions in the proper order in selects +- place expressions in the proper order in selects -* match on count in expr +- match on count in expr -* remove incorrect param count tracking +- remove incorrect param count tracking -* properly track param count +- properly track param count -* properly reverse parameters before/after expansion +- properly reverse parameters before/after expansion -* don't use the base ecto type +- don't use the base ecto type -* don't sort when joining +- don't sort when joining -* ensure repo is compiled (#80) +- ensure repo is compiled (#80) -* properly construct nested join relationships +- properly construct nested join relationships -* use `CiStringWrapper` type in ash_postgres +- use `CiStringWrapper` type in ash_postgres -* ensure we are returning * on upserts (#79) +- ensure we are returning \* on upserts (#79) -* handle new if types +- handle new if types -* copy query prefix to newly created query (#74) +- copy query prefix to newly created query (#74) ### Improvements: -* set `update_defaults` on upsert results. For most users, this means that where previously `updated_at` would not get set on an upsert that ultimately resulted in an update, it will now. +- set `update_defaults` on upsert results. For most users, this means that where previously `updated_at` would not get set on an upsert that ultimately resulted in an update, it will now. -* handle fallback ecto migration default elegantly (#94) +- handle fallback ecto migration default elegantly (#94) -* add `ignore?` option to `references` +- add `ignore?` option to `references` -* check_migrations, rename to `--check` +- check_migrations, rename to `--check` -* add explicit timeout capability declaration +- add explicit timeout capability declaration -* add static schema specification in DSL +- add static schema specification in DSL -* support static schema specification in migration generator +- support static schema specification in migration generator -* implement decimal ecto migration default (#91) +- implement decimal ecto migration default (#91) -* support float as Ecto migration default (#89) +- support float as Ecto migration default (#89) -* update ecto +- update ecto -* add atom impl for `EctoMigrationDefault` +- add atom impl for `EctoMigrationDefault` -* Add EctoMigrationDefault protocol and implement defaults (#87) +- Add EctoMigrationDefault protocol and implement defaults (#87) -* update ecto, fix dialyzer +- update ecto, fix dialyzer -* support new timeouts +- support new timeouts -* make select unique before running query +- make select unique before running query -* add doc_index +- add doc_index -* add exclusion_constraint_names (#83) +- add exclusion_constraint_names (#83) -* support referencing aggregates from aggregate filters +- support referencing aggregates from aggregate filters -* support access syntax +- support access syntax -* don't upsert defaults on conflict (#77) +- don't upsert defaults on conflict (#77) -* relax ash version requirement +- relax ash version requirement -* add custom migration types, and repo level override +- add custom migration types, and repo level override -* update to latest version of ash +- update to latest version of ash ## [v0.42.0-rc.4](https://github.com/ash-project/ash_postgres/compare/v0.42.0-rc.3...v0.42.0-rc.4) (2022-06-28) - - - ### Features: -* support `cast_in_query?/0` and `source` +- support `cast_in_query?/0` and `source` ### Bug Fixes: -* use attribute.name if attribute.source is nil +- use attribute.name if attribute.source is nil -* set attribute source properly +- set attribute source properly -* ensure source is always set on attributes in snapshots +- ensure source is always set on attributes in snapshots -* handle paths for aggregates w/ > 2 relationships +- handle paths for aggregates w/ > 2 relationships -* rename attributes correctly in down migration (#98) +- rename attributes correctly in down migration (#98) -* don't generate modify commands for attributes due to schema changes +- don't generate modify commands for attributes due to schema changes -* default schema to primary schema +- default schema to primary schema -* test and confirm behavior of schemas +- test and confirm behavior of schemas -* use correct bindings for filtered relationships +- use correct bindings for filtered relationships -* cast calcs in query expressions +- cast calcs in query expressions -* explicitly type cast aggregate/calc selects +- explicitly type cast aggregate/calc selects -* don't try and match reference schema to table schema +- don't try and match reference schema to table schema -* don't use `table` where we should use `schema` in migration generator +- don't use `table` where we should use `schema` in migration generator -* handle combinations of distinct & sort +- handle combinations of distinct & sort -* ensure all single actions are explicitly marked as primary? (#95) +- ensure all single actions are explicitly marked as primary? (#95) -* only rename schema when necessary +- only rename schema when necessary -* inspect un-defaultable value in error message +- inspect un-defaultable value in error message -* select custom aggregates properly +- select custom aggregates properly -* don't add reference when renaming column if unnecessary +- don't add reference when renaming column if unnecessary -* don't cast `nil` to `""` +- don't cast `nil` to `""` -* `!is_atom/1` -> `!is_boolean/1` +- `!is_atom/1` -> `!is_boolean/1` -* sanitize lists to stringify atoms +- sanitize lists to stringify atoms -* cast embedded atoms to strings first +- cast embedded atoms to strings first -* don't cast `{:in, :any}` types +- don't cast `{:in, :any}` types -* more don't cast any types +- more don't cast any types -* don't cast if there is no type +- don't cast if there is no type -* properly handle relationship filter bindings +- properly handle relationship filter bindings -* don't consider fields changed with only source -> name changes +- don't consider fields changed with only source -> name changes -* handle name -> source change in more places +- handle name -> source change in more places -* handle name -> source rename in operation ordering +- handle name -> source rename in operation ordering -* fix aggregate/base filters +- fix aggregate/base filters -* don't select more fields than necessary +- don't select more fields than necessary -* don't call `ecto_type` twice when resolving types +- don't call `ecto_type` twice when resolving types -* place expressions in the proper order in selects +- place expressions in the proper order in selects -* match on count in expr +- match on count in expr -* remove incorrect param count tracking +- remove incorrect param count tracking -* properly track param count +- properly track param count -* properly reverse parameters before/after expansion +- properly reverse parameters before/after expansion -* don't use the base ecto type +- don't use the base ecto type -* don't sort when joining +- don't sort when joining -* ensure repo is compiled (#80) +- ensure repo is compiled (#80) -* properly construct nested join relationships +- properly construct nested join relationships -* use `CiStringWrapper` type in ash_postgres +- use `CiStringWrapper` type in ash_postgres -* ensure we are returning * on upserts (#79) +- ensure we are returning \* on upserts (#79) -* handle new if types +- handle new if types -* copy query prefix to newly created query (#74) +- copy query prefix to newly created query (#74) ### Improvements: -* handle fallback ecto migration default elegantly (#94) +- handle fallback ecto migration default elegantly (#94) -* add `ignore?` option to `references` +- add `ignore?` option to `references` -* check_migrations, rename to `--check` +- check_migrations, rename to `--check` -* add explicit timeout capability declaration +- add explicit timeout capability declaration -* add static schema specification in DSL +- add static schema specification in DSL -* support static schema specification in migration generator +- support static schema specification in migration generator -* implement decimal ecto migration default (#91) +- implement decimal ecto migration default (#91) -* support float as Ecto migration default (#89) +- support float as Ecto migration default (#89) -* update ecto +- update ecto -* add atom impl for `EctoMigrationDefault` +- add atom impl for `EctoMigrationDefault` -* Add EctoMigrationDefault protocol and implement defaults (#87) +- Add EctoMigrationDefault protocol and implement defaults (#87) -* update ecto, fix dialyzer +- update ecto, fix dialyzer -* support new timeouts +- support new timeouts -* make select unique before running query +- make select unique before running query -* add doc_index +- add doc_index -* add exclusion_constraint_names (#83) +- add exclusion_constraint_names (#83) -* support referencing aggregates from aggregate filters +- support referencing aggregates from aggregate filters -* support access syntax +- support access syntax -* don't upsert defaults on conflict (#77) +- don't upsert defaults on conflict (#77) -* relax ash version requirement +- relax ash version requirement -* add custom migration types, and repo level override +- add custom migration types, and repo level override -* update to latest version of ash +- update to latest version of ash ## [v0.42.0-rc.3](https://github.com/ash-project/ash_postgres/compare/v0.42.0-rc.2...v0.42.0-rc.3) (2022-06-28) - - - ### Features: -* support `cast_in_query?/0` and `source` +- support `cast_in_query?/0` and `source` ### Bug Fixes: -* set attribute source properly +- set attribute source properly -* ensure source is always set on attributes in snapshots +- ensure source is always set on attributes in snapshots -* handle paths for aggregates w/ > 2 relationships +- handle paths for aggregates w/ > 2 relationships -* rename attributes correctly in down migration (#98) +- rename attributes correctly in down migration (#98) -* don't generate modify commands for attributes due to schema changes +- don't generate modify commands for attributes due to schema changes -* default schema to primary schema +- default schema to primary schema -* test and confirm behavior of schemas +- test and confirm behavior of schemas -* use correct bindings for filtered relationships +- use correct bindings for filtered relationships -* cast calcs in query expressions +- cast calcs in query expressions -* explicitly type cast aggregate/calc selects +- explicitly type cast aggregate/calc selects -* don't try and match reference schema to table schema +- don't try and match reference schema to table schema -* don't use `table` where we should use `schema` in migration generator +- don't use `table` where we should use `schema` in migration generator -* handle combinations of distinct & sort +- handle combinations of distinct & sort -* ensure all single actions are explicitly marked as primary? (#95) +- ensure all single actions are explicitly marked as primary? (#95) -* only rename schema when necessary +- only rename schema when necessary -* inspect un-defaultable value in error message +- inspect un-defaultable value in error message -* select custom aggregates properly +- select custom aggregates properly -* don't add reference when renaming column if unnecessary +- don't add reference when renaming column if unnecessary -* don't cast `nil` to `""` +- don't cast `nil` to `""` -* `!is_atom/1` -> `!is_boolean/1` +- `!is_atom/1` -> `!is_boolean/1` -* sanitize lists to stringify atoms +- sanitize lists to stringify atoms -* cast embedded atoms to strings first +- cast embedded atoms to strings first -* don't cast `{:in, :any}` types +- don't cast `{:in, :any}` types -* more don't cast any types +- more don't cast any types -* don't cast if there is no type +- don't cast if there is no type -* properly handle relationship filter bindings +- properly handle relationship filter bindings -* don't consider fields changed with only source -> name changes +- don't consider fields changed with only source -> name changes -* handle name -> source change in more places +- handle name -> source change in more places -* handle name -> source rename in operation ordering +- handle name -> source rename in operation ordering -* fix aggregate/base filters +- fix aggregate/base filters -* don't select more fields than necessary +- don't select more fields than necessary -* don't call `ecto_type` twice when resolving types +- don't call `ecto_type` twice when resolving types -* place expressions in the proper order in selects +- place expressions in the proper order in selects -* match on count in expr +- match on count in expr -* remove incorrect param count tracking +- remove incorrect param count tracking -* properly track param count +- properly track param count -* properly reverse parameters before/after expansion +- properly reverse parameters before/after expansion -* don't use the base ecto type +- don't use the base ecto type -* don't sort when joining +- don't sort when joining -* ensure repo is compiled (#80) +- ensure repo is compiled (#80) -* properly construct nested join relationships +- properly construct nested join relationships -* use `CiStringWrapper` type in ash_postgres +- use `CiStringWrapper` type in ash_postgres -* ensure we are returning * on upserts (#79) +- ensure we are returning \* on upserts (#79) -* handle new if types +- handle new if types -* copy query prefix to newly created query (#74) +- copy query prefix to newly created query (#74) ### Improvements: -* handle fallback ecto migration default elegantly (#94) +- handle fallback ecto migration default elegantly (#94) -* add `ignore?` option to `references` +- add `ignore?` option to `references` -* check_migrations, rename to `--check` +- check_migrations, rename to `--check` -* add explicit timeout capability declaration +- add explicit timeout capability declaration -* add static schema specification in DSL +- add static schema specification in DSL -* support static schema specification in migration generator +- support static schema specification in migration generator -* implement decimal ecto migration default (#91) +- implement decimal ecto migration default (#91) -* support float as Ecto migration default (#89) +- support float as Ecto migration default (#89) -* update ecto +- update ecto -* add atom impl for `EctoMigrationDefault` +- add atom impl for `EctoMigrationDefault` -* Add EctoMigrationDefault protocol and implement defaults (#87) +- Add EctoMigrationDefault protocol and implement defaults (#87) -* update ecto, fix dialyzer +- update ecto, fix dialyzer -* support new timeouts +- support new timeouts -* make select unique before running query +- make select unique before running query -* add doc_index +- add doc_index -* add exclusion_constraint_names (#83) +- add exclusion_constraint_names (#83) -* support referencing aggregates from aggregate filters +- support referencing aggregates from aggregate filters -* support access syntax +- support access syntax -* don't upsert defaults on conflict (#77) +- don't upsert defaults on conflict (#77) -* relax ash version requirement +- relax ash version requirement -* add custom migration types, and repo level override +- add custom migration types, and repo level override -* update to latest version of ash +- update to latest version of ash ## [v0.42.0-rc.2](https://github.com/ash-project/ash_postgres/compare/v0.42.0-rc.1...v0.42.0-rc.2) (2022-05-18) - - - ### Features: -* support `cast_in_query?/0` and `source` +- support `cast_in_query?/0` and `source` ### Bug Fixes: -* don't try and match reference schema to table schema +- don't try and match reference schema to table schema -* don't use `table` where we should use `schema` in migration generator +- don't use `table` where we should use `schema` in migration generator -* handle combinations of distinct & sort +- handle combinations of distinct & sort -* ensure all single actions are explicitly marked as primary? (#95) +- ensure all single actions are explicitly marked as primary? (#95) -* only rename schema when necessary +- only rename schema when necessary -* inspect un-defaultable value in error message +- inspect un-defaultable value in error message -* select custom aggregates properly +- select custom aggregates properly -* don't add reference when renaming column if unnecessary +- don't add reference when renaming column if unnecessary -* don't cast `nil` to `""` +- don't cast `nil` to `""` -* `!is_atom/1` -> `!is_boolean/1` +- `!is_atom/1` -> `!is_boolean/1` -* sanitize lists to stringify atoms +- sanitize lists to stringify atoms -* cast embedded atoms to strings first +- cast embedded atoms to strings first -* don't cast `{:in, :any}` types +- don't cast `{:in, :any}` types -* more don't cast any types +- more don't cast any types -* don't cast if there is no type +- don't cast if there is no type -* properly handle relationship filter bindings +- properly handle relationship filter bindings -* don't consider fields changed with only source -> name changes +- don't consider fields changed with only source -> name changes -* handle name -> source change in more places +- handle name -> source change in more places -* handle name -> source rename in operation ordering +- handle name -> source rename in operation ordering -* fix aggregate/base filters +- fix aggregate/base filters -* don't select more fields than necessary +- don't select more fields than necessary -* don't call `ecto_type` twice when resolving types +- don't call `ecto_type` twice when resolving types -* place expressions in the proper order in selects +- place expressions in the proper order in selects -* match on count in expr +- match on count in expr -* remove incorrect param count tracking +- remove incorrect param count tracking -* properly track param count +- properly track param count -* properly reverse parameters before/after expansion +- properly reverse parameters before/after expansion -* don't use the base ecto type +- don't use the base ecto type -* don't sort when joining +- don't sort when joining -* ensure repo is compiled (#80) +- ensure repo is compiled (#80) -* properly construct nested join relationships +- properly construct nested join relationships -* use `CiStringWrapper` type in ash_postgres +- use `CiStringWrapper` type in ash_postgres -* ensure we are returning * on upserts (#79) +- ensure we are returning \* on upserts (#79) -* handle new if types +- handle new if types -* copy query prefix to newly created query (#74) +- copy query prefix to newly created query (#74) ### Improvements: -* check_migrations, rename to `--check` +- check_migrations, rename to `--check` -* add explicit timeout capability declaration +- add explicit timeout capability declaration -* add static schema specification in DSL +- add static schema specification in DSL -* support static schema specification in migration generator +- support static schema specification in migration generator -* implement decimal ecto migration default (#91) +- implement decimal ecto migration default (#91) -* support float as Ecto migration default (#89) +- support float as Ecto migration default (#89) -* update ecto +- update ecto -* add atom impl for `EctoMigrationDefault` +- add atom impl for `EctoMigrationDefault` -* Add EctoMigrationDefault protocol and implement defaults (#87) +- Add EctoMigrationDefault protocol and implement defaults (#87) -* update ecto, fix dialyzer +- update ecto, fix dialyzer -* support new timeouts +- support new timeouts -* make select unique before running query +- make select unique before running query -* add doc_index +- add doc_index -* add exclusion_constraint_names (#83) +- add exclusion_constraint_names (#83) -* support referencing aggregates from aggregate filters +- support referencing aggregates from aggregate filters -* support access syntax +- support access syntax -* don't upsert defaults on conflict (#77) +- don't upsert defaults on conflict (#77) -* relax ash version requirement +- relax ash version requirement -* add custom migration types, and repo level override +- add custom migration types, and repo level override -* update to latest version of ash +- update to latest version of ash ## [v0.42.0-rc.1](https://github.com/ash-project/ash_postgres/compare/v0.42.0-rc.0...v0.42.0-rc.1) (2022-05-18) - - - ### Features: -* support `cast_in_query?/0` and `source` +- support `cast_in_query?/0` and `source` ### Bug Fixes: -* don't use `table` where we should use `schema` in migration generator +- don't use `table` where we should use `schema` in migration generator -* handle combinations of distinct & sort +- handle combinations of distinct & sort -* ensure all single actions are explicitly marked as primary? (#95) +- ensure all single actions are explicitly marked as primary? (#95) -* only rename schema when necessary +- only rename schema when necessary -* inspect un-defaultable value in error message +- inspect un-defaultable value in error message -* select custom aggregates properly +- select custom aggregates properly -* don't add reference when renaming column if unnecessary +- don't add reference when renaming column if unnecessary -* don't cast `nil` to `""` +- don't cast `nil` to `""` -* `!is_atom/1` -> `!is_boolean/1` +- `!is_atom/1` -> `!is_boolean/1` -* sanitize lists to stringify atoms +- sanitize lists to stringify atoms -* cast embedded atoms to strings first +- cast embedded atoms to strings first -* don't cast `{:in, :any}` types +- don't cast `{:in, :any}` types -* more don't cast any types +- more don't cast any types -* don't cast if there is no type +- don't cast if there is no type -* properly handle relationship filter bindings +- properly handle relationship filter bindings -* don't consider fields changed with only source -> name changes +- don't consider fields changed with only source -> name changes -* handle name -> source change in more places +- handle name -> source change in more places -* handle name -> source rename in operation ordering +- handle name -> source rename in operation ordering -* fix aggregate/base filters +- fix aggregate/base filters -* don't select more fields than necessary +- don't select more fields than necessary -* don't call `ecto_type` twice when resolving types +- don't call `ecto_type` twice when resolving types -* place expressions in the proper order in selects +- place expressions in the proper order in selects -* match on count in expr +- match on count in expr -* remove incorrect param count tracking +- remove incorrect param count tracking -* properly track param count +- properly track param count -* properly reverse parameters before/after expansion +- properly reverse parameters before/after expansion -* don't use the base ecto type +- don't use the base ecto type -* don't sort when joining +- don't sort when joining -* ensure repo is compiled (#80) +- ensure repo is compiled (#80) -* properly construct nested join relationships +- properly construct nested join relationships -* use `CiStringWrapper` type in ash_postgres +- use `CiStringWrapper` type in ash_postgres -* ensure we are returning * on upserts (#79) +- ensure we are returning \* on upserts (#79) -* handle new if types +- handle new if types -* copy query prefix to newly created query (#74) +- copy query prefix to newly created query (#74) ### Improvements: -* check_migrations, rename to `--check` +- check_migrations, rename to `--check` -* add explicit timeout capability declaration +- add explicit timeout capability declaration -* add static schema specification in DSL +- add static schema specification in DSL -* support static schema specification in migration generator +- support static schema specification in migration generator -* implement decimal ecto migration default (#91) +- implement decimal ecto migration default (#91) -* support float as Ecto migration default (#89) +- support float as Ecto migration default (#89) -* update ecto +- update ecto -* add atom impl for `EctoMigrationDefault` +- add atom impl for `EctoMigrationDefault` -* Add EctoMigrationDefault protocol and implement defaults (#87) +- Add EctoMigrationDefault protocol and implement defaults (#87) -* update ecto, fix dialyzer +- update ecto, fix dialyzer -* support new timeouts +- support new timeouts -* make select unique before running query +- make select unique before running query -* add doc_index +- add doc_index -* add exclusion_constraint_names (#83) +- add exclusion_constraint_names (#83) -* support referencing aggregates from aggregate filters +- support referencing aggregates from aggregate filters -* support access syntax +- support access syntax -* don't upsert defaults on conflict (#77) +- don't upsert defaults on conflict (#77) -* relax ash version requirement +- relax ash version requirement -* add custom migration types, and repo level override +- add custom migration types, and repo level override -* update to latest version of ash +- update to latest version of ash ## [v0.42.0-rc.0](https://github.com/ash-project/ash_postgres/compare/v0.41.7...v0.42.0-rc.0) (2022-04-26) - - - ### Features: -* support `cast_in_query?/0` and `source` +- support `cast_in_query?/0` and `source` ### Bug Fixes: -* select custom aggregates properly +- select custom aggregates properly -* don't add reference when renaming column if unnecessary +- don't add reference when renaming column if unnecessary -* don't cast `nil` to `""` +- don't cast `nil` to `""` -* `!is_atom/1` -> `!is_boolean/1` +- `!is_atom/1` -> `!is_boolean/1` -* sanitize lists to stringify atoms +- sanitize lists to stringify atoms -* cast embedded atoms to strings first +- cast embedded atoms to strings first -* don't cast `{:in, :any}` types +- don't cast `{:in, :any}` types -* more don't cast any types +- more don't cast any types -* don't cast if there is no type +- don't cast if there is no type -* properly handle relationship filter bindings +- properly handle relationship filter bindings -* don't consider fields changed with only source -> name changes +- don't consider fields changed with only source -> name changes -* handle name -> source change in more places +- handle name -> source change in more places -* handle name -> source rename in operation ordering +- handle name -> source rename in operation ordering -* fix aggregate/base filters +- fix aggregate/base filters -* don't select more fields than necessary +- don't select more fields than necessary -* don't call `ecto_type` twice when resolving types +- don't call `ecto_type` twice when resolving types -* place expressions in the proper order in selects +- place expressions in the proper order in selects -* match on count in expr +- match on count in expr -* remove incorrect param count tracking +- remove incorrect param count tracking -* properly track param count +- properly track param count -* properly reverse parameters before/after expansion +- properly reverse parameters before/after expansion -* don't use the base ecto type +- don't use the base ecto type -* don't sort when joining +- don't sort when joining -* ensure repo is compiled (#80) +- ensure repo is compiled (#80) -* properly construct nested join relationships +- properly construct nested join relationships -* use `CiStringWrapper` type in ash_postgres +- use `CiStringWrapper` type in ash_postgres -* ensure we are returning * on upserts (#79) +- ensure we are returning \* on upserts (#79) -* handle new if types +- handle new if types -* copy query prefix to newly created query (#74) +- copy query prefix to newly created query (#74) ### Improvements: -* update ecto +- update ecto -* add atom impl for `EctoMigrationDefault` +- add atom impl for `EctoMigrationDefault` -* Add EctoMigrationDefault protocol and implement defaults (#87) +- Add EctoMigrationDefault protocol and implement defaults (#87) -* update ecto, fix dialyzer +- update ecto, fix dialyzer -* support new timeouts +- support new timeouts -* make select unique before running query +- make select unique before running query -* add doc_index +- add doc_index -* add exclusion_constraint_names (#83) +- add exclusion_constraint_names (#83) -* support referencing aggregates from aggregate filters +- support referencing aggregates from aggregate filters -* support access syntax +- support access syntax -* don't upsert defaults on conflict (#77) +- don't upsert defaults on conflict (#77) -* relax ash version requirement +- relax ash version requirement -* add custom migration types, and repo level override +- add custom migration types, and repo level override -* update to latest version of ash +- update to latest version of ash ## [v0.41.7](https://github.com/ash-project/ash_postgres/compare/v0.41.6...v0.41.7) (2021-12-21) - - - ### Bug Fixes: -* ensure repo is compiled (#80) +- ensure repo is compiled (#80) -* properly construct nested join relationships +- properly construct nested join relationships -* use `CiStringWrapper` type in ash_postgres +- use `CiStringWrapper` type in ash_postgres -* ensure we are returning * on upserts (#79) +- ensure we are returning \* on upserts (#79) -* handle new if types +- handle new if types -* copy query prefix to newly created query (#74) +- copy query prefix to newly created query (#74) ### Improvements: -* don't upsert defaults on conflict (#77) +- don't upsert defaults on conflict (#77) -* relax ash version requirement +- relax ash version requirement -* add custom migration types, and repo level override +- add custom migration types, and repo level override -* update to latest version of ash +- update to latest version of ash ## [v0.41.6](https://github.com/ash-project/ash_postgres/compare/v0.41.5...v0.41.6) (2021-12-21) - - - ### Bug Fixes: -* properly construct nested join relationships +- properly construct nested join relationships -* use `CiStringWrapper` type in ash_postgres +- use `CiStringWrapper` type in ash_postgres -* ensure we are returning * on upserts (#79) +- ensure we are returning \* on upserts (#79) -* handle new if types +- handle new if types -* copy query prefix to newly created query (#74) +- copy query prefix to newly created query (#74) ### Improvements: -* don't upsert defaults on conflict (#77) +- don't upsert defaults on conflict (#77) -* relax ash version requirement +- relax ash version requirement -* add custom migration types, and repo level override +- add custom migration types, and repo level override -* update to latest version of ash +- update to latest version of ash ## [v0.41.5](https://github.com/ash-project/ash_postgres/compare/v0.41.4...v0.41.5) (2021-11-26) - - - ### Bug Fixes: -* ensure we are returning * on upserts (#79) +- ensure we are returning \* on upserts (#79) -* handle new if types +- handle new if types -* copy query prefix to newly created query (#74) +- copy query prefix to newly created query (#74) ### Improvements: -* don't upsert defaults on conflict (#77) +- don't upsert defaults on conflict (#77) -* relax ash version requirement +- relax ash version requirement -* add custom migration types, and repo level override +- add custom migration types, and repo level override -* update to latest version of ash +- update to latest version of ash ## [v0.41.4](https://github.com/ash-project/ash_postgres/compare/v0.41.3...v0.41.4) (2021-11-25) - - - ### Bug Fixes: -* handle new if types +- handle new if types -* copy query prefix to newly created query (#74) +- copy query prefix to newly created query (#74) ### Improvements: -* don't upsert defaults on conflict (#77) +- don't upsert defaults on conflict (#77) -* relax ash version requirement +- relax ash version requirement -* add custom migration types, and repo level override +- add custom migration types, and repo level override -* update to latest version of ash +- update to latest version of ash ## [v0.41.3](https://github.com/ash-project/ash_postgres/compare/v0.41.2...v0.41.3) (2021-11-13) - - - ### Bug Fixes: -* handle new if types +- handle new if types -* copy query prefix to newly created query (#74) +- copy query prefix to newly created query (#74) ### Improvements: -* relax ash version requirement +- relax ash version requirement -* add custom migration types, and repo level override +- add custom migration types, and repo level override -* update to latest version of ash +- update to latest version of ash ## [v0.41.2](https://github.com/ash-project/ash_postgres/compare/v0.41.1...v0.41.2) (2021-11-10) - - - ### Bug Fixes: -* copy query prefix to newly created query (#74) +- copy query prefix to newly created query (#74) ### Improvements: -* add custom migration types, and repo level override +- add custom migration types, and repo level override -* update to latest version of ash +- update to latest version of ash ## [v0.41.1](https://github.com/ash-project/ash_postgres/compare/v0.41.0-rc.9...v0.41.1) (2021-11-03) - - - ### Bug Fixes: -* copy query prefix to newly created query (#74) +- copy query prefix to newly created query (#74) ### Improvements: -* update to latest version of ash +- update to latest version of ash ## [v0.41.0-rc.9](https://github.com/ash-project/ash_postgres/compare/v0.41.0-rc.8...v0.41.0-rc.9) (2021-11-01) - - - ### Bug Fixes: -* use proper ecto types everywhere +- use proper ecto types everywhere -* try to fix missing paren issue in array_agg +- try to fix missing paren issue in array_agg -* fix can? for :joins (#73) +- fix can? for :joins (#73) -* remove unused default value +- remove unused default value -* use proper identity names for polymorphic resources +- use proper identity names for polymorphic resources -* set identity names propertly for polymorphic resources +- set identity names propertly for polymorphic resources -* handle nil values in snapshots better +- handle nil values in snapshots better -* remove unused field from snapshot parsing +- remove unused field from snapshot parsing ### Improvements: -* support `default` on aggregates +- support `default` on aggregates -* support `custom_indexes` +- support `custom_indexes` ## [v0.41.0-rc.8](https://github.com/ash-project/ash_postgres/compare/v0.41.0-rc.7...v0.41.0-rc.8) (2021-10-25) - - - ### Bug Fixes: -* fix can? for :joins (#73) +- fix can? for :joins (#73) -* remove unused default value +- remove unused default value -* use proper identity names for polymorphic resources +- use proper identity names for polymorphic resources -* set identity names propertly for polymorphic resources +- set identity names propertly for polymorphic resources -* handle nil values in snapshots better +- handle nil values in snapshots better -* remove unused field from snapshot parsing +- remove unused field from snapshot parsing ### Improvements: -* support `default` on aggregates +- support `default` on aggregates -* support `custom_indexes` +- support `custom_indexes` ## [v0.41.0-rc.7](https://github.com/ash-project/ash_postgres/compare/v0.41.0-rc.6...v0.41.0-rc.7) (2021-10-24) - - - ### Bug Fixes: -* fix can? for :joins (#73) +- fix can? for :joins (#73) -* remove unused default value +- remove unused default value -* use proper identity names for polymorphic resources +- use proper identity names for polymorphic resources -* set identity names propertly for polymorphic resources +- set identity names propertly for polymorphic resources -* handle nil values in snapshots better +- handle nil values in snapshots better -* remove unused field from snapshot parsing +- remove unused field from snapshot parsing ### Improvements: -* support `custom_indexes` +- support `custom_indexes` ## [v0.41.0-rc.6](https://github.com/ash-project/ash_postgres/compare/v0.41.0-rc.5...v0.41.0-rc.6) (2021-09-26) - - - ### Bug Fixes: -* remove unused default value +- remove unused default value -* use proper identity names for polymorphic resources +- use proper identity names for polymorphic resources -* set identity names propertly for polymorphic resources +- set identity names propertly for polymorphic resources -* handle nil values in snapshots better +- handle nil values in snapshots better -* remove unused field from snapshot parsing +- remove unused field from snapshot parsing ### Improvements: -* support `custom_indexes` +- support `custom_indexes` ## [v0.41.0-rc.5](https://github.com/ash-project/ash_postgres/compare/v0.41.0-rc.4...v0.41.0-rc.5) (2021-09-21) - - - ### Bug Fixes: -* use proper identity names for polymorphic resources +- use proper identity names for polymorphic resources -* set identity names propertly for polymorphic resources +- set identity names propertly for polymorphic resources -* handle nil values in snapshots better +- handle nil values in snapshots better -* remove unused field from snapshot parsing +- remove unused field from snapshot parsing ### Improvements: -* support `custom_indexes` +- support `custom_indexes` ## [v0.41.0-rc.4](https://github.com/ash-project/ash_postgres/compare/v0.41.0-rc.3...v0.41.0-rc.4) (2021-09-21) - - - ### Bug Fixes: -* set identity names propertly for polymorphic resources +- set identity names propertly for polymorphic resources -* handle nil values in snapshots better +- handle nil values in snapshots better -* remove unused field from snapshot parsing +- remove unused field from snapshot parsing ### Improvements: -* support `custom_indexes` +- support `custom_indexes` ## [v0.41.0-rc.3](https://github.com/ash-project/ash_postgres/compare/v0.41.0-rc.2...v0.41.0-rc.3) (2021-09-21) - - - ### Bug Fixes: -* handle nil values in snapshots better +- handle nil values in snapshots better -* remove unused field from snapshot parsing +- remove unused field from snapshot parsing ### Improvements: -* support `custom_indexes` +- support `custom_indexes` ## [v0.41.0-rc.2](https://github.com/ash-project/ash_postgres/compare/v0.41.0-rc.1...v0.41.0-rc.2) (2021-09-21) - - - ### Bug Fixes: -* remove unused field from snapshot parsing +- remove unused field from snapshot parsing ### Improvements: -* support `custom_indexes` +- support `custom_indexes` ## [v0.41.0-rc.1](https://github.com/ash-project/ash_postgres/compare/v0.41.0-rc.0...v0.41.0-rc.1) (2021-09-20) - - - ### Improvements: -* support `custom_indexes` +- support `custom_indexes` ## [v0.41.0-rc.0](https://github.com/ash-project/ash_postgres/compare/v0.40.11...v0.41.0-rc.0) (2021-09-13) + ### Breaking Changes: -* update to latest ash/ecto versions w/ parameterized types - - +- update to latest ash/ecto versions w/ parameterized types ### Improvements: -* Support default tenant migration path in releases (#69) +- Support default tenant migration path in releases (#69) ## [v0.40.11](https://github.com/ash-project/ash_postgres/compare/v0.40.10...v0.40.11) (2021-07-28) - - - ### Bug Fixes: -* set subquery prefix properly +- set subquery prefix properly ## [v0.40.10](https://github.com/ash-project/ash_postgres/compare/v0.40.9...v0.40.10) (2021-07-27) - - - ### Bug Fixes: -* set subquery source correctly +- set subquery source correctly -* create parameter for ci strings +- create parameter for ci strings -* explicitly set prefix at each level +- explicitly set prefix at each level -* interaction w/ attribute and context tenancy +- interaction w/ attribute and context tenancy ### Improvements: -* info on migration generator output +- info on migration generator output -* use match: :full on attr multitenancy +- use match: :full on attr multitenancy -* update to latest ash +- update to latest ash -* update to latest ash +- update to latest ash -* upgrade ash dep +- upgrade ash dep ## [v0.40.9](https://github.com/ash-project/ash_postgres/compare/v0.40.8...v0.40.9) (2021-07-22) - - - ### Bug Fixes: -* don't add a non-list to a list +- don't add a non-list to a list ### Improvements: -* add sort + select test +- add sort + select test ## [v0.40.8](https://github.com/ash-project/ash_postgres/compare/v0.40.7...v0.40.8) (2021-07-19) - - - ### Bug Fixes: -* ensure source table is sorted in lateral join +- ensure source table is sorted in lateral join ### Improvements: -* fix significant performance issue in lateral joins +- fix significant performance issue in lateral joins ## [v0.40.7](https://github.com/ash-project/ash_postgres/compare/v0.40.6...v0.40.7) (2021-07-12) - - - ### Improvements: -* support default_prefix configuration +- support default_prefix configuration ## [v0.40.6](https://github.com/ash-project/ash_postgres/compare/v0.40.5...v0.40.6) (2021-07-08) - - - ### Bug Fixes: -* fix migrator mix tasks w/ only/except tenants +- fix migrator mix tasks w/ only/except tenants -* drop foreign keys after table create properly +- drop foreign keys after table create properly -* drop foreign keys before dropping table +- drop foreign keys before dropping table -* left_lateral_join for many_to_many aggregates +- left_lateral_join for many_to_many aggregates -* properly reference nested aggregate fields for join +- properly reference nested aggregate fields for join -* properly determine fallback table for polymorphic resources +- properly determine fallback table for polymorphic resources -* ensure non-tenant resources can be aggregates +- ensure non-tenant resources can be aggregates -* properly set aggregate query sources +- properly set aggregate query sources -* retain parent as bindings +- retain parent as bindings -* don't add `rel_source` at all +- don't add `rel_source` at all -* properly build atoms list +- properly build atoms list -* horribly hack ecto for dynamic bindings +- horribly hack ecto for dynamic bindings -* properly coalesce aggregate values +- properly coalesce aggregate values -* always add nullability flag +- always add nullability flag -* sort references only after other same-table ops +- sort references only after other same-table ops -* generate multitenant foreign keys properly +- generate multitenant foreign keys properly ### Improvements: -* `--name` when generating migrations +- `--name` when generating migrations -* add `mix ash_postgres.rollback` +- add `mix ash_postgres.rollback` -* update to latest ash +- update to latest ash -* update to latest ash +- update to latest ash -* leverage new `private_vars` for errs +- leverage new `private_vars` for errs ## [v0.40.5](https://github.com/ash-project/ash_postgres/compare/v0.40.4...v0.40.5) (2021-07-08) - - - ### Bug Fixes: -* fix migrator mix tasks w/ only/except tenants +- fix migrator mix tasks w/ only/except tenants -* drop foreign keys after table create properly +- drop foreign keys after table create properly -* drop foreign keys before dropping table +- drop foreign keys before dropping table -* left_lateral_join for many_to_many aggregates +- left_lateral_join for many_to_many aggregates -* properly reference nested aggregate fields for join +- properly reference nested aggregate fields for join -* properly determine fallback table for polymorphic resources +- properly determine fallback table for polymorphic resources -* ensure non-tenant resources can be aggregates +- ensure non-tenant resources can be aggregates -* properly set aggregate query sources +- properly set aggregate query sources -* retain parent as bindings +- retain parent as bindings -* don't add `rel_source` at all +- don't add `rel_source` at all -* properly build atoms list +- properly build atoms list -* horribly hack ecto for dynamic bindings +- horribly hack ecto for dynamic bindings -* properly coalesce aggregate values +- properly coalesce aggregate values -* always add nullability flag +- always add nullability flag -* sort references only after other same-table ops +- sort references only after other same-table ops -* generate multitenant foreign keys properly +- generate multitenant foreign keys properly ### Improvements: -* add `mix ash_postgres.rollback` +- add `mix ash_postgres.rollback` -* update to latest ash +- update to latest ash -* update to latest ash +- update to latest ash -* leverage new `private_vars` for errs +- leverage new `private_vars` for errs ## [v0.40.4](https://github.com/ash-project/ash_postgres/compare/v0.40.3...v0.40.4) (2021-07-05) - - - ### Bug Fixes: -* left_lateral_join for many_to_many aggregates +- left_lateral_join for many_to_many aggregates -* properly reference nested aggregate fields for join +- properly reference nested aggregate fields for join -* properly determine fallback table for polymorphic resources +- properly determine fallback table for polymorphic resources -* ensure non-tenant resources can be aggregates +- ensure non-tenant resources can be aggregates -* properly set aggregate query sources +- properly set aggregate query sources -* retain parent as bindings +- retain parent as bindings -* don't add `rel_source` at all +- don't add `rel_source` at all -* properly build atoms list +- properly build atoms list -* horribly hack ecto for dynamic bindings +- horribly hack ecto for dynamic bindings -* properly coalesce aggregate values +- properly coalesce aggregate values -* always add nullability flag +- always add nullability flag -* sort references only after other same-table ops +- sort references only after other same-table ops -* generate multitenant foreign keys properly +- generate multitenant foreign keys properly ### Improvements: -* update to latest ash +- update to latest ash -* update to latest ash +- update to latest ash -* leverage new `private_vars` for errs +- leverage new `private_vars` for errs ## [v0.40.3](https://github.com/ash-project/ash_postgres/compare/v0.40.2...v0.40.3) (2021-07-03) - - - ### Bug Fixes: -* ensure non-tenant resources can be aggregates +- ensure non-tenant resources can be aggregates -* properly set aggregate query sources +- properly set aggregate query sources -* retain parent as bindings +- retain parent as bindings -* don't add `rel_source` at all +- don't add `rel_source` at all -* properly build atoms list +- properly build atoms list -* horribly hack ecto for dynamic bindings +- horribly hack ecto for dynamic bindings -* properly coalesce aggregate values +- properly coalesce aggregate values -* always add nullability flag +- always add nullability flag -* sort references only after other same-table ops +- sort references only after other same-table ops -* generate multitenant foreign keys properly +- generate multitenant foreign keys properly ### Improvements: -* update to latest ash +- update to latest ash -* leverage new `private_vars` for errs +- leverage new `private_vars` for errs ## [v0.40.2](https://github.com/ash-project/ash_postgres/compare/v0.40.1...v0.40.2) (2021-07-02) - - - ### Bug Fixes: -* properly set aggregate query sources +- properly set aggregate query sources -* retain parent as bindings +- retain parent as bindings -* don't add `rel_source` at all +- don't add `rel_source` at all -* properly build atoms list +- properly build atoms list -* horribly hack ecto for dynamic bindings +- horribly hack ecto for dynamic bindings -* properly coalesce aggregate values +- properly coalesce aggregate values -* always add nullability flag +- always add nullability flag -* sort references only after other same-table ops +- sort references only after other same-table ops -* generate multitenant foreign keys properly +- generate multitenant foreign keys properly ### Improvements: -* update to latest ash +- update to latest ash -* leverage new `private_vars` for errs +- leverage new `private_vars` for errs ## [v0.40.1](https://github.com/ash-project/ash_postgres/compare/v0.40.0-rc5...v0.40.1) (2021-07-02) - - - ### Bug Fixes: -* properly coalesce aggregate values +- properly coalesce aggregate values -* always add nullability flag +- always add nullability flag -* sort references only after other same-table ops +- sort references only after other same-table ops -* generate multitenant foreign keys properly +- generate multitenant foreign keys properly ### Improvements: -* update to latest ash +- update to latest ash -* leverage new `private_vars` for errs +- leverage new `private_vars` for errs ## [v0.40.0-rc5](https://github.com/ash-project/ash_postgres/compare/v0.40.0-rc4...v0.40.0-rc5) (2021-07-01) - - - ### Bug Fixes: -* properly coalesce aggregate values +- properly coalesce aggregate values -* always add nullability flag +- always add nullability flag -* sort references only after other same-table ops +- sort references only after other same-table ops -* generate multitenant foreign keys properly +- generate multitenant foreign keys properly ### Improvements: -* leverage new `private_vars` for errs +- leverage new `private_vars` for errs ## [v0.40.0-rc4](https://github.com/ash-project/ash_postgres/compare/v0.40.0-rc3...v0.40.0-rc4) (2021-06-23) - - - ### Bug Fixes: -* always add nullability flag +- always add nullability flag -* sort references only after other same-table ops +- sort references only after other same-table ops -* generate multitenant foreign keys properly +- generate multitenant foreign keys properly ### Improvements: -* leverage new `private_vars` for errs +- leverage new `private_vars` for errs ## [v0.40.0-rc3](https://github.com/ash-project/ash_postgres/compare/v0.40.0-rc2...v0.40.0-rc3) (2021-06-15) - - - ### Bug Fixes: -* always add nullability flag +- always add nullability flag -* sort references only after other same-table ops +- sort references only after other same-table ops -* generate multitenant foreign keys properly +- generate multitenant foreign keys properly ## [v0.40.0-rc2](https://github.com/ash-project/ash_postgres/compare/v0.40.0-rc1...v0.40.0-rc2) (2021-06-08) - - - ### Bug Fixes: -* sort references only after other same-table ops +- sort references only after other same-table ops -* generate multitenant foreign keys properly +- generate multitenant foreign keys properly ## [v0.40.0-rc1](https://github.com/ash-project/ash_postgres/compare/v0.40.0-rc.0...v0.40.0-rc1) (2021-06-05) - - - ## [v0.39.0-rc.0](https://github.com/ash-project/ash_postgres/compare/v0.38.11...v0.39.0-rc.0) (2021-06-04) - - - ### Features: -* support expression based calculations +- support expression based calculations -* support concat + if expressions +- support concat + if expressions ### Improvements: -* various other improvements +- various other improvements ## [v0.38.11](https://github.com/ash-project/ash_postgres/compare/v0.38.10...v0.38.11) (2021-05-23) - - - ### Bug Fixes: -* set prefix to "public" for fkeys to public schema +- set prefix to "public" for fkeys to public schema ### Improvements: -* set explicit prefix on join filters +- set explicit prefix on join filters ## [v0.38.10](https://github.com/ash-project/ash_postgres/compare/v0.38.9...v0.38.10) (2021-05-19) - - - ### Improvements: -* support new ash upsert specifying targets +- support new ash upsert specifying targets -* update to latest ash +- update to latest ash ## [v0.38.9](https://github.com/ash-project/ash_postgres/compare/v0.38.8...v0.38.9) (2021-05-12) - - - ### Bug Fixes: -* properly group many_to_many aggregates +- properly group many_to_many aggregates ## [v0.38.8](https://github.com/ash-project/ash_postgres/compare/v0.38.7...v0.38.8) (2021-05-09) - - - ### Improvements: -* update to the latest ash version +- update to the latest ash version ## [v0.38.7](https://github.com/ash-project/ash_postgres/compare/v0.38.6...v0.38.7) (2021-05-09) - - - ### Improvements: -* support latest ash/filtering on related aggregates +- support latest ash/filtering on related aggregates ## [v0.38.6](https://github.com/ash-project/ash_postgres/compare/v0.38.5...v0.38.6) (2021-05-07) - - - ### Bug Fixes: -* properly construct sources for lateral joins +- properly construct sources for lateral joins -* copy the correct data for lateral join queries +- copy the correct data for lateral join queries -* better errors in error cases +- better errors in error cases ### Improvements: -* update to latest ash +- update to latest ash ## [v0.38.5](https://github.com/ash-project/ash_postgres/compare/v0.38.4...v0.38.5) (2021-05-07) - - - ### Bug Fixes: -* don't cast booleans to string in last_ditch_cast +- don't cast booleans to string in last_ditch_cast ## [v0.38.4](https://github.com/ash-project/ash_postgres/compare/v0.38.3...v0.38.4) (2021-05-07) - - - ### Improvements: -* support latest ash version resource sorts +- support latest ash version resource sorts ## [v0.38.3](https://github.com/ash-project/ash_postgres/compare/v0.38.2...v0.38.3) (2021-05-06) - - - ### Improvements: -* update to latest ash +- update to latest ash -* document script to iterate migrations (#65) +- document script to iterate migrations (#65) ## [v0.38.2](https://github.com/ash-project/ash_postgres/compare/v0.38.1...v0.38.2) (2021-05-04) - - - ### Bug Fixes: -* join to join table in lateral join query +- join to join table in lateral join query -* multitenancy + lateral join sources +- multitenancy + lateral join sources -* don't distinct in lateral joins +- don't distinct in lateral joins ## [v0.38.1](https://github.com/ash-project/ash_postgres/compare/v0.38.0...v0.38.1) (2021-05-04) - - - ### Bug Fixes: -* fix fragment processing broken (#64) +- fix fragment processing broken (#64) ## [v0.38.0](https://github.com/ash-project/ash_postgres/compare/v0.37.8...v0.38.0) (2021-04-29) - - - ### Features: -* support new side load improvements +- support new side load improvements ### Improvements: -* Preserve attribute order (#63) +- Preserve attribute order (#63) ## [v0.37.8](https://github.com/ash-project/ash_postgres/compare/v0.37.7...v0.37.8) (2021-04-27) - - - ### Bug Fixes: -* simpler index names +- simpler index names -* don't prefix unique indices with prefix() +- don't prefix unique indices with prefix() -* sort index operations last +- sort index operations last ### Improvements: -* custom index names +- custom index names ## [v0.37.7](https://github.com/ash-project/ash_postgres/compare/v0.37.6...v0.37.7) (2021-04-27) - - - ### Bug Fixes: -* remove inspects that were left in by accident +- remove inspects that were left in by accident ## [v0.37.6](https://github.com/ash-project/ash_postgres/compare/v0.37.5...v0.37.6) (2021-04-27) - - - ### Bug Fixes: -* type cast atoms to strings in last ditch cast +- type cast atoms to strings in last ditch cast -* properly type cast +- properly type cast -* Remove duplicate file extension (#60) +- Remove duplicate file extension (#60) ## [v0.37.5](https://github.com/ash-project/ash_postgres/compare/v0.37.4...v0.37.5) (2021-04-27) - - - ### Bug Fixes: -* properly type cast +- properly type cast ## [v0.37.4](https://github.com/ash-project/ash_postgres/compare/v0.37.3...v0.37.4) (2021-04-26) - - - ### Improvements: -* support `list` aggregate +- support `list` aggregate ## [v0.37.3](https://github.com/ash-project/ash_postgres/compare/v0.37.2...v0.37.3) (2021-04-26) - - - ### Bug Fixes: -* stringify struct defaults in migration generator +- stringify struct defaults in migration generator -* properly comment out extension uninstallation code +- properly comment out extension uninstallation code ## [v0.37.2](https://github.com/ash-project/ash_postgres/compare/v0.37.1...v0.37.2) (2021-04-21) - - - ### Improvements: -* support ash enums +- support ash enums ## [v0.37.1](https://github.com/ash-project/ash_postgres/compare/v0.37.0...v0.37.1) (2021-04-19) - - - ### Bug Fixes: -* include type in references (because it is *not* automatic) +- include type in references (because it is _not_ automatic) ## [v0.37.0](https://github.com/ash-project/ash_postgres/compare/v0.36.5...v0.37.0) (2021-04-19) - - - ### Features: -* add check_constraints, both for validation and migrations +- add check_constraints, both for validation and migrations ## [v0.36.5](https://github.com/ash-project/ash_postgres/compare/v0.36.4...v0.36.5) (2021-04-13) - - - ### Bug Fixes: -* always drop constraints before modifying +- always drop constraints before modifying -* properly compare old references and new references +- properly compare old references and new references ## [v0.36.4](https://github.com/ash-project/ash_postgres/compare/v0.36.3...v0.36.4) (2021-04-12) - - - ### Bug Fixes: -* don't explicitly set type in `references` +- don't explicitly set type in `references` ### Improvements: -* default integers to `:bigint` +- default integers to `:bigint` ## [v0.36.3](https://github.com/ash-project/ash_postgres/compare/v0.36.2...v0.36.3) (2021-04-12) - - - ### Improvements: -* primary autoincrement key as bigserial (#54) +- primary autoincrement key as bigserial (#54) ## [v0.36.2](https://github.com/ash-project/ash_postgres/compare/v0.36.1...v0.36.2) (2021-04-09) - - - ### Improvements: -* support new ash select feature +- support new ash select feature ## [v0.36.1](https://github.com/ash-project/ash_postgres/compare/v0.36.0...v0.36.1) (2021-04-04) - - - ### Bug Fixes: -* raise when `all_tenants/0` default impl is called +- raise when `all_tenants/0` default impl is called ### Improvements: -* add sum aggregate (#53) +- add sum aggregate (#53) ## [v0.36.0](https://github.com/ash-project/ash_postgres/compare/v0.35.5...v0.36.0) (2021-04-01) - - - ### Features: -* support configuring references +- support configuring references -* support configuring polymorphic references +- support configuring polymorphic references -* support `distinct` Ash queries +- support `distinct` Ash queries ## [v0.35.5](https://github.com/ash-project/ash_postgres/compare/v0.35.4...v0.35.5) (2021-03-29) - - - ### Bug Fixes: -* Made AshPostgres.Repo.init/2 overridable (#51) +- Made AshPostgres.Repo.init/2 overridable (#51) ### Improvements: -* only count resources w/ create action for nullability +- only count resources w/ create action for nullability -* better error message on missing table +- better error message on missing table ## [v0.35.4](https://github.com/ash-project/ash_postgres/compare/v0.35.3...v0.35.4) (2021-03-21) - - - ### Bug Fixes: -* reroute `Ash.Type.UUID` to `:uuid` in migrations +- reroute `Ash.Type.UUID` to `:uuid` in migrations -* force create extensions snapshot +- force create extensions snapshot ### Improvements: -* consistent foreign key names +- consistent foreign key names -* support custom foreign key error messages +- support custom foreign key error messages ## [v0.35.3](https://github.com/ash-project/ash_postgres/compare/v0.35.2...v0.35.3) (2021-03-19) - - - ### Bug Fixes: -* force create extensions snapshot +- force create extensions snapshot -* more conservative inner join checks +- more conservative inner join checks -* add back in inner join detection logic +- add back in inner join detection logic ### Improvements: -* consistent foreign key names +- consistent foreign key names -* support custom foreign key error messages +- support custom foreign key error messages ## [v0.35.2](https://github.com/ash-project/ash_postgres/compare/v0.35.1...v0.35.2) (2021-03-05) - - - ### Bug Fixes: -* more conservative inner join checks +- more conservative inner join checks -* add back in inner join detection logic +- add back in inner join detection logic ## [v0.35.1](https://github.com/ash-project/ash_postgres/compare/v0.35.0...v0.35.1) (2021-03-02) - - - ### Bug Fixes: -* don't start the whole app in migrate +- don't start the whole app in migrate ## [v0.35.0](https://github.com/ash-project/ash_postgres/compare/v0.34.7...v0.35.0) (2021-03-02) - - - ### Features: -* automatically install extensions from repo +- automatically install extensions from repo ## [v0.34.7](https://github.com/ash-project/ash_postgres/compare/v0.34.6...v0.34.7) (2021-03-02) - - - ### Bug Fixes: -* typo in references for multitenancy +- typo in references for multitenancy -* `null: true` when attr isn't on all resources for a table +- `null: true` when attr isn't on all resources for a table ## [v0.34.6](https://github.com/ash-project/ash_postgres/compare/v0.34.5...v0.34.6) (2021-02-24) - - - ### Bug Fixes: -* better embedded filters, switch to latest ash +- better embedded filters, switch to latest ash ## [v0.34.5](https://github.com/ash-project/ash_postgres/compare/v0.34.4...v0.34.5) (2021-02-23) - - - ### Improvements: -* support latest ash +- support latest ash ## [v0.34.4](https://github.com/ash-project/ash_postgres/compare/v0.34.3...v0.34.4) (2021-02-08) - - - ### Bug Fixes: -* trim when choosing new attribute name +- trim when choosing new attribute name ## [v0.34.3](https://github.com/ash-project/ash_postgres/compare/v0.34.2...v0.34.3) (2021-02-06) - - - ### Bug Fixes: -* don't reference polymorphic tables to belongs_to relationships +- don't reference polymorphic tables to belongs_to relationships ## [v0.34.2](https://github.com/ash-project/ash_postgres/compare/v0.34.1...v0.34.2) (2021-02-06) - - - ### Bug Fixes: -* set up references properly +- set up references properly ## [v0.34.1](https://github.com/ash-project/ash_postgres/compare/v0.34.0...v0.34.1) (2021-02-06) - - - ### Bug Fixes: -* reference the configured table if set +- reference the configured table if set ## [v0.34.0](https://github.com/ash-project/ash_postgres/compare/v0.33.1...v0.34.0) (2021-02-06) - - - ### Features: -* support polymorphic relationships +- support polymorphic relationships ## [v0.33.1](https://github.com/ash-project/ash_postgres/compare/v0.33.0...v0.33.1) (2021-01-27) - - - ### Bug Fixes: -* actually insert the tracking row +- actually insert the tracking row ## [v0.33.0](https://github.com/ash-project/ash_postgres/compare/v0.32.2...v0.33.0) (2021-01-27) - - - ### Features: -* add `mix ash_postgres.create` +- add `mix ash_postgres.create` -* add `mix ash_postgres.migrate` +- add `mix ash_postgres.migrate` -* add `mix ash_postgres.migrate --tenants` +- add `mix ash_postgres.migrate --tenants` -* add `mix ash_postgres.drop` +- add `mix ash_postgres.drop` ### Bug Fixes: -* rework the way multitenant migrations work +- rework the way multitenant migrations work ## [v0.32.2](https://github.com/ash-project/ash_postgres/compare/v0.32.1...v0.32.2) (2021-01-26) - - - ### Bug Fixes: -* un-break the `in` filter type casting code +- un-break the `in` filter type casting code ### Improvements: -* better errors for multitenant unique constraints +- better errors for multitenant unique constraints ## [v0.32.1](https://github.com/ash-project/ash_postgres/compare/v0.32.0...v0.32.1) (2021-01-24) - - - ### Bug Fixes: -* `ago` was adding, not subtracting +- `ago` was adding, not subtracting ## [v0.32.0](https://github.com/ash-project/ash_postgres/compare/v0.31.1...v0.32.0) (2021-01-24) - - - ### Features: -* support latest ash + contains +- support latest ash + contains ## [v0.31.1](https://github.com/ash-project/ash_postgres/compare/v0.31.0...v0.31.1) (2021-01-22) - - - ### Improvements: -* update to latest ash +- update to latest ash ## [v0.31.0](https://github.com/ash-project/ash_postgres/compare/v0.30.1...v0.31.0) (2021-01-22) - - - ### Features: -* support fragments +- support fragments -* support type casting +- support type casting -* update to latest ash to support expressions +- update to latest ash to support expressions ### Bug Fixes: -* update CI versions +- update CI versions ## [v0.30.1](https://github.com/ash-project/ash_postgres/compare/v0.30.0...v0.30.1) (2021-01-13) - - - ## [v0.30.0](https://github.com/ash-project/ash_postgres/compare/v0.29.6...v0.30.0) (2021-01-13) - - - ### Features: -* Add check_migrated option to migration generator (#40) (#43) +- Add check_migrated option to migration generator (#40) (#43) ## [v0.29.6](https://github.com/ash-project/ash_postgres/compare/v0.29.5...v0.29.6) (2021-01-12) - - - ### Bug Fixes: -* rename out of phase, small migration fix +- rename out of phase, small migration fix ## [v0.29.5](https://github.com/ash-project/ash_postgres/compare/v0.29.4...v0.29.5) (2021-01-10) - - - ### Improvements: -* Use ecto_sql formatter settings (#38) +- Use ecto_sql formatter settings (#38) ## [v0.29.4](https://github.com/ash-project/ash_postgres/compare/v0.29.3...v0.29.4) (2021-01-10) - - - ### Improvements: -* Omit field opts if they are default values (#37) +- Omit field opts if they are default values (#37) ## [v0.29.3](https://github.com/ash-project/ash_postgres/compare/v0.29.2...v0.29.3) (2021-01-08) - - - ### Improvements: -* support latest ash +- support latest ash ## [v0.29.2](https://github.com/ash-project/ash_postgres/compare/v0.29.1...v0.29.2) (2021-01-08) - - - ### Improvements: -* Make integer serial if generated +- Make integer serial if generated ## [v0.29.1](https://github.com/ash-project/ash_postgres/compare/v0.29.0...v0.29.1) (2021-01-08) - - - ### Improvements: -* support latest ash version +- support latest ash version ## [v0.29.0](https://github.com/ash-project/ash_postgres/compare/v0.28.1...v0.29.0) (2021-01-08) - - - ### Features: -* retain snapshot history +- retain snapshot history ### Improvements: -* support latest ash version +- support latest ash version ## [v0.28.1](https://github.com/ash-project/ash_postgres/compare/v0.28.0...v0.28.1) (2021-01-07) - - - ### Improvements: -* Add :binary migration type (#33) +- Add :binary migration type (#33) ## [v0.28.0](https://github.com/ash-project/ash_postgres/compare/v0.27.0...v0.28.0) (2020-12-29) - - - ### Features: -* support latest Ash version +- support latest Ash version ## [v0.27.0](https://github.com/ash-project/ash_postgres/compare/v0.26.2...v0.27.0) (2020-12-23) - - - ### Features: -* support refs on both sides of operators +- support refs on both sides of operators ### Bug Fixes: -* bump ash version +- bump ash version ## [v0.26.2](https://github.com/ash-project/ash_postgres/compare/v0.26.1...v0.26.2) (2020-12-06) - - - ### Bug Fixes: -* properly accept the `tenant_migration_path` +- properly accept the `tenant_migration_path` ## [v0.26.1](https://github.com/ash-project/ash_postgres/compare/v0.26.0...v0.26.1) (2020-12-01) - - - ### Bug Fixes: -* set default properly when modifying +- set default properly when modifying ## [v0.26.0](https://github.com/ash-project/ash_postgres/compare/v0.25.5...v0.26.0) (2020-11-25) - - - ### Features: -* don't drop columns unless explicitly told to +- don't drop columns unless explicitly told to ### Bug Fixes: -* various migration generator bug fixes +- various migration generator bug fixes ## [v0.25.5](https://github.com/ash-project/ash_postgres/compare/v0.25.4...v0.25.5) (2020-11-17) - - - ### Bug Fixes: -* drop constraints outside of phases (#29) +- drop constraints outside of phases (#29) ## [v0.25.4](https://github.com/ash-project/ash_postgres/compare/v0.25.3...v0.25.4) (2020-11-07) - - - ### Bug Fixes: -* only alter the things that have changed +- only alter the things that have changed ## [v0.25.3](https://github.com/ash-project/ash_postgres/compare/v0.25.2...v0.25.3) (2020-11-06) - - - ### Improvements: -* add utc_datetime migration type +- add utc_datetime migration type ## [v0.25.2](https://github.com/ash-project/ash_postgres/compare/v0.25.1...v0.25.2) (2020-11-03) - - - ### Bug Fixes: -* access data_layer_query with function +- access data_layer_query with function ## [v0.25.1](https://github.com/ash-project/ash_postgres/compare/v0.25.0...v0.25.1) (2020-10-29) - - - ### Improvements: -* mark repo as not requiring compile-time dep +- mark repo as not requiring compile-time dep ## [v0.25.0](https://github.com/ash-project/ash_postgres/compare/v0.24.0...v0.25.0) (2020-10-29) - - - ### Features: -* multitenancy (#25) +- multitenancy (#25) ### Bug Fixes: -* verify repo using ensure_compiled +- verify repo using ensure_compiled ## [v0.24.0](https://github.com/ash-project/ash_postgres/compare/v0.23.2...v0.24.0) (2020-10-17) - - - ### Features: -* support latest ash +- support latest ash ## [v0.23.2](https://github.com/ash-project/ash_postgres/compare/v0.23.1...v0.23.2) (2020-10-07) - - - ## [v0.23.1](https://github.com/ash-project/ash_postgres/compare/v0.23.0...v0.23.1) (2020-10-06) - - - ## [v0.23.0](https://github.com/ash-project/ash_postgres/compare/v0.22.1...v0.23.0) (2020-10-06) - - - ### Features: -* update to latest ash, trigram filter +- update to latest ash, trigram filter ## [v0.22.1](https://github.com/ash-project/ash_postgres/compare/v0.22.0...v0.22.1) (2020-10-01) - - - ### Bug Fixes: -* don't group alters with creates (#22) +- don't group alters with creates (#22) -* add jason dependency, clean lockfile (#21) +- add jason dependency, clean lockfile (#21) ## [v0.22.0](https://github.com/ash-project/ash_postgres/compare/v0.21.0...v0.22.0) (2020-09-24) - - - ### Features: -* fix error when filtering with `true` +- fix error when filtering with `true` ### Bug Fixes: -* broken types for `in` operator +- broken types for `in` operator ## [v0.21.0](https://github.com/ash-project/ash_postgres/compare/v0.20.1...v0.21.0) (2020-09-19) - - - ### Features: -* support base_filter (#18) +- support base_filter (#18) ## [v0.20.1](https://github.com/ash-project/ash_postgres/compare/v0.20.0...v0.20.1) (2020-09-11) - - - ### Bug Fixes: -* document/update migration path logic +- document/update migration path logic ## [v0.20.0](https://github.com/ash-project/ash_postgres/compare/v0.19.0...v0.20.0) (2020-09-11) - - - ### Features: -* snapshot-based migration generator +- snapshot-based migration generator ## [v0.19.0](https://github.com/ash-project/ash_postgres/compare/v0.18.0...v0.19.0) (2020-09-02) diff --git a/README.md b/README.md index 61ae04f..3999424 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ Then, configure each of your `Ash.Resource` resources by adding `use Ash.Resourc ```elixir defmodule MyApp.SomeResource do - use Ash.Resource, data_layer: AshPostgres.DataLayer + use Ash.Resource, domain: MyDomain, data_layer: AshPostgres.DataLayer postgres do repo MyApp.Repo diff --git a/benchmarks/bulk_create.exs b/benchmarks/bulk_create.exs index e8f2029..5d9ee39 100644 --- a/benchmarks/bulk_create.exs +++ b/benchmarks/bulk_create.exs @@ -1,4 +1,4 @@ -alias AshPostgres.Test.{Api, Post} +alias AshPostgres.Test.{Domain, Post} ten_rows = 1..10 @@ -25,7 +25,7 @@ hundred_thousand_rows = end) # do them both once to warm things up -Api.bulk_create(ten_rows, Post, :create, +Ash.bulk_create(ten_rows, Post, :create, batch_size: 10, max_concurrency: 2 ) @@ -39,13 +39,13 @@ batch_size = 200 Benchee.run( %{ "ash sync": fn input -> - %{error_count: 0} = Api.bulk_create(input, Post, :create, + %{error_count: 0} = Ash.bulk_create(input, Post, :create, batch_size: batch_size, transaction: false ) end, "ash sync assuming casted": fn input -> - %{error_count: 0} = Api.bulk_create(input, Post, :create, + %{error_count: 0} = Ash.bulk_create(input, Post, :create, batch_size: batch_size, transaction: false, assume_casted?: true @@ -62,7 +62,7 @@ Benchee.run( input |> Stream.chunk_every(batch_size) |> Task.async_stream(fn batch -> - %{error_count: 0} = Api.bulk_create(batch, Post, :create, + %{error_count: 0} = Ash.bulk_create(batch, Post, :create, transaction: false ) end, max_concurrency: max_concurrency, timeout: :infinity) @@ -72,7 +72,7 @@ Benchee.run( input |> Stream.chunk_every(batch_size) |> Task.async_stream(fn batch -> - %{error_count: 0} = Api.bulk_create(batch, Post, :create, + %{error_count: 0} = Ash.bulk_create(batch, Post, :create, transaction: false, assume_casted?: true ) @@ -80,14 +80,14 @@ Benchee.run( |> Stream.run() end, "ash using own async option": fn input -> - %{error_count: 0} = Api.bulk_create(input, Post, :create, + %{error_count: 0} = Ash.bulk_create(input, Post, :create, transaction: false, max_concurrency: max_concurrency, batch_size: batch_size ) end, "ash using own async option assuming casted": fn input -> - %{error_count: 0} = Api.bulk_create(input, Post, :create, + %{error_count: 0} = Ash.bulk_create(input, Post, :create, transaction: false, assume_casted?: true, max_concurrency: max_concurrency, diff --git a/config/config.exs b/config/config.exs index 0b18acf..f3c392c 100644 --- a/config/config.exs +++ b/config/config.exs @@ -15,8 +15,8 @@ if Mix.env() == :dev do end if Mix.env() == :test do - config :ash, :validate_api_resource_inclusion?, false - config :ash, :validate_api_config_inclusion?, false + config :ash, :validate_domain_resource_inclusion?, false + config :ash, :validate_domain_config_inclusion?, false config :ash_postgres, AshPostgres.TestRepo, username: "postgres", @@ -42,10 +42,10 @@ if Mix.env() == :test do config :ash_postgres, ecto_repos: [AshPostgres.TestRepo, AshPostgres.TestNoSandboxRepo], - ash_apis: [ - AshPostgres.Test.Api, - AshPostgres.MultitenancyTest.Api, - AshPostgres.Test.ComplexCalculations.Api + ash_domains: [ + AshPostgres.Test.Domain, + AshPostgres.MultitenancyTest.Domain, + AshPostgres.Test.ComplexCalculations.Domain ] config :logger, level: :warning diff --git a/documentation/how_to/join-manual-relationships.md b/documentation/how_to/join-manual-relationships.md index f53fa0e..76b577d 100644 --- a/documentation/how_to/join-manual-relationships.md +++ b/documentation/how_to/join-manual-relationships.md @@ -38,7 +38,7 @@ defmodule Helpdesk.Support.Ticket.Relationships.TicketsAboveThreshold do |> Enum.group_by(& &1.representative_id)} end - # query is the "source" query that is being built. + # query is the "source" query that is being built. # _opts are options provided to the manual relationship, i.e `{Manual, opt: :val}` diff --git a/documentation/topics/migrations_and_tasks.md b/documentation/topics/migrations_and_tasks.md index 6afdace..694a2dd 100644 --- a/documentation/topics/migrations_and_tasks.md +++ b/documentation/topics/migrations_and_tasks.md @@ -25,7 +25,7 @@ AshPostgres is built on top of ecto, so much of its behavior is pass-through/orc For more information on generating migrations, see the module documentation here: `Mix.Tasks.AshPostgres.GenerateMigrations`, or run `mix help ash_postgres.generate_migrations` -For running your migrations, there is a mix task that will find all of the repos configured in your apis and run their +For running your migrations, there is a mix task that will find all of the repos configured in your domains and run their migrations. It is a thin wrapper around `mix ecto.migrate`. Ours is called `mix ash_postgres.migrate` If you want to run or rollback individual migrations, use the corresponding @@ -146,17 +146,17 @@ Tasks that need to be executed in the released application (because mix is not p end defp repos do - apis() - |> Enum.flat_map(fn api -> - api - |> Ash.Api.Info.resources() + domains() + |> Enum.flat_map(fn domain -> + domain + |> Ash.Domain.Info.resources() |> Enum.map(&AshPostgres.DataLayer.Info.repo/1) end) |> Enum.uniq() end - defp apis do - Application.fetch_env!(@app, :ash_apis) + defp domains do + Application.fetch_env!(@app, :ash_domains) end defp load_app do diff --git a/documentation/topics/polymorphic_resources.md b/documentation/topics/polymorphic_resources.md index fdab27a..038f1cd 100644 --- a/documentation/topics/polymorphic_resources.md +++ b/documentation/topics/polymorphic_resources.md @@ -5,6 +5,7 @@ To support leveraging the same resource backed by multiple tables (useful for th ```elixir defmodule MyApp.Reaction do use Ash.Resource, + domain: MyDomain, data_layer: AshPostgres.DataLayer postgres do @@ -12,9 +13,9 @@ defmodule MyApp.Reaction do end attributes do - attribute(:resource_id, :uuid) + attribute :resource_id, :uuid, public?: true end - + ... end ``` @@ -24,6 +25,7 @@ Then, in your related resources, you set the table context like so: ```elixir defmodule MyApp.Post do use Ash.Resource, + domain: MyDomain, data_layer: AshPostgres.DataLayer ... @@ -37,6 +39,7 @@ end defmodule MyApp.Comment do use Ash.Resource, + domain: MyDomain, data_layer: AshPostgres.DataLayer ... @@ -61,6 +64,7 @@ For example: ```elixir defmodule MyApp.Reaction do + # ... actions do read :for_comments do prepare set_context(%{data_layer: %{table: "comment_reactions"}}) @@ -78,5 +82,5 @@ end When a migration is marked as `polymorphic? true`, the migration generator will look at all resources that are related to it, that set the `%{data_layer: %{table: "table"}}` context. For each of those, a migration is generated/managed automatically. This means that adding reactions -to a new resource is as easy as adding the relationship and table context, and then running +to a new resource is as easy as adding the relationship and table context, and then running `mix ash_postgres.generate_migrations`. diff --git a/documentation/tutorials/get-started-with-postgres.md b/documentation/tutorials/get-started-with-postgres.md index 5a6bfa5..13e2fcc 100644 --- a/documentation/tutorials/get-started-with-postgres.md +++ b/documentation/tutorials/get-started-with-postgres.md @@ -68,7 +68,7 @@ import Config # This should already have been added in the first # getting started guide config :helpdesk, - ash_apis: [Helpdesk.Support] + ash_domains: [Helpdesk.Support] config :helpdesk, ecto_repos: [Helpdesk.Repo] @@ -155,6 +155,7 @@ Now we can add the data layer to our resources. The basic configuration for a re # in lib/helpdesk/support/resources/ticket.ex use Ash.Resource, + domain: Helpdesk.Support, data_layer: AshPostgres.DataLayer postgres do @@ -167,6 +168,7 @@ Now we can add the data layer to our resources. The basic configuration for a re # in lib/helpdesk/support/resources/representative.ex use Ash.Resource, + domain: Helpdesk.Support, data_layer: AshPostgres.DataLayer postgres do diff --git a/lib/aggregate.ex b/lib/aggregate.ex index 581ee86..84a4cf7 100644 --- a/lib/aggregate.ex +++ b/lib/aggregate.ex @@ -499,8 +499,7 @@ defmodule AshPostgres.Aggregate do end defp resource_aggregates_to_aggregates(resource, aggregates) do - aggregates - |> Enum.reduce_while({:ok, []}, fn + Enum.reduce_while(aggregates, {:ok, []}, fn %Ash.Query.Aggregate{} = aggregate, {:ok, aggregates} -> {:cont, {:ok, [aggregate | aggregates]}} @@ -523,6 +522,8 @@ defmodule AshPostgres.Aggregate do default: aggregate.default, filterable?: aggregate.filterable?, type: aggregate.type, + sortable?: aggregate.filterable?, + include_nil?: aggregate.include_nil?, constraints: aggregate.constraints, implementation: aggregate.implementation, uniq?: aggregate.uniq?, @@ -685,11 +686,11 @@ defmodule AshPostgres.Aggregate do type: type, constraints: constraints } -> - {:ok, new_calc} = Ash.Query.Calculation.new(name, module, opts, {type, constraints}) + {:ok, new_calc} = Ash.Query.Calculation.new(name, module, opts, type, constraints) expression = module.expression(opts, aggregate.context) expression = - Ash.Filter.build_filter_from_template( + Ash.Expr.fill_template( expression, aggregate.context[:actor], aggregate.context, @@ -719,11 +720,11 @@ defmodule AshPostgres.Aggregate do expression = module.expression(opts, aggregate.context) expression = - Ash.Filter.build_filter_from_template( + Ash.Expr.fill_template( expression, - aggregate.context[:actor], - aggregate.context, - aggregate.context + aggregate.context.actor, + aggregate.context.arguments, + aggregate.context.source_context ) {:ok, expression} = @@ -1189,6 +1190,13 @@ defmodule AshPostgres.Aggregate do has_sort? = has_sort?(aggregate.query) + array_agg = + if AshPostgres.DataLayer.Info.pg_version_matches?(aggregate.resource, ">= 16.0.0") do + "any_value" + else + "array_agg" + end + {sorted, query} = if has_sort? || first_relationship.sort not in [nil, []] do {sort, binding} = @@ -1211,31 +1219,63 @@ defmodule AshPostgres.Aggregate do :return ) - question_marks = Enum.map(sort_expr, fn _ -> " ? " end) + if aggregate.include_nil? do + question_marks = Enum.map(sort_expr, fn _ -> " ? " end) - {:ok, expr} = - AshPostgres.Functions.Fragment.casted_new( - ["array_agg(? ORDER BY #{question_marks})", field] ++ sort_expr - ) + {:ok, expr} = + Ash.Query.Function.Fragment.casted_new( + ["#{array_agg}(? ORDER BY #{question_marks} FILTER (WHERE ? IS NOT NULL))", field] ++ + sort_expr ++ [field] + ) - {sort_expr, acc} = - AshPostgres.Expr.dynamic_expr(query, expr, query.__ash_bindings__, false) + {sort_expr, acc} = + AshPostgres.Expr.dynamic_expr(query, expr, query.__ash_bindings__, false) - query = - AshPostgres.DataLayer.merge_expr_accumulator(query, acc) + query = + AshPostgres.DataLayer.merge_expr_accumulator(query, acc) - {sort_expr, query} + {sort_expr, query} + else + question_marks = Enum.map(sort_expr, fn _ -> " ? " end) + + {:ok, expr} = + Ash.Query.Function.Fragment.casted_new( + ["#{array_agg}(? ORDER BY #{question_marks})", field] ++ sort_expr + ) + + {sort_expr, acc} = + AshPostgres.Expr.dynamic_expr(query, expr, query.__ash_bindings__, false) + + query = + AshPostgres.DataLayer.merge_expr_accumulator(query, acc) + + {sort_expr, query} + end else - {Ecto.Query.dynamic( - [row], - fragment("array_agg(?)", ^field) - ), query} + case array_agg do + "array_agg" -> + {Ecto.Query.dynamic( + [row], + fragment("array_agg(?)", ^field) + ), query} + + "any_value" -> + {Ecto.Query.dynamic( + [row], + fragment("any_value(?)", ^field) + ), query} + end end {query, filtered} = filter_field(sorted, query, aggregate, relationship_path, is_single?) - value = Ecto.Query.dynamic(fragment("(?)[1]", ^filtered)) + value = + if array_agg == "array_agg" do + Ecto.Query.dynamic(fragment("(?)[1]", ^filtered)) + else + filtered + end with_default = if aggregate.default_value do @@ -1327,10 +1367,26 @@ defmodule AshPostgres.Aggregate do "" end - {:ok, expr} = - AshPostgres.Functions.Fragment.casted_new( - ["array_agg(#{distinct}? ORDER BY #{question_marks})", field] ++ sort_expr - ) + expr = + if aggregate.include_nil? do + {:ok, expr} = + Ash.Query.Function.Fragment.casted_new( + [ + "array_agg(#{distinct}? ORDER BY #{question_marks} FILTER (WHERE ? IS NOT NULL))", + field + ] ++ + sort_expr ++ [field] + ) + + expr + else + {:ok, expr} = + Ash.Query.Function.Fragment.casted_new( + ["array_agg(#{distinct}? ORDER BY #{question_marks})", field] ++ sort_expr + ) + + expr + end {expr, acc} = AshPostgres.Expr.dynamic_expr(query, expr, query.__ash_bindings__, false) diff --git a/lib/calculation.ex b/lib/calculation.ex index f896698..1e03028 100644 --- a/lib/calculation.ex +++ b/lib/calculation.ex @@ -73,10 +73,11 @@ defmodule AshPostgres.Calculation do expression = Ash.Actions.Read.add_calc_context_to_filter( expression, - calculation.context[:actor], - calculation.context[:authorize?], - calculation.context[:tenant], - calculation.context[:tracer] + calculation.context.actor, + calculation.context.authorize?, + calculation.context.tenant, + calculation.context.tracer, + nil ) {expr, acc} = diff --git a/lib/data_layer.ex b/lib/data_layer.ex index 995bc23..fec2784 100644 --- a/lib/data_layer.ex +++ b/lib/data_layer.ex @@ -384,11 +384,12 @@ defmodule AshPostgres.DataLayer do use Spark.Dsl.Extension, sections: @sections, - transformers: [ - AshPostgres.Transformers.ValidateReferences, - AshPostgres.Transformers.EnsureTableOrPolymorphic, - AshPostgres.Transformers.PreventMultidimensionalArrayAggregates, - AshPostgres.Transformers.PreventAttributeMultitenancyAndNonFullMatchType + verifiers: [ + AshPostgres.Verifiers.VerifyPostgresVersion, + AshPostgres.Verifiers.PreventMultidimensionalArrayAggregates, + AshPostgres.Verifiers.ValidateReferences, + AshPostgres.Verifiers.PreventAttributeMultitenancyAndNonFullMatchType, + AshPostgres.Verifiers.EnsureTableOrPolymorphic ] def migrate(args) do @@ -704,7 +705,7 @@ defmodule AshPostgres.DataLayer do repo = dynamic_repo(resource, query) with_savepoint(repo, query, fn -> - {:ok, repo.all(query, repo_opts(nil, nil, resource)) |> remap_mapped_fields(query)} + {:ok, repo.all(query, repo_opts(repo, nil, nil, resource)) |> remap_mapped_fields(query)} end) end rescue @@ -715,7 +716,7 @@ defmodule AshPostgres.DataLayer do defp no_table?(%{from: %{source: {"", _}}}), do: true defp no_table?(_), do: false - defp repo_opts(timeout, nil, resource) do + defp repo_opts(_repo, timeout, nil, resource) do if schema = AshPostgres.DataLayer.Info.schema(resource) do [prefix: schema] else @@ -724,9 +725,9 @@ defmodule AshPostgres.DataLayer do |> add_timeout(timeout) end - defp repo_opts(timeout, tenant, resource) do + defp repo_opts(_repo, timeout, tenant, resource) do if Ash.Resource.Info.multitenancy_strategy(resource) == :context do - [prefix: tenant] + [prefix: Ash.ToTenant.to_tenant(resource, tenant)] else if schema = AshPostgres.DataLayer.Info.schema(resource) do [prefix: schema] @@ -748,7 +749,6 @@ defmodule AshPostgres.DataLayer do config = AshPostgres.DataLayer.Info.repo(resource, :mutate).config() functions = [ - AshPostgres.Functions.Fragment, AshPostgres.Functions.Like, AshPostgres.Functions.ILike ] @@ -844,7 +844,8 @@ defmodule AshPostgres.DataLayer do %{} _ -> - dynamic_repo(resource, query).one(query, repo_opts(nil, nil, resource)) + repo = dynamic_repo(resource, query) + repo.one(query, repo_opts(repo, nil, nil, resource)) end {:ok, add_single_aggs(result, resource, original_query, cant_group)} @@ -880,10 +881,12 @@ defmodule AshPostgres.DataLayer do |> Ecto.Query.select(%{}) end + repo = dynamic_repo(resource, filtered) + Map.put( result || %{}, agg.name, - dynamic_repo(resource, filtered).exists?(filtered, repo_opts(nil, nil, resource)) + repo.exists?(filtered, repo_opts(repo, nil, nil, resource)) ) agg, result -> @@ -953,9 +956,11 @@ defmodule AshPostgres.DataLayer do first_relationship ) + repo = dynamic_repo(resource, query) + Map.merge( result || %{}, - dynamic_repo(resource, query).one(query, repo_opts(nil, nil, resource)) + repo.one(query, repo_opts(repo, nil, nil, resource)) ) end) end @@ -1049,9 +1054,11 @@ defmodule AshPostgres.DataLayer do %{} _ -> - dynamic_repo(source_resource, query).one( + repo = dynamic_repo(source_resource, query) + + repo.one( query, - repo_opts(nil, nil, source_resource) + repo_opts(repo, nil, nil, source_resource) ) end @@ -1082,10 +1089,12 @@ defmodule AshPostgres.DataLayer do |> elem(0) |> Map.get(:resource) + repo = dynamic_repo(source_resource, lateral_join_query) + results = - dynamic_repo(source_resource, lateral_join_query).all( + repo.all( lateral_join_query, - repo_opts(nil, nil, source_resource) + repo_opts(repo, nil, nil, source_resource) ) |> remap_mapped_fields(query) @@ -1357,7 +1366,8 @@ defmodule AshPostgres.DataLayer do @doc false def set_subquery_prefix(data_layer_query, source_query, resource) do - config = AshPostgres.DataLayer.Info.repo(resource, :mutate).config() + repo = AshPostgres.DataLayer.Info.repo(resource, :mutate) + config = repo.config() case data_layer_query do %{__ash_bindings__: %{context: %{data_layer: %{schema: schema}}}} when not is_nil(schema) -> @@ -1375,20 +1385,16 @@ defmodule AshPostgres.DataLayer do %{ data_layer_query | prefix: - to_string( - query_tenant || AshPostgres.DataLayer.Info.schema(resource) || - config[:default_prefix] || - "public" - ) + query_tenant || AshPostgres.DataLayer.Info.schema(resource) || + config[:default_prefix] || + "public" } else %{ data_layer_query | prefix: - to_string( - AshPostgres.DataLayer.Info.schema(resource) || config[:default_prefix] || - "public" - ) + AshPostgres.DataLayer.Info.schema(resource) || config[:default_prefix] || + "public" } end end @@ -1418,7 +1424,7 @@ defmodule AshPostgres.DataLayer do data end |> Map.update!(:__meta__, &Map.put(&1, :source, table(resource, changeset))) - |> ecto_changeset(changeset, :update, true, true) + |> ecto_changeset(changeset, :update, true) case bulk_updatable_query(query, resource, changeset.atomics, changeset.context) do {:error, error} -> @@ -1427,12 +1433,12 @@ defmodule AshPostgres.DataLayer do {:ok, query} -> try do repo = dynamic_repo(resource, changeset) - repo_opts = repo_opts(changeset.timeout, changeset.tenant, changeset.resource) + repo_opts = repo_opts(repo, changeset.timeout, changeset.tenant, changeset.resource) case query_with_atomics( resource, query, - ecto_changeset.filters, + changeset.filter, changeset.atomics, ecto_changeset.changes, [] @@ -1582,7 +1588,7 @@ defmodule AshPostgres.DataLayer do data end |> Map.update!(:__meta__, &Map.put(&1, :source, table(resource, changeset))) - |> ecto_changeset(changeset, :update, true, true) + |> ecto_changeset(changeset, :update, true) try do query = @@ -1599,10 +1605,10 @@ defmodule AshPostgres.DataLayer do end |> Ecto.Query.exclude(:order_by) - repo_opts = repo_opts(changeset.timeout, changeset.tenant, changeset.resource) - repo = dynamic_repo(resource, changeset) + repo_opts = repo_opts(repo, changeset.timeout, changeset.tenant, changeset.resource) + query = if Enum.any?(query.joins, &(&1.qual != :inner)) do root_query = @@ -1663,7 +1669,11 @@ defmodule AshPostgres.DataLayer do @impl true def bulk_create(resource, stream, options) do - opts = repo_opts(nil, options[:tenant], resource) + changesets = Enum.to_list(stream) + + repo = dynamic_repo(resource, Enum.at(changesets, 0)) + + opts = repo_opts(repo, nil, options[:tenant], resource) opts = if options.return_records? do @@ -1672,8 +1682,6 @@ defmodule AshPostgres.DataLayer do opts end - changesets = Enum.to_list(stream) - repo = dynamic_repo(resource, Enum.at(changesets, 0)) source = resolve_source(resource, Enum.at(changesets, 0)) try do @@ -1681,7 +1689,7 @@ defmodule AshPostgres.DataLayer do if options[:upsert?] do # Ash groups changesets by atomics before dispatching them to the data layer # this means that all changesets have the same atomics - %{atomics: atomics, filters: filters} = Enum.at(changesets, 0) + %{atomics: atomics, filter: filter} = Enum.at(changesets, 0) query = from(row in source, as: ^0) @@ -1696,7 +1704,7 @@ defmodule AshPostgres.DataLayer do case query_with_atomics( resource, query, - filters, + filter, atomics, %{}, upsert_set @@ -1967,10 +1975,6 @@ defmodule AshPostgres.DataLayer do end) end - defp handle_errors({:error, %Ecto.Changeset{errors: errors}}) do - {:error, Enum.map(errors, &to_ash_error/1)} - end - defp to_ash_error({field, {message, vars}}) do Ash.Error.Changes.InvalidAttribute.exception( field: field, @@ -1979,25 +1983,7 @@ defmodule AshPostgres.DataLayer do ) end - defp ecto_changeset(record, changeset, type, table_error? \\ true, bulk_update? \\ false) do - filters = - if changeset.action_type == :create do - %{} - else - Map.get(changeset, :filters, %{}) - end - - filters = - if changeset.action_type == :create || bulk_update? do - filters - else - changeset.resource - |> Ash.Resource.Info.primary_key() - |> Enum.reduce(filters, fn key, filters -> - Map.put(filters, key, Map.get(record, key)) - end) - end - + defp ecto_changeset(record, changeset, type, table_error? \\ true) do attributes = changeset.resource |> Ash.Resource.Info.attributes() @@ -2013,7 +1999,6 @@ defmodule AshPostgres.DataLayer do |> to_ecto() |> set_table(changeset, type, table_error?) |> Ecto.Changeset.change(Map.take(changeset.attributes, attributes_to_change)) - |> Map.update!(:filters, &Map.merge(&1, filters)) |> add_configured_foreign_key_constraints(record.__struct__) |> add_unique_indexes(record.__struct__, changeset) |> add_check_constraints(record.__struct__) @@ -2615,7 +2600,11 @@ defmodule AshPostgres.DataLayer do |> ecto_changeset(changeset, :update) source = resolve_source(resource, changeset) - query = from(row in source, as: ^0) |> default_bindings(resource, changeset.context) + + query = + from(row in source, as: ^0) + |> default_bindings(resource, changeset.context) + |> pkey_filter(changeset.data) select = Keyword.keys(changeset.atomics) ++ Ash.Resource.Info.primary_key(resource) @@ -2630,7 +2619,7 @@ defmodule AshPostgres.DataLayer do case query_with_atomics( resource, query, - ecto_changeset.filters, + changeset.filter, changeset.atomics, ecto_changeset.changes, [] @@ -2639,13 +2628,12 @@ defmodule AshPostgres.DataLayer do {:ok, changeset.data} {:ok, query} -> - repo_opts = repo_opts(changeset.timeout, changeset.tenant, changeset.resource) + repo = dynamic_repo(resource, changeset) + repo_opts = repo_opts(repo, changeset.timeout, changeset.tenant, changeset.resource) repo_opts = Keyword.put(repo_opts, :returning, Keyword.keys(changeset.atomics)) - repo = dynamic_repo(resource, changeset) - result = with_savepoint(repo, query, fn -> repo.update_all( @@ -2660,7 +2648,7 @@ defmodule AshPostgres.DataLayer do {:error, Ash.Error.Changes.StaleRecord.exception( resource: resource, - filters: ecto_changeset.filters + filters: changeset.filter )} {1, [result]} -> @@ -2684,20 +2672,29 @@ defmodule AshPostgres.DataLayer do end end + defp pkey_filter(query, %resource{} = record) do + pkey = + record + |> Map.take(Ash.Resource.Info.primary_key(resource)) + |> Map.to_list() + + Ecto.Query.where(query, ^pkey) + end + defp query_with_atomics( resource, query, - filters, + filter, atomics, updating_one_changes, existing_set ) do query = - Enum.reduce(filters, query, fn {key, value}, query -> - from(row in query, - where: field(row, ^key) == ^value - ) - end) + if is_nil(filter) do + query + else + filter(query, filter, resource) + end atomics_result = Enum.reduce_while(atomics, {:ok, query, []}, fn {field, expr}, {:ok, query, set} -> @@ -2792,20 +2789,23 @@ defmodule AshPostgres.DataLayer do try do repo = dynamic_repo(resource, changeset) - result = - repo.delete( - ecto_changeset, - repo_opts(changeset.timeout, changeset.tenant, changeset.resource) - ) + source = resolve_source(resource, changeset) - result - |> from_ecto() + from(row in source, as: ^0) + |> default_bindings(resource, changeset.context) + |> filter(changeset.filter, resource) |> case do - {:ok, _record} -> + {:ok, query} -> + query + |> pkey_filter(record) + |> repo.delete_all( + repo_opts(repo, changeset.timeout, changeset.tenant, changeset.resource) + ) + :ok {:error, error} -> - handle_errors({:error, error}) + {:error, error} end rescue e -> @@ -3201,9 +3201,13 @@ defmodule AshPostgres.DataLayer do |> Enum.reduce(query, fn filter, query -> {dynamic, acc} = AshPostgres.Expr.dynamic_expr(query, filter, query.__ash_bindings__) - query - |> Ecto.Query.where(^dynamic) - |> merge_expr_accumulator(acc) + if is_nil(dynamic) do + query + else + query + |> Ecto.Query.where([], ^dynamic) + |> merge_expr_accumulator(acc) + end end) end diff --git a/lib/data_layer/info.ex b/lib/data_layer/info.ex index 3184660..8126ce1 100644 --- a/lib/data_layer/info.ex +++ b/lib/data_layer/info.ex @@ -14,6 +14,21 @@ defmodule AshPostgres.DataLayer.Info do end end + @doc "Checks a version requirement against the resource's repo's postgres version" + def pg_version_matches?(resource, requirement) do + resource + |> pg_version() + |> Version.match?(requirement) + end + + @doc "Gets the resource's repo's postgres version" + def pg_version(resource) do + case repo(resource, :read).pg_version() do + %Version{} = version -> version + string when is_binary(string) -> Version.parse!(string) + end + end + @doc "The configured table for a resource" def table(resource) do Extension.get_opt(resource, [:postgres], :table, nil, true) diff --git a/lib/expr.ex b/lib/expr.ex index 8cd6b87..305f9e9 100644 --- a/lib/expr.ex +++ b/lib/expr.ex @@ -14,6 +14,7 @@ defmodule AshPostgres.Expr do DateAdd, DateTimeAdd, Error, + Fragment, FromNow, GetPath, If, @@ -21,6 +22,7 @@ defmodule AshPostgres.Expr do Length, Now, Round, + StringDowncase, StringJoin, StringLength, StringSplit, @@ -29,7 +31,7 @@ defmodule AshPostgres.Expr do Type } - alias AshPostgres.Functions.{Fragment, ILike, Like, TrigramSimilarity, VectorCosineDistance} + alias AshPostgres.Functions.{ILike, Like, TrigramSimilarity, VectorCosineDistance} require Ecto.Query @@ -725,6 +727,27 @@ defmodule AshPostgres.Expr do ) end + defp do_dynamic_expr( + query, + %StringDowncase{arguments: [value], embedded?: pred_embedded?}, + bindings, + embedded?, + acc, + type + ) do + do_dynamic_expr( + query, + %Fragment{ + embedded?: pred_embedded?, + arguments: [raw: "lower(", expr: value, raw: ")"] + }, + bindings, + embedded?, + acc, + type + ) + end + defp do_dynamic_expr( query, %StringTrim{arguments: [value], embedded?: pred_embedded?}, @@ -1074,10 +1097,11 @@ defmodule AshPostgres.Expr do expression = Ash.Actions.Read.add_calc_context_to_filter( expression, - calculation.context[:actor], - calculation.context[:authorize?], - calculation.context[:tenant], - calculation.context[:tracer] + calculation.context.actor, + calculation.context.authorize?, + calculation.context.tenant, + calculation.context.tracer, + nil ) do_dynamic_expr( @@ -1190,7 +1214,8 @@ defmodule AshPostgres.Expr do aggregate.context[:actor], aggregate.context[:authorize?], aggregate.context[:tenant], - aggregate.context[:tracer] + aggregate.context[:tracer], + nil ) {value, acc} = do_dynamic_expr(query, ref, query.__ash_bindings__, false, acc) @@ -1452,10 +1477,10 @@ defmodule AshPostgres.Expr do end {encoded, acc} = - if Ash.Filter.TemplateHelpers.expr?(input) do + if Ash.Expr.expr?(input) do frag_parts = Enum.flat_map(input, fn {key, value} -> - if Ash.Filter.TemplateHelpers.expr?(value) do + if Ash.Expr.expr?(value) do [ expr: to_string(key), raw: "::text, ", @@ -1720,7 +1745,7 @@ defmodule AshPostgres.Expr do when is_map(value) and not is_struct(value) do if bindings[:location] == :update && Enum.any?(value, fn {key, value} -> - Ash.Filter.TemplateHelpers.expr?(key) || Ash.Filter.TemplateHelpers.expr?(value) + Ash.Expr.expr?(key) || Ash.Expr.expr?(value) end) do elements = value @@ -1770,7 +1795,7 @@ defmodule AshPostgres.Expr do if other && is_atom(other) && !is_boolean(other) do {to_string(other), acc} else - if Ash.Filter.TemplateHelpers.expr?(other) do + if Ash.Expr.expr?(other) do if is_list(other) do list_expr(query, other, bindings, true, acc, type) else @@ -1801,7 +1826,7 @@ defmodule AshPostgres.Expr do end defp do_dynamic_expr(query, value, bindings, false, acc, type) do - if Ash.Filter.TemplateHelpers.expr?(value) do + if Ash.Expr.expr?(value) do if is_list(value) do list_expr(query, value, bindings, false, acc, type) else @@ -2033,7 +2058,7 @@ defmodule AshPostgres.Expr do defp list_expr(query, value, bindings, embedded?, acc, type) do if !Enum.empty?(value) && Enum.any?(value, fn value -> - Ash.Filter.TemplateHelpers.expr?(value) || is_map(value) || is_list(value) + Ash.Expr.expr?(value) || is_map(value) || is_list(value) end) do type = case type do diff --git a/lib/functions/fragment.ex b/lib/functions/fragment.ex deleted file mode 100644 index 84387e8..0000000 --- a/lib/functions/fragment.ex +++ /dev/null @@ -1,72 +0,0 @@ -defmodule AshPostgres.Functions.Fragment do - @moduledoc """ - A function that maps to ecto's `fragment` function - - https://hexdocs.pm/ecto/Ecto.Query.API.html#fragment/1 - """ - - use Ash.Query.Function, name: :fragment - - def private?, do: true - - # Varargs is special, and should only be used in rare circumstances (like this one) - # no type casting or help can be provided for these functions. - def args, do: :var_args - - def new([fragment | _]) when not is_binary(fragment) do - {:error, "First argument to `fragment` must be a string."} - end - - def new([fragment | rest]) do - split = split_fragment(fragment) - - if Enum.count(split, &(&1 == :slot)) != length(rest) do - {:error, - "fragment(...) expects extra arguments in the same amount of question marks in string. " <> - "It received #{Enum.count(split, &(&1 == :slot))} extra argument(s) but expected #{length(rest)}"} - else - {:ok, %__MODULE__{arguments: merge_fragment(split, rest)}} - end - end - - def casted_new([fragment | _]) when not is_binary(fragment) do - {:error, "First argument to `fragment` must be a string."} - end - - def casted_new([fragment | rest]) do - split = split_fragment(fragment) - - if Enum.count(split, &(&1 == :slot)) != length(rest) do - {:error, - "fragment(...) expects extra arguments in the same amount of question marks in string. " <> - "It received #{Enum.count(split, &(&1 == :slot))} extra argument(s) but expected #{length(rest)}"} - else - {:ok, %__MODULE__{arguments: merge_fragment(split, rest, :casted_expr)}} - end - end - - defp merge_fragment(expr, args, tag \\ :expr) - defp merge_fragment([], [], _tag), do: [] - - defp merge_fragment([:slot | rest], [arg | rest_args], tag) do - [{tag, arg} | merge_fragment(rest, rest_args, tag)] - end - - defp merge_fragment([val | rest], rest_args, tag) do - [{:raw, val} | merge_fragment(rest, rest_args, tag)] - end - - defp split_fragment(frag, consumed \\ "") - - defp split_fragment(<<>>, consumed), - do: [consumed] - - defp split_fragment(<>, consumed), - do: [consumed, :slot | split_fragment(rest, "")] - - defp split_fragment(<>, consumed), - do: split_fragment(rest, consumed <> <>) - - defp split_fragment(<>, consumed), - do: split_fragment(rest, consumed <> <>) -end diff --git a/lib/migration_generator/migration_generator.ex b/lib/migration_generator/migration_generator.ex index cbe2c7d..1d2c979 100644 --- a/lib/migration_generator/migration_generator.ex +++ b/lib/migration_generator/migration_generator.ex @@ -20,11 +20,11 @@ defmodule AshPostgres.MigrationGenerator do check: false, drop_columns: false - def generate(apis, opts \\ []) do - apis = List.wrap(apis) + def generate(domains, opts \\ []) do + domains = List.wrap(domains) opts = opts(opts) - all_resources = Enum.uniq(Enum.flat_map(apis, &Ash.Api.Info.resources/1)) + all_resources = Enum.uniq(Enum.flat_map(domains, &Ash.Domain.Info.resources/1)) {tenant_snapshots, snapshots} = all_resources @@ -60,8 +60,8 @@ defmodule AshPostgres.MigrationGenerator do Does not support everything supported by the migration generator. """ - def take_snapshots(api, repo, only_resources \\ nil) do - all_resources = api |> Ash.Api.Info.resources() |> Enum.uniq() + def take_snapshots(domain, repo, only_resources \\ nil) do + all_resources = domain |> Ash.Domain.Info.resources() |> Enum.uniq() all_resources |> Enum.filter(fn resource -> diff --git a/lib/mix/helpers.ex b/lib/mix/helpers.ex index bc6c8bc..2a4ea75 100644 --- a/lib/mix/helpers.ex +++ b/lib/mix/helpers.ex @@ -1,6 +1,6 @@ defmodule AshPostgres.MixHelpers do @moduledoc false - def apis!(opts, args) do + def domains!(opts, args) do apps = if apps_paths = Mix.Project.apps_paths() do apps_paths |> Map.keys() |> Enum.sort() @@ -8,46 +8,46 @@ defmodule AshPostgres.MixHelpers do [Mix.Project.config()[:app]] end - configured_apis = Enum.flat_map(apps, &Application.get_env(&1, :ash_apis, [])) + configure_domains = Enum.flat_map(apps, &Application.get_env(&1, :ash_domains, [])) - apis = - if opts[:apis] && opts[:apis] != "" do - opts[:apis] + domains = + if opts[:domains] && opts[:domains] != "" do + opts[:domains] |> Kernel.||("") |> String.split(",") |> Enum.flat_map(fn "" -> [] - api -> - [Module.concat([api])] + domain -> + [Module.concat([domain])] end) else - configured_apis + configure_domains end - apis + domains |> Enum.map(&ensure_compiled(&1, args)) |> case do [] -> - raise "must supply the --apis argument, or set `config :my_app, ash_apis: [...]` in config" + raise "must supply the --domains argument, or set `config :my_app, ash_domains: [...]` in config" - apis -> - apis + domains -> + domains end end def repos!(opts, args) do - apis = apis!(opts, args) + domains = domains!(opts, args) resources = - apis - |> Enum.flat_map(&Ash.Api.Info.resources/1) + domains + |> Enum.flat_map(&Ash.Domain.Info.resources/1) |> Enum.filter(&(Ash.DataLayer.data_layer(&1) == AshPostgres.DataLayer)) |> case do [] -> raise """ - No resources with `data_layer: AshPostgres.DataLayer` found in the apis #{Enum.map_join(apis, ",", &inspect/1)}. + No resources with `data_layer: AshPostgres.DataLayer` found in the domains #{Enum.map_join(domains, ",", &inspect/1)}. Must be able to find at least one resource with `data_layer: AshPostgres.DataLayer`. """ @@ -64,7 +64,7 @@ defmodule AshPostgres.MixHelpers do |> case do [] -> raise """ - No repos could be found configured on the resources in the apis: #{Enum.map_join(apis, ",", &inspect/1)} + No repos could be found configured on the resources in the domains: #{Enum.map_join(domains, ",", &inspect/1)} At least one resource must have a repo configured. @@ -98,7 +98,7 @@ defmodule AshPostgres.MixHelpers do end end - defp ensure_compiled(api, args) do + defp ensure_compiled(domain, args) do if Code.ensure_loaded?(Mix.Tasks.App.Config) do Mix.Task.run("app.config", args) else @@ -106,18 +106,18 @@ defmodule AshPostgres.MixHelpers do "--no-compile" not in args && Mix.Task.run("compile", args) end - case Code.ensure_compiled(api) do + case Code.ensure_compiled(domain) do {:module, _} -> - api - |> Ash.Api.Info.resources() + domain + |> Ash.Domain.Info.resources() |> Enum.each(&Code.ensure_compiled/1) # TODO: We shouldn't need to make sure that the resources are compiled - api + domain {:error, error} -> - Mix.raise("Could not load #{inspect(api)}, error: #{inspect(error)}. ") + Mix.raise("Could not load #{inspect(domain)}, error: #{inspect(error)}. ") end end diff --git a/lib/mix/tasks/ash_postgres.create.ex b/lib/mix/tasks/ash_postgres.create.ex index bdfaa61..e4de634 100644 --- a/lib/mix/tasks/ash_postgres.create.ex +++ b/lib/mix/tasks/ash_postgres.create.ex @@ -5,7 +5,7 @@ defmodule Mix.Tasks.AshPostgres.Create do @switches [ quiet: :boolean, - apis: :string, + domains: :string, no_compile: :boolean, no_deps_check: :boolean ] @@ -15,16 +15,16 @@ defmodule Mix.Tasks.AshPostgres.Create do ] @moduledoc """ - Create the storage for repos in all resources for the given (or configured) apis. + Create the storage for repos in all resources for the given (or configured) domains. ## Examples mix ash_postgres.create - mix ash_postgres.create --apis MyApp.Api1,MyApp.Api2 + mix ash_postgres.create --domains MyApp.Domain1,MyApp.Domain2 ## Command line options - * `--apis` - the apis who's repos you want to migrate. + * `--domains` - the domains who's repos you want to migrate. * `--quiet` - do not log output * `--no-compile` - do not compile before creating * `--no-deps-check` - do not compile before creating @@ -41,7 +41,7 @@ defmodule Mix.Tasks.AshPostgres.Create do ["-r", to_string(repo)] end) - rest_opts = AshPostgres.MixHelpers.delete_arg(args, "--apis") + rest_opts = AshPostgres.MixHelpers.delete_arg(args, "--domains") Mix.Task.reenable("ecto.create") Mix.Task.run("ecto.create", repo_args ++ rest_opts) diff --git a/lib/mix/tasks/ash_postgres.drop.ex b/lib/mix/tasks/ash_postgres.drop.ex index af121b0..b8ac91d 100644 --- a/lib/mix/tasks/ash_postgres.drop.ex +++ b/lib/mix/tasks/ash_postgres.drop.ex @@ -1,7 +1,7 @@ defmodule Mix.Tasks.AshPostgres.Drop do use Mix.Task - @shortdoc "Drops the repository storage for the repos in the specified (or configured) apis" + @shortdoc "Drops the repository storage for the repos in the specified (or configured) domains" @default_opts [force: false, force_drop: false] @aliases [ @@ -13,7 +13,7 @@ defmodule Mix.Tasks.AshPostgres.Drop do force: :boolean, force_drop: :boolean, quiet: :boolean, - apis: :string, + domains: :string, no_compile: :boolean, no_deps_check: :boolean ] @@ -24,11 +24,11 @@ defmodule Mix.Tasks.AshPostgres.Drop do ## Examples mix ash_postgres.drop - mix ash_postgres.drop -r MyApp.Api1,MyApp.Api2 + mix ash_postgres.drop -r MyApp.Repo1,MyApp.Repo2 ## Command line options - * `--apis` - the apis who's repos should be dropped + * `--domains` - the domains who's repos should be dropped * `-q`, `--quiet` - run the command quietly * `-f`, `--force` - do not ask for confirmation when dropping the database. Configuration is asked only when `:start_permanent` is set to true @@ -51,7 +51,7 @@ defmodule Mix.Tasks.AshPostgres.Drop do ["-r", to_string(repo)] end) - rest_opts = AshPostgres.MixHelpers.delete_arg(args, "--apis") + rest_opts = AshPostgres.MixHelpers.delete_arg(args, "--domains") Mix.Task.reenable("ecto.drop") Mix.Task.run("ecto.drop", repo_args ++ rest_opts) diff --git a/lib/mix/tasks/ash_postgres.generate_migrations.ex b/lib/mix/tasks/ash_postgres.generate_migrations.ex index 4a3154d..33ebb22 100644 --- a/lib/mix/tasks/ash_postgres.generate_migrations.ex +++ b/lib/mix/tasks/ash_postgres.generate_migrations.ex @@ -4,7 +4,7 @@ defmodule Mix.Tasks.AshPostgres.GenerateMigrations do Options: - * `apis` - a comma separated list of API modules, for which migrations will be generated + * `domains` - a comma separated list of Domain modules, for which migrations will be generated * `snapshot-path` - a custom path to store the snapshots, defaults to "priv/resource_snapshots" * `migration-path` - a custom path to store the migrations, defaults to "priv". Migrations are stored in a folder for each repo, so `priv/repo_name/migrations` @@ -87,7 +87,7 @@ defmodule Mix.Tasks.AshPostgres.GenerateMigrations do {opts, _} = OptionParser.parse!(args, strict: [ - apis: :string, + domains: :string, snapshot_path: :string, migration_path: :string, tenant_migration_path: :string, @@ -100,7 +100,7 @@ defmodule Mix.Tasks.AshPostgres.GenerateMigrations do ] ) - apis = AshPostgres.MixHelpers.apis!(opts, args) + domains = AshPostgres.MixHelpers.domains!(opts, args) opts = opts @@ -119,6 +119,6 @@ defmodule Mix.Tasks.AshPostgres.GenerateMigrations do """) end - AshPostgres.MigrationGenerator.generate(apis, opts) + AshPostgres.MigrationGenerator.generate(domains, opts) end end diff --git a/lib/mix/tasks/ash_postgres.migrate.ex b/lib/mix/tasks/ash_postgres.migrate.ex index d3d3cb6..d453025 100644 --- a/lib/mix/tasks/ash_postgres.migrate.ex +++ b/lib/mix/tasks/ash_postgres.migrate.ex @@ -4,7 +4,7 @@ defmodule Mix.Tasks.AshPostgres.Migrate do import AshPostgres.MixHelpers, only: [migrations_path: 2, tenant_migrations_path: 2, tenants: 2] - @shortdoc "Runs the repository migrations for all repositories in the provided (or congigured) apis" + @shortdoc "Runs the repository migrations for all repositories in the provided (or congigured) domains" @aliases [ n: :step @@ -20,7 +20,7 @@ defmodule Mix.Tasks.AshPostgres.Migrate do pool_size: :integer, log_sql: :boolean, strict_version_order: :boolean, - apis: :string, + domains: :string, no_compile: :boolean, no_deps_check: :boolean, migrations_path: :keep, @@ -42,7 +42,7 @@ defmodule Mix.Tasks.AshPostgres.Migrate do specific version number, supply `--to version_number`. To migrate a specific number of times, use `--step n`. - This is only really useful if your api or apis only use a single repo. + This is only really useful if your domains only use a single repo. If you have multiple repos and you want to run a single migration and/or migrate/roll them back to different points, you will need to use the ecto specific task, `mix ecto.migrate` and provide your repo name. @@ -53,7 +53,7 @@ defmodule Mix.Tasks.AshPostgres.Migrate do ## Examples mix ash_postgres.migrate - mix ash_postgres.migrate --apis MyApp.Api1,MyApp.Api2 + mix ash_postgres.migrate --domains MyApp.Domain1,MyApp.Domain2 mix ash_postgres.migrate -n 3 mix ash_postgres.migrate --step 3 @@ -62,7 +62,7 @@ defmodule Mix.Tasks.AshPostgres.Migrate do ## Command line options - * `--apis` - the apis who's repos should be migrated + * `--domains` - the domains who's repos should be migrated * `--tenants` - Run the tenant migrations @@ -107,7 +107,7 @@ defmodule Mix.Tasks.AshPostgres.Migrate do rest_opts = args - |> AshPostgres.MixHelpers.delete_arg("--apis") + |> AshPostgres.MixHelpers.delete_arg("--domains") |> AshPostgres.MixHelpers.delete_arg("--migrations-path") |> AshPostgres.MixHelpers.delete_flag("--tenants") |> AshPostgres.MixHelpers.delete_flag("--only-tenants") diff --git a/lib/mix/tasks/ash_postgres.rollback.ex b/lib/mix/tasks/ash_postgres.rollback.ex index ecb4765..b01d91d 100644 --- a/lib/mix/tasks/ash_postgres.rollback.ex +++ b/lib/mix/tasks/ash_postgres.rollback.ex @@ -4,7 +4,7 @@ defmodule Mix.Tasks.AshPostgres.Rollback do import AshPostgres.MixHelpers, only: [migrations_path: 2, tenant_migrations_path: 2, tenants: 2] - @shortdoc "Rolls back the repository migrations for all repositories in the provided (or configured) apis" + @shortdoc "Rolls back the repository migrations for all repositories in the provided (or configured) domains" @moduledoc """ Reverts applied migrations in the given repository. @@ -16,7 +16,7 @@ defmodule Mix.Tasks.AshPostgres.Rollback do specific number of times, use `--step n`. To undo all applied migrations, provide `--all`. - This is only really useful if your api or apis only use a single repo. + This is only really useful if your domains only use a single repo. If you have multiple repos and you want to run a single migration and/or migrate/roll them back to different points, you will need to use the ecto specific task, `mix ecto.migrate` and provide your repo name. @@ -30,7 +30,7 @@ defmodule Mix.Tasks.AshPostgres.Rollback do mix ash_postgres.rollback --to 20080906120000 ## Command line options - * `--apis` - the apis who's repos should be rolledback + * `--domains` - the domains who's repos should be rolledback * `--all` - revert all applied migrations * `--step` / `-n` - revert n number of applied migrations * `--to` / `-v` - revert all migrations down to and including version @@ -66,7 +66,7 @@ defmodule Mix.Tasks.AshPostgres.Rollback do rest_opts = args - |> AshPostgres.MixHelpers.delete_arg("--apis") + |> AshPostgres.MixHelpers.delete_arg("--domains") |> AshPostgres.MixHelpers.delete_arg("--migrations-path") |> AshPostgres.MixHelpers.delete_flag("--tenants") |> AshPostgres.MixHelpers.delete_flag("--only-tenants") diff --git a/lib/repo.ex b/lib/repo.ex index 01b6ceb..78e3bb8 100644 --- a/lib/repo.ex +++ b/lib/repo.ex @@ -44,6 +44,9 @@ defmodule AshPostgres.Repo do @doc "Use this to inform the data layer about what extensions are installed" @callback installed_extensions() :: [String.t() | module()] + @doc "Configure the version of postgres that is being used." + @callback pg_version() :: Version.t() + @doc """ Use this to inform the data layer about the oldest potential postgres version it will be run on. @@ -54,7 +57,6 @@ defmodule AshPostgres.Repo do For things like `Fly.Repo`, where you might need to have more fine grained control over the repo module, you can use the `define_ecto_repo?: false` option to `use AshPostgres.Repo`. """ - @callback min_pg_version() :: integer() @callback on_transaction_begin(reason :: Ash.DataLayer.transaction_reason()) :: term @@ -66,6 +68,7 @@ defmodule AshPostgres.Repo do @callback migrations_path() :: String.t() | nil @doc "The default prefix(postgres schema) to use when building queries" @callback default_prefix() :: String.t() + @doc "Allows overriding a given migration type for *all* fields, for example if you wanted to always use :timestamptz for :utc_datetime fields" @callback override_migration_type(atom) :: atom @@ -88,7 +91,6 @@ defmodule AshPostgres.Repo do def migrations_path, do: nil def default_prefix, do: "public" def override_migration_type(type), do: type - def min_pg_version, do: 10 def transaction!(fun) do case fun.() do @@ -224,8 +226,7 @@ defmodule AshPostgres.Repo do all_tenants: 0, tenant_migrations_path: 0, default_prefix: 0, - override_migration_type: 1, - min_pg_version: 0 + override_migration_type: 1 end end end diff --git a/lib/transformers/ensure_table_or_polymorphic.ex b/lib/verifiers/ensure_table_or_polymorphic.ex similarity index 51% rename from lib/transformers/ensure_table_or_polymorphic.ex rename to lib/verifiers/ensure_table_or_polymorphic.ex index 064d026..1f60b8e 100644 --- a/lib/transformers/ensure_table_or_polymorphic.ex +++ b/lib/verifiers/ensure_table_or_polymorphic.ex @@ -1,14 +1,14 @@ -defmodule AshPostgres.Transformers.EnsureTableOrPolymorphic do +defmodule AshPostgres.Verifiers.EnsureTableOrPolymorphic do @moduledoc false - use Spark.Dsl.Transformer - alias Spark.Dsl.Transformer + use Spark.Dsl.Verifier + alias Spark.Dsl.Verifier - def transform(dsl) do - if Transformer.get_option(dsl, [:postgres], :polymorphic?) || - Transformer.get_option(dsl, [:postgres], :table) do - {:ok, dsl} + def verify(dsl) do + if Verifier.get_option(dsl, [:postgres], :polymorphic?) || + Verifier.get_option(dsl, [:postgres], :table) do + :ok else - resource = Transformer.get_persisted(dsl, :module) + resource = Verifier.get_persisted(dsl, :module) raise Spark.Error.DslError, module: resource, diff --git a/lib/transformers/prevent_attribute_multitenancy_and_non_full_match_type.ex b/lib/verifiers/prevent_attribute_multitenancy_and_non_full_match_type.ex similarity index 81% rename from lib/transformers/prevent_attribute_multitenancy_and_non_full_match_type.ex rename to lib/verifiers/prevent_attribute_multitenancy_and_non_full_match_type.ex index b3b02e8..0d9e71c 100644 --- a/lib/transformers/prevent_attribute_multitenancy_and_non_full_match_type.ex +++ b/lib/verifiers/prevent_attribute_multitenancy_and_non_full_match_type.ex @@ -1,10 +1,10 @@ -defmodule AshPostgres.Transformers.PreventAttributeMultitenancyAndNonFullMatchType do +defmodule AshPostgres.Verifiers.PreventAttributeMultitenancyAndNonFullMatchType do @moduledoc false - use Spark.Dsl.Transformer - alias Spark.Dsl.Transformer + use Spark.Dsl.Verifier + alias Spark.Dsl.Verifier - def transform(dsl) do - if Transformer.get_option(dsl, [:multitenancy], :strategy) == :attribute do + def verify(dsl) do + if Verifier.get_option(dsl, [:multitenancy], :strategy) == :attribute do dsl |> AshPostgres.DataLayer.Info.references() |> Enum.filter(&(&1.match_type && &1.match_type != :full)) @@ -14,7 +14,7 @@ defmodule AshPostgres.Transformers.PreventAttributeMultitenancyAndNonFullMatchTy if uses_attribute_strategy?(relationship) and not targets_primary_key?(relationship) and not targets_multitenancy_attribute?(relationship) do - resource = Transformer.get_persisted(dsl, :module) + resource = Verifier.get_persisted(dsl, :module) raise Spark.Error.DslError, module: resource, @@ -28,9 +28,9 @@ defmodule AshPostgres.Transformers.PreventAttributeMultitenancyAndNonFullMatchTy :ok end end) - else - {:ok, dsl} end + + :ok end defp uses_attribute_strategy?(relationship) do diff --git a/lib/transformers/prevent_multidimensional_array_aggregates.ex b/lib/verifiers/prevent_multidimensional_array_aggregates.ex similarity index 80% rename from lib/transformers/prevent_multidimensional_array_aggregates.ex rename to lib/verifiers/prevent_multidimensional_array_aggregates.ex index 62bfa73..6b267ff 100644 --- a/lib/transformers/prevent_multidimensional_array_aggregates.ex +++ b/lib/verifiers/prevent_multidimensional_array_aggregates.ex @@ -1,12 +1,10 @@ -defmodule AshPostgres.Transformers.PreventMultidimensionalArrayAggregates do +defmodule AshPostgres.Verifiers.PreventMultidimensionalArrayAggregates do @moduledoc false - use Spark.Dsl.Transformer - alias Spark.Dsl.Transformer + use Spark.Dsl.Verifier + alias Spark.Dsl.Verifier - def after_compile?, do: true - - def transform(dsl) do - resource = Transformer.get_persisted(dsl, :module) + def verify(dsl) do + resource = Verifier.get_persisted(dsl, :module) dsl |> Ash.Resource.Info.aggregates() @@ -35,6 +33,6 @@ defmodule AshPostgres.Transformers.PreventMultidimensionalArrayAggregates do end end) - {:ok, dsl} + :ok end end diff --git a/lib/transformers/validate_references.ex b/lib/verifiers/validate_references.ex similarity index 65% rename from lib/transformers/validate_references.ex rename to lib/verifiers/validate_references.ex index 0a46e6d..0bb6955 100644 --- a/lib/transformers/validate_references.ex +++ b/lib/verifiers/validate_references.ex @@ -1,23 +1,21 @@ -defmodule AshPostgres.Transformers.ValidateReferences do +defmodule AshPostgres.Verifiers.ValidateReferences do @moduledoc false - use Spark.Dsl.Transformer - alias Spark.Dsl.Transformer + use Spark.Dsl.Verifier + alias Spark.Dsl.Verifier - def after_compile?, do: true - - def transform(dsl) do + def verify(dsl) do dsl |> AshPostgres.DataLayer.Info.references() |> Enum.each(fn reference -> unless Ash.Resource.Info.relationship(dsl, reference.relationship) do raise Spark.Error.DslError, path: [:postgres, :references, reference.relationship], - module: Transformer.get_persisted(dsl, :module), + module: Verifier.get_persisted(dsl, :module), message: "Found reference configuration for relationship `#{reference.relationship}`, but no such relationship exists" end end) - {:ok, dsl} + :ok end end diff --git a/lib/verifiers/verify_postgres_version.ex b/lib/verifiers/verify_postgres_version.ex new file mode 100644 index 0000000..0c7bad9 --- /dev/null +++ b/lib/verifiers/verify_postgres_version.ex @@ -0,0 +1,37 @@ +defmodule AshPostgres.Verifiers.VerifyPostgresVersion do + @moduledoc false + use Spark.Dsl.Verifier + + def verify(dsl) do + read_repo = AshPostgres.DataLayer.Info.repo(dsl, :read) + mutate_repo = AshPostgres.DataLayer.Info.repo(dsl, :mutate) + + read_version = + read_repo.pg_version() |> parse!(read_repo) + + mutation_version = mutate_repo.pg_version() |> parse!(mutate_repo) + + if Version.match?(read_version, ">= 14.0.0") && Version.match?(mutation_version, ">= 14.0.0") do + :ok + else + {:error, "AshPostgres now only supports versions >= 14.0."} + end + end + + defp parse!(%Version{} = version, _repo) do + version + end + + defp parse!(version, repo) do + Version.parse!(version) + rescue + e -> + reraise ArgumentError, + """ + Failed to parse version in `#{inspect(repo)}.pg_version()`: #{inspect(version)} + + Error: #{Exception.message(e)} + """, + __STACKTRACE__ + end +end diff --git a/mix.exs b/mix.exs index 19c0d25..7df3a32 100644 --- a/mix.exs +++ b/mix.exs @@ -45,7 +45,7 @@ defmodule AshPostgres.MixProject do if Mix.env() == :test do def application() do [ - applications: [:ecto, :ecto_sql, :jason, :ash, :postgrex, :tools, :benchee], + applications: [:ecto, :ecto_sql, :jason, :ash, :postgrex, :tools, :benchee, :xmerl], mod: {AshPostgres.TestApp, []} ] end @@ -140,7 +140,6 @@ defmodule AshPostgres.MixProject do EctoMigrationDefault ], Expressions: [ - AshPostgres.Functions.Fragment, AshPostgres.Functions.TrigramSimilarity, AshPostgres.Functions.ILike, AshPostgres.Functions.Like, @@ -157,7 +156,10 @@ defmodule AshPostgres.MixProject do {:ecto, "~> 3.9"}, {:jason, "~> 1.0"}, {:postgrex, ">= 0.0.0"}, - {:ash, ash_version("~> 2.19 and >= 2.20.3")}, + {:spark, path: "../spark", override: true}, + # dev/test dependencies + {:simple_sat, "~> 0.1"}, + {:ash, ash_version(github: "ash-project/ash", branch: "3.0")}, {:benchee, "~> 1.1", only: [:dev, :test]}, {:git_ops, "~> 2.5", only: [:dev, :test]}, {:ex_doc, github: "elixir-lang/ex_doc", only: [:dev, :test], runtime: false}, diff --git a/mix.lock b/mix.lock index 3f15e7d..da3f1f0 100644 --- a/mix.lock +++ b/mix.lock @@ -1,5 +1,5 @@ %{ - "ash": {:hex, :ash, "2.20.3", "2ded1295fd20e2a45b01c678fe93c51397384ec5e5e4babc80f1ae9ce896ca82", [:mix], [{:comparable, "~> 1.0", [hex: :comparable, repo: "hexpm", optional: false]}, {:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:earmark, "~> 1.4", [hex: :earmark, repo: "hexpm", optional: false]}, {:ecto, "~> 3.7", [hex: :ecto, repo: "hexpm", optional: false]}, {:ets, "~> 0.8", [hex: :ets, repo: "hexpm", optional: false]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: false]}, {:picosat_elixir, "~> 0.2", [hex: :picosat_elixir, repo: "hexpm", optional: false]}, {:plug, ">= 0.0.0", [hex: :plug, repo: "hexpm", optional: true]}, {:reactor, "~> 0.6", [hex: :reactor, repo: "hexpm", optional: false]}, {:spark, ">= 1.1.55 and < 2.0.0-0", [hex: :spark, repo: "hexpm", optional: false]}, {:stream_data, "~> 0.6", [hex: :stream_data, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.1", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "b53374c6c70da21bb8d53fefb88e1b0dc7a6fd8cf48ecaff4d6e57d2e69afbca"}, + "ash": {:git, "https://github.com/ash-project/ash.git", "37587cbc580c30248044eea01d461f578df6cbc4", [branch: "3.0"]}, "benchee": {:hex, :benchee, "1.3.0", "f64e3b64ad3563fa9838146ddefb2d2f94cf5b473bdfd63f5ca4d0657bf96694", [:mix], [{:deep_merge, "~> 1.0", [hex: :deep_merge, repo: "hexpm", optional: false]}, {:statistex, "~> 1.0", [hex: :statistex, repo: "hexpm", optional: false]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "34f4294068c11b2bd2ebf2c59aac9c7da26ffa0068afdf3419f1b176e16c5f81"}, "bunt": {:hex, :bunt, "1.0.0", "081c2c665f086849e6d57900292b3a161727ab40431219529f13c4ddcf3e7a44", [:mix], [], "hexpm", "dc5f86aa08a5f6fa6b8096f0735c4e76d54ae5c9fa2c143e5a1fc7c1cd9bb6b5"}, "comparable": {:hex, :comparable, "1.0.0", "bb669e91cedd14ae9937053e5bcbc3c52bb2f22422611f43b6e38367d94a495f", [:mix], [{:typable, "~> 0.1", [hex: :typable, repo: "hexpm", optional: false]}], "hexpm", "277c11eeb1cd726e7cd41c6c199e7e52fa16ee6830b45ad4cdc62e51f62eb60c"}, @@ -8,11 +8,9 @@ "decimal": {:hex, :decimal, "2.1.1", "5611dca5d4b2c3dd497dec8f68751f1f1a54755e8ed2a966c2633cf885973ad6", [:mix], [], "hexpm", "53cfe5f497ed0e7771ae1a475575603d77425099ba5faef9394932b35020ffcc"}, "deep_merge": {:hex, :deep_merge, "1.0.0", "b4aa1a0d1acac393bdf38b2291af38cb1d4a52806cf7a4906f718e1feb5ee961", [:mix], [], "hexpm", "ce708e5f094b9cd4e8f2be4f00d2f4250c4095be93f8cd6d018c753894885430"}, "dialyxir": {:hex, :dialyxir, "1.4.3", "edd0124f358f0b9e95bfe53a9fcf806d615d8f838e2202a9f430d59566b6b53b", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "bf2cfb75cd5c5006bec30141b131663299c661a864ec7fbbc72dfa557487a986"}, - "earmark": {:hex, :earmark, "1.4.46", "8c7287bd3137e99d26ae4643e5b7ef2129a260e3dcf41f251750cb4563c8fb81", [:mix], [], "hexpm", "798d86db3d79964e759ddc0c077d5eb254968ed426399fbf5a62de2b5ff8910a"}, "earmark_parser": {:hex, :earmark_parser, "1.4.39", "424642f8335b05bb9eb611aa1564c148a8ee35c9c8a8bba6e129d51a3e3c6769", [:mix], [], "hexpm", "06553a88d1f1846da9ef066b87b57c6f605552cfbe40d20bd8d59cc6bde41944"}, "ecto": {:hex, :ecto, "3.11.2", "e1d26be989db350a633667c5cda9c3d115ae779b66da567c68c80cfb26a8c9ee", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "3c38bca2c6f8d8023f2145326cc8a80100c3ffe4dcbd9842ff867f7fc6156c65"}, "ecto_sql": {:hex, :ecto_sql, "3.11.1", "e9abf28ae27ef3916b43545f9578b4750956ccea444853606472089e7d169470", [:mix], [{:db_connection, "~> 2.4.1 or ~> 2.5", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.11.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.6.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.16.0 or ~> 0.17.0 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "ce14063ab3514424276e7e360108ad6c2308f6d88164a076aac8a387e1fea634"}, - "elixir_make": {:hex, :elixir_make, "0.8.2", "cd4a5a75891362e9207adaac7e66223fd256ec2518ae013af7f10c9c85b50b5c", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:certifi, "~> 2.0", [hex: :certifi, repo: "hexpm", optional: true]}], "hexpm", "9d9607d640c372a7291e5a56ce655aa2351897929be20bd211648fdb79e725dc"}, "erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"}, "ets": {:hex, :ets, "0.9.0", "79c6a6c205436780486f72d84230c6cba2f8a9920456750ddd1e47389107d5fd", [:mix], [], "hexpm", "2861fdfb04bcaeff370f1a5904eec864f0a56dcfebe5921ea9aadf2a481c822b"}, "ex_check": {:hex, :ex_check, "0.15.0", "074b94c02de11c37bba1ca82ae5cc4926e6ccee862e57a485b6ba60fca2d8dc1", [:mix], [], "hexpm", "33848031a0c7e4209c3b4369ce154019788b5219956220c35ca5474299fb6a0e"}, @@ -26,14 +24,14 @@ "makeup": {:hex, :makeup, "1.1.0", "6b67c8bc2882a6b6a445859952a602afc1a41c2e08379ca057c0f525366fc3ca", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "0a45ed501f4a8897f580eabf99a2e5234ea3e75a4373c8a52824f6e873be57a6"}, "makeup_elixir": {:hex, :makeup_elixir, "0.16.1", "cc9e3ca312f1cfeccc572b37a09980287e243648108384b97ff2b76e505c3555", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "e127a341ad1b209bd80f7bd1620a15693a9908ed780c3b763bccf7d200c767c6"}, "makeup_erlang": {:hex, :makeup_erlang, "0.1.2", "ad87296a092a46e03b7e9b0be7631ddcf64c790fa68a9ef5323b6cbb36affc72", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "f3f5a1ca93ce6e092d92b6d9c049bcda58a3b617a8d888f8e7231c85630e8108"}, - "nimble_options": {:hex, :nimble_options, "1.1.0", "3b31a57ede9cb1502071fade751ab0c7b8dbe75a9a4c2b5bbb0943a690b63172", [:mix], [], "hexpm", "8bbbb3941af3ca9acc7835f5655ea062111c9c27bcac53e004460dfd19008a99"}, "nimble_parsec": {:hex, :nimble_parsec, "1.4.0", "51f9b613ea62cfa97b25ccc2c1b4216e81df970acd8e16e8d1bdc58fef21370d", [:mix], [], "hexpm", "9c565862810fb383e9838c1dd2d7d2c437b3d13b267414ba6af33e50d2d1cf28"}, - "picosat_elixir": {:hex, :picosat_elixir, "0.2.3", "bf326d0f179fbb3b706bb2c15fbc367dacfa2517157d090fdfc32edae004c597", [:make, :mix], [{:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "f76c9db2dec9d2561ffaa9be35f65403d53e984e8cd99c832383b7ab78c16c66"}, "postgrex": {:hex, :postgrex, "0.17.4", "5777781f80f53b7c431a001c8dad83ee167bcebcf3a793e3906efff680ab62b3", [:mix], [{:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "6458f7d5b70652bc81c3ea759f91736c16a31be000f306d3c64bcdfe9a18b3cc"}, - "reactor": {:hex, :reactor, "0.7.0", "fb76d23d95829b28ac9b9d654620c43c890c6a32ea26ac13086c48540b34e8c5", [:mix], [{:libgraph, "~> 0.16", [hex: :libgraph, repo: "hexpm", optional: false]}, {:spark, "~> 1.0", [hex: :spark, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.2", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "4310da820d753aafd7dc4ee8cc687b84565dd6d9536e38806ee211da792178fd"}, + "reactor": {:hex, :reactor, "0.8.1", "1aec71d16083901277727c8162f6dd0f07e80f5ca98911b6ef4f2c95e6e62758", [:mix], [{:libgraph, "~> 0.16", [hex: :libgraph, repo: "hexpm", optional: false]}, {:spark, "~> 2.0", [hex: :spark, repo: "hexpm", optional: false]}, {:splode, "~> 0.2", [hex: :splode, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.2", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "ae3936d97a3e4a316744f70c77b85345b08b70da334024c26e6b5eb8ede1246b"}, + "simple_sat": {:hex, :simple_sat, "0.1.1", "68a5ebe6f6d5956bd806e4881c495692c14580a2f1a4420488985abd0fba2119", [:mix], [], "hexpm", "63571218f92ff029838df7645eb8f0c38df8ed60d2d14578412a8d142a94471e"}, "sobelow": {:hex, :sobelow, "0.13.0", "218afe9075904793f5c64b8837cc356e493d88fddde126a463839351870b8d1e", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "cd6e9026b85fc35d7529da14f95e85a078d9dd1907a9097b3ba6ac7ebbe34a0d"}, "sourceror": {:hex, :sourceror, "1.0.2", "c5e86fdc14881f797749d1fe5df017ca66727a8146e7ee3e736605a3df78f3e6", [:mix], [], "hexpm", "832335e87d0913658f129d58b2a7dc0490ddd4487b02de6d85bca0169ec2bd79"}, - "spark": {:hex, :spark, "1.1.55", "d20c3f899b23d841add29edc912ffab4463d3bb801bc73448738631389291d2e", [:mix], [{:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.5 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:sourceror, "~> 1.0", [hex: :sourceror, repo: "hexpm", optional: false]}], "hexpm", "bbc15a4223d8e610c81ceca825d5d0bae3738d1c4ac4dbb1061749966776c3f1"}, + "spark": {:hex, :spark, "2.1.6", "15c6725836607322e867b40fb6bdeb13f4606d48a001d2a74518559678e26895", [:mix], [{:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:sourceror, "~> 1.0", [hex: :sourceror, repo: "hexpm", optional: false]}], "hexpm", "6838d226e83acedb3a6169169bfc2d7afde19ef6a37fb14f0572d39db9d56c7b"}, + "splode": {:hex, :splode, "0.2.0", "a1f3b5a8e7c957be495bf0f22dd9e0567a87ec63559963a0ce0c3f0e8dfacedc", [:mix], [], "hexpm", "7cfecc5913ff7feeb04f143e2494cfa7bc6d5bb5bec70f7ffac94c18ea97f303"}, "statistex": {:hex, :statistex, "1.0.0", "f3dc93f3c0c6c92e5f291704cf62b99b553253d7969e9a5fa713e5481cd858a5", [:mix], [], "hexpm", "ff9d8bee7035028ab4742ff52fc80a2aa35cece833cf5319009b52f1b5a86c27"}, "stream_data": {:hex, :stream_data, "0.6.0", "e87a9a79d7ec23d10ff83eb025141ef4915eeb09d4491f79e52f2562b73e5f47", [:mix], [], "hexpm", "b92b5031b650ca480ced047578f1d57ea6dd563f5b57464ad274718c9c29501c"}, "telemetry": {:hex, :telemetry, "1.2.1", "68fdfe8d8f05a8428483a97d7aab2f268aaff24b49e0f599faa091f1d4e7f61c", [:rebar3], [], "hexpm", "dad9ce9d8effc621708f99eac538ef1cbe05d6a874dd741de2e689c47feafed5"}, diff --git a/test/aggregate_test.exs b/test/aggregate_test.exs index 162c3e6..1d95515 100644 --- a/test/aggregate_test.exs +++ b/test/aggregate_test.exs @@ -1,37 +1,37 @@ defmodule AshPostgres.AggregateTest do use AshPostgres.RepoCase, async: false - alias AshPostgres.Test.{Api, Author, Comment, Organization, Post, Rating, User} + alias AshPostgres.Test.{Author, Comment, Organization, Post, Rating, User} require Ash.Query - require Ash.Expr + import Ash.Expr test "relates to actor via has_many and with an aggregate" do org = Organization - |> Ash.Changeset.new(%{name: "The Org"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{name: "The Org"}) + |> Ash.create!() post = Post |> Ash.Changeset.for_create(:create, %{title: "title"}) |> Ash.Changeset.manage_relationship(:organization, org, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() user = User |> Ash.Changeset.for_create(:create, %{}) |> Ash.Changeset.manage_relationship(:organization, org, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "match"}) + |> Ash.Changeset.for_create(:create, %{title: "match"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() read_post = Post |> Ash.Query.filter(id == ^post.id) - |> Api.read_one!(actor: user) + |> Ash.read_one!(actor: user) assert read_post.id == post.id @@ -39,13 +39,13 @@ defmodule AshPostgres.AggregateTest do Post |> Ash.Query.filter(id == ^post.id) |> Ash.Query.load(:count_of_comments) - |> Api.read_one!(actor: user) + |> Ash.read_one!(actor: user) assert read_post.count_of_comments == 1 read_post = post - |> Api.load!(:count_of_comments, actor: user) + |> Ash.load!(:count_of_comments, actor: user) assert read_post.count_of_comments == 1 end @@ -53,70 +53,70 @@ defmodule AshPostgres.AggregateTest do describe "join filters" do test "with no data, it does not effect the behavior" do Author - |> Ash.Changeset.new(%{}) - |> Api.create!() + |> Ash.Changeset.for_create(:create) + |> Ash.create!() assert [%{count_of_posts_with_better_comment: 0}] = Author |> Ash.Query.load(:count_of_posts_with_better_comment) - |> Api.read!() + |> Ash.read!() end test "it properly applies join criteria" do author = Author - |> Ash.Changeset.new(%{}) - |> Api.create!() + |> Ash.Changeset.for_create(:create) + |> Ash.create!() matching_post = Post - |> Ash.Changeset.new(%{title: "match", score: 10}) + |> Ash.Changeset.for_create(:create, %{title: "match", score: 10}) |> Ash.Changeset.manage_relationship(:author, author, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() non_matching_post = Post - |> Ash.Changeset.new(%{title: "non_match", score: 100}) + |> Ash.Changeset.for_create(:create, %{title: "non_match", score: 100}) |> Ash.Changeset.manage_relationship(:author, author, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "match", likes: 100}) + |> Ash.Changeset.for_create(:create, %{title: "match", likes: 100}) |> Ash.Changeset.manage_relationship(:post, matching_post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "non_match", likes: 0}) + |> Ash.Changeset.for_create(:create, %{title: "non_match", likes: 0}) |> Ash.Changeset.manage_relationship(:post, non_matching_post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() assert [%{count_of_posts_with_better_comment: 1}] = Author |> Ash.Query.load(:count_of_posts_with_better_comment) - |> Api.read!() + |> Ash.read!() end test "it properly applies join criteria to exists queries in filters" do author = Author - |> Ash.Changeset.new(%{}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{}) + |> Ash.create!() non_matching_post = Post - |> Ash.Changeset.new(%{title: "non_match", score: 100}) + |> Ash.Changeset.for_create(:create, %{title: "non_match", score: 100}) |> Ash.Changeset.manage_relationship(:author, author, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "non_match", likes: 0}) + |> Ash.Changeset.for_create(:create, %{title: "non_match", likes: 0}) |> Ash.Changeset.manage_relationship(:post, non_matching_post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() assert [] = Author |> Ash.Query.filter(has_post_with_better_comment) - |> Api.read!() + |> Ash.read!() end end @@ -124,33 +124,31 @@ defmodule AshPostgres.AggregateTest do test "with no related data it returns 0" do post = Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() assert %{count_of_comments: 0} = Post |> Ash.Query.filter(id == ^post.id) |> Ash.Query.load(:count_of_comments) - |> Api.read_one!() + |> Ash.read_one!() end test "with data and a custom aggregate, it returns the count" do post = Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "match"}) + |> Ash.Changeset.for_create(:create, %{title: "match"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() Comment |> Ash.Changeset.new() |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() - - import Ash.Query + |> Ash.create!() assert %{aggregates: %{custom_count_of_comments: 1}} = Post @@ -161,12 +159,12 @@ defmodule AshPostgres.AggregateTest do :comments, query: [filter: expr(not is_nil(title))] ) - |> Api.read_one!() + |> Ash.read_one!() Comment - |> Ash.Changeset.new(%{title: "match"}) + |> Ash.Changeset.for_create(:create, %{title: "match"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() assert %{aggregates: %{custom_count_of_comments: 2}} = Post @@ -177,26 +175,24 @@ defmodule AshPostgres.AggregateTest do :comments, query: [filter: expr(not is_nil(title))] ) - |> Api.read_one!() + |> Ash.read_one!() end test "with data and a custom string keyed aggregate, it returns the count" do post = Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "match"}) + |> Ash.Changeset.for_create(:create, %{title: "match"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() Comment |> Ash.Changeset.new() |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() - - import Ash.Query + |> Ash.create!() assert %{aggregates: %{"custom_count_of_comments" => 1}} = Post @@ -207,36 +203,36 @@ defmodule AshPostgres.AggregateTest do :comments, query: [filter: expr(not is_nil(title))] ) - |> Api.read_one!() + |> Ash.read_one!() end test "with data for a many_to_many, it returns the count" do post = Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() post2 = Post - |> Ash.Changeset.new(%{title: "title2"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title2"}) + |> Ash.create!() post3 = Post - |> Ash.Changeset.new(%{title: "title3"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title3"}) + |> Ash.create!() post |> Ash.Changeset.new() |> Ash.Changeset.manage_relationship(:linked_posts, [post2, post3], type: :append_and_remove ) - |> Api.update!() + |> Ash.update!() post2 |> Ash.Changeset.new() |> Ash.Changeset.manage_relationship(:linked_posts, [post3], type: :append_and_remove) - |> Api.update!() + |> Ash.update!() assert [ %{count_of_linked_posts: 2, title: "title"}, @@ -246,36 +242,36 @@ defmodule AshPostgres.AggregateTest do |> Ash.Query.load(:count_of_linked_posts) |> Ash.Query.filter(count_of_linked_posts >= 1) |> Ash.Query.sort(count_of_linked_posts: :desc) - |> Api.read!() + |> Ash.read!() end test "with data and a filter, it returns the count" do post = Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "match"}) + |> Ash.Changeset.for_create(:create, %{title: "match"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() assert %{count_of_comments_called_match: 1} = Post |> Ash.Query.filter(id == ^post.id) |> Ash.Query.load(:count_of_comments_called_match) - |> Api.read_one!() + |> Ash.read_one!() Comment - |> Ash.Changeset.new(%{title: "not_match"}) + |> Ash.Changeset.for_create(:create, %{title: "not_match"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() assert %{count_of_comments_called_match: 1} = Post |> Ash.Query.filter(id == ^post.id) |> Ash.Query.load(:count_of_comments_called_match) - |> Api.read_one!() + |> Ash.read_one!() end end @@ -283,81 +279,81 @@ defmodule AshPostgres.AggregateTest do test "with data and a filter, it returns the correct result" do post = Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "non-match"}) + |> Ash.Changeset.for_create(:create, %{title: "non-match"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() assert %{has_comment_called_match: false} = Post |> Ash.Query.filter(id == ^post.id) |> Ash.Query.load(:has_comment_called_match) - |> Api.read_one!() + |> Ash.read_one!() Comment - |> Ash.Changeset.new(%{title: "match"}) + |> Ash.Changeset.for_create(:create, %{title: "match"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() assert %{has_comment_called_match: true} = Post |> Ash.Query.filter(id == ^post.id) |> Ash.Query.load(:has_comment_called_match) - |> Api.read_one!() + |> Ash.read_one!() end test "exists aggregates can be referenced in filters" do post = Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() refute Post |> Ash.Query.filter(has_comment_called_match) - |> Api.read_one!() + |> Ash.read_one!() Comment - |> Ash.Changeset.new(%{title: "match"}) + |> Ash.Changeset.for_create(:create, %{title: "match"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() assert %{has_comment_called_match: true} = Post |> Ash.Query.filter(has_comment_called_match) |> Ash.Query.load(:has_comment_called_match) - |> Api.read_one!() + |> Ash.read_one!() end test "exists aggregates can be used at the query level" do post = Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() Post - |> Ash.Changeset.new(%{title: "title2"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title2"}) + |> Ash.create!() refute Post |> Ash.Query.filter(has_comment_called_match) - |> Api.exists?() + |> Ash.exists?() Comment - |> Ash.Changeset.new(%{title: "match"}) + |> Ash.Changeset.for_create(:create, %{title: "match"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "match"}) + |> Ash.Changeset.for_create(:create, %{title: "match"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() - assert Post |> Api.exists?() + assert Post |> Ash.exists?() - refute Post |> Api.exists?(query: [filter: [title: "non-match"]]) + refute Post |> Ash.exists?(query: [filter: [title: "non-match"]]) end end @@ -365,88 +361,88 @@ defmodule AshPostgres.AggregateTest do test "with no related data it returns an empty list" do post = Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() assert %{comment_titles: []} = Post |> Ash.Query.filter(id == ^post.id) |> Ash.Query.load(:comment_titles) - |> Api.read_one!() + |> Ash.read_one!() end test "with related data, it returns the value" do post = Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "bbb"}) + |> Ash.Changeset.for_create(:create, %{title: "bbb"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "ccc"}) + |> Ash.Changeset.for_create(:create, %{title: "ccc"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() assert %{comment_titles: ["bbb", "ccc"]} = Post |> Ash.Query.filter(id == ^post.id) |> Ash.Query.load(:comment_titles) - |> Api.read_one!() + |> Ash.read_one!() Comment - |> Ash.Changeset.new(%{title: "aaa"}) + |> Ash.Changeset.for_create(:create, %{title: "aaa"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() assert %{comment_titles: ["aaa", "bbb", "ccc"]} = Post |> Ash.Query.filter(id == ^post.id) |> Ash.Query.load(:comment_titles) - |> Api.read_one!() + |> Ash.read_one!() end test "with related data, it returns the uniq" do post = Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "aaa"}) + |> Ash.Changeset.for_create(:create, %{title: "aaa"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "aaa"}) + |> Ash.Changeset.for_create(:create, %{title: "aaa"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() assert %{uniq_comment_titles: ["aaa"]} = Post |> Ash.Query.filter(id == ^post.id) |> Ash.Query.load(:uniq_comment_titles) - |> Api.read_one!() + |> Ash.read_one!() Comment - |> Ash.Changeset.new(%{title: "bbb"}) + |> Ash.Changeset.for_create(:create, %{title: "bbb"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() assert %{uniq_comment_titles: ["aaa", "bbb"]} = Post |> Ash.Query.filter(id == ^post.id) |> Ash.Query.load(:uniq_comment_titles) - |> Api.read_one!() + |> Ash.read_one!() assert %{count_comment_titles: 3, count_uniq_comment_titles: 2} = Post |> Ash.Query.filter(id == ^post.id) |> Ash.Query.load([:count_comment_titles, :count_uniq_comment_titles]) - |> Api.read_one!() + |> Ash.read_one!() end end @@ -454,118 +450,118 @@ defmodule AshPostgres.AggregateTest do test "with no related data it returns nil" do post = Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() assert %{first_comment: nil} = Post |> Ash.Query.filter(id == ^post.id) |> Ash.Query.load(:first_comment) - |> Api.read_one!() + |> Ash.read_one!() end test "with related data, it returns the value" do post = Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "match"}) + |> Ash.Changeset.for_create(:create, %{title: "match"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() assert %{first_comment: "match"} = Post |> Ash.Query.filter(id == ^post.id) |> Ash.Query.load(:first_comment) - |> Api.read_one!() + |> Ash.read_one!() Comment - |> Ash.Changeset.new(%{title: "early match"}) + |> Ash.Changeset.for_create(:create, %{title: "early match"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() assert %{first_comment: "early match"} = Post |> Ash.Query.filter(id == ^post.id) |> Ash.Query.load(:first_comment) - |> Api.read_one!() + |> Ash.read_one!() end test "it can be sorted on" do post = Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() post_id = post.id Comment - |> Ash.Changeset.new(%{title: "match"}) + |> Ash.Changeset.for_create(:create, %{title: "match"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() post_2 = Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "zed"}) + |> Ash.Changeset.for_create(:create, %{title: "zed"}) |> Ash.Changeset.manage_relationship(:post, post_2, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() assert %{id: ^post_id} = Post |> Ash.Query.sort(:first_comment) |> Ash.Query.limit(1) - |> Api.read_one!() + |> Ash.read_one!() end test "first aggregates can be sorted on" do author = Author - |> Ash.Changeset.new(%{first_name: "first name"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{first_name: "first name"}) + |> Ash.create!() post = Post - |> Ash.Changeset.new(%{title: "title"}) + |> Ash.Changeset.for_create(:create, %{title: "title"}) |> Ash.Changeset.manage_relationship(:author, author, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() assert %{author_first_name: "first name"} = Post |> Ash.Query.filter(id == ^post.id) |> Ash.Query.load(:author_first_name) |> Ash.Query.sort(author_first_name: :asc) - |> Api.read_one!() + |> Ash.read_one!() end test "aggregate maintains datetime precision" do author = Author - |> Ash.Changeset.new(%{first_name: "first name"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{first_name: "first name"}) + |> Ash.create!() post = Post - |> Ash.Changeset.new(%{title: "title"}) + |> Ash.Changeset.for_create(:create, %{title: "title"}) |> Ash.Changeset.manage_relationship(:author, author, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() latest_comment = Comment - |> Ash.Changeset.new(%{title: "title"}) + |> Ash.Changeset.for_create(:create, %{title: "title"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() fetched_post = Post |> Ash.Query.filter(id == ^post.id) |> Ash.Query.load(:latest_comment_created_at) - |> Api.read_one!() + |> Ash.read_one!() assert latest_comment.created_at == fetched_post.latest_comment_created_at end @@ -573,48 +569,48 @@ defmodule AshPostgres.AggregateTest do test "it can be sorted on and produces the appropriate order" do post1 = Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "b"}) + |> Ash.Changeset.for_create(:create, %{title: "b"}) |> Ash.Changeset.manage_relationship(:post, post1, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "c"}) + |> Ash.Changeset.for_create(:create, %{title: "c"}) |> Ash.Changeset.manage_relationship(:post, post1, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() post2 = Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "a"}) + |> Ash.Changeset.for_create(:create, %{title: "a"}) |> Ash.Changeset.manage_relationship(:post, post2, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "b"}) + |> Ash.Changeset.for_create(:create, %{title: "b"}) |> Ash.Changeset.manage_relationship(:post, post2, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() post3 = Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "c"}) + |> Ash.Changeset.for_create(:create, %{title: "c"}) |> Ash.Changeset.manage_relationship(:post, post3, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "d"}) + |> Ash.Changeset.for_create(:create, %{title: "d"}) |> Ash.Changeset.manage_relationship(:post, post3, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() assert [%{last_comment: "d"}, %{last_comment: "c"}] = Post @@ -622,15 +618,15 @@ defmodule AshPostgres.AggregateTest do |> Ash.Query.sort(last_comment: :desc) |> Ash.Query.filter(not is_nil(comments.title)) |> Ash.Query.limit(2) - |> Api.read!() + |> Ash.read!() end end test "sum aggregates show the same value with filters on the sum vs filters on relationships" do post = Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() for i <- 1..5 do ratings = @@ -639,22 +635,21 @@ defmodule AshPostgres.AggregateTest do end Comment - |> Ash.Changeset.new(%{title: "title#{i}"}) + |> Ash.Changeset.for_create(:create, %{title: "title#{i}"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) |> Ash.Changeset.manage_relationship(:ratings, ratings, type: :create) - |> Api.create!() + |> Ash.create!() end values = post - |> Api.load!([ - :sum_of_popular_comment_rating_scores, + |> Ash.load!([ :sum_of_popular_comment_rating_scores_2 ]) - |> Map.take([:sum_of_popular_comment_rating_scores, :sum_of_popular_comment_rating_scores_2]) - |> Map.values() + |> Map.take([:sum_of_popular_comment_rating_scores_2]) - assert [80, 80] = values + assert %{sum_of_popular_comment_rating_scores_2: 80} = + values end test "can't define multidimensional array aggregate types" do @@ -662,6 +657,7 @@ defmodule AshPostgres.AggregateTest do defmodule Foo do @moduledoc false use Ash.Resource, + domain: nil, data_layer: AshPostgres.DataLayer postgres do @@ -678,7 +674,9 @@ defmodule AshPostgres.AggregateTest do end relationships do - belongs_to(:author, AshPostgres.Test.Author) + belongs_to(:author, AshPostgres.Test.Author) do + public?(true) + end end aggregates do @@ -691,277 +689,277 @@ defmodule AshPostgres.AggregateTest do test "related aggregates can be filtered on" do post = Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() post2 = Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "match"}) + |> Ash.Changeset.for_create(:create, %{title: "match"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "non_match"}) + |> Ash.Changeset.for_create(:create, %{title: "non_match"}) |> Ash.Changeset.manage_relationship(:post, post2, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "non_match2"}) + |> Ash.Changeset.for_create(:create, %{title: "non_match2"}) |> Ash.Changeset.manage_relationship(:post, post2, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() assert %{title: "match"} = Comment |> Ash.Query.filter(post.count_of_comments == 1) - |> Api.read_one!() + |> Ash.read_one!() end describe "sum" do test "with no related data it returns nil" do post = Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() assert %{sum_of_comment_likes: nil} = Post |> Ash.Query.filter(id == ^post.id) |> Ash.Query.load(:sum_of_comment_likes) - |> Api.read_one!() + |> Ash.read_one!() end test "with no related data and a default it returns the default" do post = Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() assert %{sum_of_comment_likes_with_default: 0} = Post |> Ash.Query.filter(id == ^post.id) |> Ash.Query.load(:sum_of_comment_likes_with_default) - |> Api.read_one!() + |> Ash.read_one!() end test "with data, it returns the sum" do post = Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "match", likes: 2}) + |> Ash.Changeset.for_create(:create, %{title: "match", likes: 2}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() assert %{sum_of_comment_likes: 2} = Post |> Ash.Query.filter(id == ^post.id) |> Ash.Query.load(:sum_of_comment_likes) - |> Api.read_one!() + |> Ash.read_one!() Comment - |> Ash.Changeset.new(%{title: "match", likes: 3}) + |> Ash.Changeset.for_create(:create, %{title: "match", likes: 3}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() assert %{sum_of_comment_likes: 5} = Post |> Ash.Query.filter(id == ^post.id) |> Ash.Query.load(:sum_of_comment_likes) - |> Api.read_one!() + |> Ash.read_one!() end test "with data and a filter, it returns the sum" do post = Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "match", likes: 2}) + |> Ash.Changeset.for_create(:create, %{title: "match", likes: 2}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() assert %{sum_of_comment_likes_called_match: 2} = Post |> Ash.Query.filter(id == ^post.id) |> Ash.Query.load(:sum_of_comment_likes_called_match) - |> Api.read_one!() + |> Ash.read_one!() Comment - |> Ash.Changeset.new(%{title: "not_match", likes: 3}) + |> Ash.Changeset.for_create(:create, %{title: "not_match", likes: 3}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() assert %{sum_of_comment_likes_called_match: 2} = Post |> Ash.Query.filter(id == ^post.id) |> Ash.Query.load(:sum_of_comment_likes_called_match) - |> Api.read_one!() + |> Ash.read_one!() end test "filtering on a nested aggregate works" do Post |> Ash.Query.filter(count_of_comment_ratings == 0) - |> Api.read!() + |> Ash.read!() end test "nested aggregates show the proper values" do post = Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() author = AshPostgres.Test.Author - |> Ash.Changeset.new(%{"first_name" => "ted"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{"first_name" => "ted"}) + |> Ash.create!() comment1 = Comment - |> Ash.Changeset.new(%{title: "match", likes: 2}) + |> Ash.Changeset.for_create(:create, %{title: "match", likes: 2}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) |> Ash.Changeset.manage_relationship(:author, author, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() comment2 = Comment - |> Ash.Changeset.new(%{title: "match", likes: 2}) + |> Ash.Changeset.for_create(:create, %{title: "match", likes: 2}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) |> Ash.Changeset.manage_relationship(:author, author, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() Rating - |> Ash.Changeset.new(%{score: 5, resource_id: comment1.id}) + |> Ash.Changeset.for_create(:create, %{score: 5, resource_id: comment1.id}) |> Ash.Changeset.set_context(%{data_layer: %{table: "comment_ratings"}}) - |> Api.create!() + |> Ash.create!() Rating - |> Ash.Changeset.new(%{score: 10, resource_id: comment2.id}) + |> Ash.Changeset.for_create(:create, %{score: 10, resource_id: comment2.id}) |> Ash.Changeset.set_context(%{data_layer: %{table: "comment_ratings"}}) - |> Api.create!() + |> Ash.create!() assert [%{count_of_comment_ratings: 2}] = - Post |> Ash.Query.load(:count_of_comment_ratings) |> Api.read!() + Post |> Ash.Query.load(:count_of_comment_ratings) |> Ash.read!() assert [%{highest_comment_rating: 10}] = - Post |> Ash.Query.load(:highest_comment_rating) |> Api.read!() + Post |> Ash.Query.load(:highest_comment_rating) |> Ash.read!() assert [%{lowest_comment_rating: 5}] = - Post |> Ash.Query.load(:lowest_comment_rating) |> Api.read!() + Post |> Ash.Query.load(:lowest_comment_rating) |> Ash.read!() assert [%{avg_comment_rating: 7.5}] = - Post |> Ash.Query.load(:avg_comment_rating) |> Api.read!() + Post |> Ash.Query.load(:avg_comment_rating) |> Ash.read!() # TODO: want to add an option for `unique` here at some point assert [%{comment_authors: "ted,ted"}] = - Post |> Ash.Query.load(:comment_authors) |> Api.read!() + Post |> Ash.Query.load(:comment_authors) |> Ash.read!() end test "nested filtered aggregates show the proper values" do post = Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() comment1 = Comment - |> Ash.Changeset.new(%{title: "match", likes: 2}) + |> Ash.Changeset.for_create(:create, %{title: "match", likes: 2}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() comment2 = Comment - |> Ash.Changeset.new(%{title: "match", likes: 2}) + |> Ash.Changeset.for_create(:create, %{title: "match", likes: 2}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() Rating - |> Ash.Changeset.new(%{score: 20, resource_id: comment1.id}) + |> Ash.Changeset.for_create(:create, %{score: 20, resource_id: comment1.id}) |> Ash.Changeset.set_context(%{data_layer: %{table: "comment_ratings"}}) - |> Api.create!() + |> Ash.create!() Rating - |> Ash.Changeset.new(%{score: 1, resource_id: comment2.id}) + |> Ash.Changeset.for_create(:create, %{score: 1, resource_id: comment2.id}) |> Ash.Changeset.set_context(%{data_layer: %{table: "comment_ratings"}}) - |> Api.create!() + |> Ash.create!() assert [%{count_of_comment_ratings: 2, count_of_popular_comment_ratings: 1}] = Post |> Ash.Query.load([:count_of_comment_ratings, :count_of_popular_comment_ratings]) - |> Api.read!() + |> Ash.read!() assert [%{count_of_comment_ratings: 2}] = Post |> Ash.Query.load([:count_of_comment_ratings]) - |> Api.read!() + |> Ash.read!() assert [%{count_of_popular_comment_ratings: 1}] = Post |> Ash.Query.load([:count_of_popular_comment_ratings]) - |> Api.read!() + |> Ash.read!() end test "nested filtered and sorted aggregates show the proper values" do post = Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() comment1 = Comment - |> Ash.Changeset.new(%{title: "match", likes: 2}) + |> Ash.Changeset.for_create(:create, %{title: "match", likes: 2}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() comment2 = Comment - |> Ash.Changeset.new(%{title: "match", likes: 2}) + |> Ash.Changeset.for_create(:create, %{title: "match", likes: 2}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() Rating - |> Ash.Changeset.new(%{score: 20, resource_id: comment1.id}) + |> Ash.Changeset.for_create(:create, %{score: 20, resource_id: comment1.id}) |> Ash.Changeset.set_context(%{data_layer: %{table: "comment_ratings"}}) - |> Api.create!() + |> Ash.create!() Rating - |> Ash.Changeset.new(%{score: 1, resource_id: comment2.id}) + |> Ash.Changeset.for_create(:create, %{score: 1, resource_id: comment2.id}) |> Ash.Changeset.set_context(%{data_layer: %{table: "comment_ratings"}}) - |> Api.create!() + |> Ash.create!() assert [%{count_of_comment_ratings: 2, count_of_popular_comment_ratings: 1}] = Post |> Ash.Query.load([:count_of_comment_ratings, :count_of_popular_comment_ratings]) - |> Api.read!() + |> Ash.read!() end test "nested first aggregate works" do post = Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() comment = Comment - |> Ash.Changeset.new(%{title: "title", likes: 2}) + |> Ash.Changeset.for_create(:create, %{title: "title", likes: 2}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() Rating - |> Ash.Changeset.new(%{score: 10, resource_id: comment.id}) + |> Ash.Changeset.for_create(:create, %{score: 10, resource_id: comment.id}) |> Ash.Changeset.set_context(%{data_layer: %{table: "comment_ratings"}}) - |> Api.create!() + |> Ash.create!() post = Post |> Ash.Query.load(:highest_rating) - |> Api.read!() + |> Ash.read!() |> Enum.at(0) assert post.highest_rating == 10 @@ -970,17 +968,17 @@ defmodule AshPostgres.AggregateTest do test "loading a nested aggregate works" do post = Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "title", likes: 2}) + |> Ash.Changeset.for_create(:create, %{title: "title", likes: 2}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() Post |> Ash.Query.load(:count_of_comment_ratings) - |> Api.read!() + |> Ash.read!() |> Enum.map(fn post -> assert post.count_of_comment_ratings == 0 end) @@ -989,55 +987,55 @@ defmodule AshPostgres.AggregateTest do test "the sum can be filtered on when paginating" do post = Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "match", likes: 2}) + |> Ash.Changeset.for_create(:create, %{title: "match", likes: 2}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() assert %{sum_of_comment_likes_called_match: 2} = Post |> Ash.Query.filter(id == ^post.id) |> Ash.Query.load(:sum_of_comment_likes_called_match) - |> Api.read_one!() + |> Ash.read_one!() Comment - |> Ash.Changeset.new(%{title: "not_match", likes: 3}) + |> Ash.Changeset.for_create(:create, %{title: "not_match", likes: 3}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() assert %Ash.Page.Offset{results: [%{sum_of_comment_likes_called_match: 2}]} = Post |> Ash.Query.filter(id == ^post.id) |> Ash.Query.load(:sum_of_comment_likes_called_match) |> Ash.Query.filter(sum_of_comment_likes_called_match == 2) - |> Api.read!(action: :paginated, page: [limit: 1, count: true]) + |> Ash.read!(action: :paginated, page: [limit: 1, count: true]) assert %Ash.Page.Offset{results: []} = Post |> Ash.Query.filter(id == ^post.id) |> Ash.Query.load(:sum_of_comment_likes_called_match) |> Ash.Query.filter(sum_of_comment_likes_called_match == 3) - |> Api.read!(action: :paginated, page: [limit: 1, count: true]) + |> Ash.read!(action: :paginated, page: [limit: 1, count: true]) end test "an aggregate on relationships with a filter returns the proper value" do post = Post - |> Ash.Changeset.new(%{title: "title", category: "foo"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title", category: "foo"}) + |> Ash.create!() Comment |> Ash.Changeset.for_create(:create, %{title: "match", likes: 20}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() Comment |> Ash.Changeset.for_create(:create, %{title: "match", likes: 17}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() Comment |> Ash.Changeset.for_create(:create, %{title: "match", likes: 50}) @@ -1046,29 +1044,29 @@ defmodule AshPostgres.AggregateTest do DateTime.add(DateTime.utc_now(), :timer.hours(24) * -20, :second) ) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() assert %Post{sum_of_recent_popular_comment_likes: 37} = Post |> Ash.Query.load(:sum_of_recent_popular_comment_likes) - |> Api.read_one!() + |> Ash.read_one!() end test "a count aggregate on relationships with a filter returns the proper value" do post = Post - |> Ash.Changeset.new(%{title: "title", category: "foo"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title", category: "foo"}) + |> Ash.create!() Comment |> Ash.Changeset.for_create(:create, %{title: "match", likes: 20}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() Comment |> Ash.Changeset.for_create(:create, %{title: "match", likes: 17}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() Comment |> Ash.Changeset.for_create(:create, %{title: "match", likes: 50}) @@ -1077,142 +1075,142 @@ defmodule AshPostgres.AggregateTest do DateTime.add(DateTime.utc_now(), :timer.hours(24) * -20, :second) ) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() assert %Post{count_of_recent_popular_comments: 2} = Post |> Ash.Query.load([ :count_of_recent_popular_comments ]) - |> Api.read_one!() + |> Ash.read_one!() end test "a count aggregate with a related filter returns the proper value" do post = Post - |> Ash.Changeset.new(%{title: "title", category: "foo"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title", category: "foo"}) + |> Ash.create!() Comment |> Ash.Changeset.for_create(:create, %{title: "match"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() Comment |> Ash.Changeset.for_create(:create, %{title: "match"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() Comment |> Ash.Changeset.for_create(:create, %{title: "match"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() assert %Post{count_of_comments_that_have_a_post: 3} = Post |> Ash.Query.load([ :count_of_comments_that_have_a_post ]) - |> Api.read_one!() + |> Ash.read_one!() end test "a count aggregate with a related filter that uses `exists` returns the proper value" do post = Post - |> Ash.Changeset.new(%{title: "title", category: "foo"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title", category: "foo"}) + |> Ash.create!() Comment |> Ash.Changeset.for_create(:create, %{title: "match"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() Comment |> Ash.Changeset.for_create(:create, %{title: "match"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() Comment |> Ash.Changeset.for_create(:create, %{title: "match"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() assert %Post{count_of_comments_that_have_a_post_with_exists: 3} = Post |> Ash.Query.load([ :count_of_comments_that_have_a_post_with_exists ]) - |> Api.read_one!() + |> Ash.read_one!() end test "a count with a filter that references a relationship that also has a filter" do post = Post - |> Ash.Changeset.new(%{title: "title", category: "foo"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title", category: "foo"}) + |> Ash.create!() comment = Comment |> Ash.Changeset.for_create(:create, %{title: "match"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() comment2 = Comment |> Ash.Changeset.for_create(:create, %{title: "match"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() Rating |> Ash.Changeset.for_create(:create, %{score: 10, resource_id: comment.id}) |> Ash.Changeset.set_context(%{data_layer: %{table: "comment_ratings"}}) - |> Api.create!() + |> Ash.create!() Rating |> Ash.Changeset.for_create(:create, %{score: 1, resource_id: comment2.id}) |> Ash.Changeset.set_context(%{data_layer: %{table: "comment_ratings"}}) - |> Api.create!() + |> Ash.create!() assert %Post{count_of_popular_comments: 1} = Post |> Ash.Query.load([ :count_of_popular_comments ]) - |> Api.read_one!() + |> Ash.read_one!() end test "a count with a filter that references a to many relationship can be aggregated at the query level" do Post |> Ash.Query.filter(comments.likes > 10) - |> Api.count!() + |> Ash.count!() end test "a list with a filter that references a to many relationship can be aggregated at the query level" do Post |> Ash.Query.filter(comments.likes > 10) - |> Api.list!(:title) + |> Ash.list!(:title) end test "a count with a limit and a filter can be aggregated at the query level" do Post - |> Ash.Changeset.new(%{title: "foo"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "foo"}) + |> Ash.create!() Post - |> Ash.Changeset.new(%{title: "foo"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "foo"}) + |> Ash.create!() assert 1 = Post |> Ash.Query.for_read(:title_is_foo) |> Ash.Query.limit(1) - |> Api.count!() + |> Ash.count!() end test "a count can filter independently of the query" do assert {:ok, %{count: 0, count2: 0}} = Post - |> Api.aggregate([ + |> Ash.aggregate([ {:count, :count, query: [filter: Ash.Expr.expr(comments.likes > 10)]}, {:count2, :count, query: [filter: Ash.Expr.expr(comments.likes < 10)]} ]) @@ -1221,7 +1219,7 @@ defmodule AshPostgres.AggregateTest do test "multiple aggregates will be grouped up if possible" do assert {:ok, %{count: 0, count2: 0}} = Post - |> Api.aggregate([ + |> Ash.aggregate([ {:count, :count, query: [ filter: @@ -1240,30 +1238,30 @@ defmodule AshPostgres.AggregateTest do test "a count with a filter that references a relationship combined with another" do post = Post - |> Ash.Changeset.new(%{title: "title", category: "foo"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title", category: "foo"}) + |> Ash.create!() comment = Comment |> Ash.Changeset.for_create(:create, %{title: "match"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() comment2 = Comment |> Ash.Changeset.for_create(:create, %{title: "match"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() Rating |> Ash.Changeset.for_create(:create, %{score: 10, resource_id: comment.id}) |> Ash.Changeset.set_context(%{data_layer: %{table: "comment_ratings"}}) - |> Api.create!() + |> Ash.create!() Rating |> Ash.Changeset.for_create(:create, %{score: 1, resource_id: comment2.id}) |> Ash.Changeset.set_context(%{data_layer: %{table: "comment_ratings"}}) - |> Api.create!() + |> Ash.create!() assert %Post{count_of_popular_comments: 1} = Post @@ -1271,7 +1269,7 @@ defmodule AshPostgres.AggregateTest do :count_of_comments, :count_of_popular_comments ]) - |> Api.read_one!() + |> Ash.read_one!() end end end diff --git a/test/ash_postgres_test.exs b/test/ash_postgres_test.exs index df0fc92..dfcf765 100644 --- a/test/ash_postgres_test.exs +++ b/test/ash_postgres_test.exs @@ -3,8 +3,8 @@ defmodule AshPostgresTest do test "transaction metadata is given to on_transaction_begin" do AshPostgres.Test.Post - |> Ash.Changeset.new(%{title: "title"}) - |> AshPostgres.Test.Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() assert_receive %{ type: :create, @@ -15,8 +15,8 @@ defmodule AshPostgresTest do test "filter policies are applied" do post = AshPostgres.Test.Post - |> Ash.Changeset.new(%{title: "good"}) - |> AshPostgres.Test.Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "good"}) + |> Ash.create!() assert_raise Ash.Error.Forbidden, fn -> post @@ -24,13 +24,13 @@ defmodule AshPostgresTest do authorize?: true, actor: %{id: Ash.UUID.generate()} ) - |> AshPostgres.Test.Api.update!() + |> Ash.update!() |> Map.get(:title) end post |> Ash.Changeset.for_update(:update, %{title: "okay"}, authorize?: true) - |> AshPostgres.Test.Api.update!() + |> Ash.update!() |> Map.get(:title) end end diff --git a/test/atomics_test.exs b/test/atomics_test.exs index 99fe059..7f03507 100644 --- a/test/atomics_test.exs +++ b/test/atomics_test.exs @@ -1,6 +1,6 @@ defmodule AshPostgres.AtomicsTest do use AshPostgres.RepoCase, async: false - alias AshPostgres.Test.{Api, Post} + alias AshPostgres.Test.Post import Ash.Expr @@ -10,55 +10,57 @@ defmodule AshPostgres.AtomicsTest do Post |> Ash.Changeset.for_create(:create, %{id: id, title: "foo", price: 1}, upsert?: true) |> Ash.Changeset.atomic_update(:price, expr(price + 1)) - |> Api.create!() + |> Ash.create!() Post |> Ash.Changeset.for_create(:create, %{id: id, title: "foo", price: 1}, upsert?: true) |> Ash.Changeset.atomic_update(:price, expr(price + 1)) - |> Api.create!() + |> Ash.create!() - assert [%{price: 2}] = Post |> Api.read!() + assert [%{price: 2}] = Post |> Ash.read!() end test "a basic atomic works" do post = Post |> Ash.Changeset.for_create(:create, %{title: "foo", price: 1}) - |> Api.create!() + |> Ash.create!() assert %{price: 2} = post |> Ash.Changeset.for_update(:update, %{}) |> Ash.Changeset.atomic_update(:price, expr(price + 1)) - |> Api.update!() + |> Ash.update!() end test "an atomic works with a datetime" do post = Post |> Ash.Changeset.for_create(:create, %{title: "foo", price: 1}) - |> Api.create!() + |> Ash.create!() now = DateTime.utc_now() assert %{created_at: ^now} = post - |> Ash.Changeset.for_update(:update, %{}) + |> Ash.Changeset.new() |> Ash.Changeset.atomic_update(:created_at, expr(^now)) - |> Api.update!() + |> Ash.Changeset.for_update(:update, %{}) + |> Ash.update!() end test "an atomic that violates a constraint will return the proper error" do post = Post |> Ash.Changeset.for_create(:create, %{title: "foo", price: 1}) - |> Api.create!() + |> Ash.create!() assert_raise Ash.Error.Invalid, ~r/does not exist/, fn -> post - |> Ash.Changeset.for_update(:update, %{}) + |> Ash.Changeset.new() |> Ash.Changeset.atomic_update(:organization_id, Ash.UUID.generate()) - |> Api.update!() + |> Ash.Changeset.for_update(:update, %{}) + |> Ash.update!() end end @@ -66,13 +68,13 @@ defmodule AshPostgres.AtomicsTest do post = Post |> Ash.Changeset.for_create(:create, %{title: "foo", price: 1}) - |> Api.create!() + |> Ash.create!() post = post |> Ash.Changeset.for_update(:update, %{}) |> Ash.Changeset.atomic_update(:score, expr(score_after_winning)) - |> Api.update!() + |> Ash.update!() assert post.score == 1 end @@ -81,7 +83,7 @@ defmodule AshPostgres.AtomicsTest do post = Post |> Ash.Changeset.for_create(:create, %{title: "foo", price: 1}) - |> Api.create!() + |> Ash.create!() assert Post.increment_score!(post, 2).score == 2 diff --git a/test/bulk_create_test.exs b/test/bulk_create_test.exs index e5b301d..b351c3d 100644 --- a/test/bulk_create_test.exs +++ b/test/bulk_create_test.exs @@ -1,20 +1,20 @@ defmodule AshPostgres.BulkCreateTest do use AshPostgres.RepoCase, async: false - alias AshPostgres.Test.{Api, Post} + alias AshPostgres.Test.Post describe "bulk creates" do test "bulk creates insert each input" do - Api.bulk_create!([%{title: "fred"}, %{title: "george"}], Post, :create) + Ash.bulk_create!([%{title: "fred"}, %{title: "george"}], Post, :create) assert [%{title: "fred"}, %{title: "george"}] = Post |> Ash.Query.sort(:title) - |> Api.read!() + |> Ash.read!() end test "bulk creates can be streamed" do assert [{:ok, %{title: "fred"}}, {:ok, %{title: "george"}}] = - Api.bulk_create!([%{title: "fred"}, %{title: "george"}], Post, :create, + Ash.bulk_create!([%{title: "fred"}, %{title: "george"}], Post, :create, return_stream?: true, return_records?: true ) @@ -26,7 +26,7 @@ defmodule AshPostgres.BulkCreateTest do {:ok, %{title: "fred", uniq_one: "one", uniq_two: "two", price: 10}}, {:ok, %{title: "george", uniq_one: "three", uniq_two: "four", price: 20}} ] = - Api.bulk_create!( + Ash.bulk_create!( [ %{title: "fred", uniq_one: "one", uniq_two: "two", price: 10}, %{title: "george", uniq_one: "three", uniq_two: "four", price: 20} @@ -42,7 +42,7 @@ defmodule AshPostgres.BulkCreateTest do {:ok, %{title: "fred", uniq_one: "one", uniq_two: "two", price: 1000}}, {:ok, %{title: "george", uniq_one: "three", uniq_two: "four", price: 20_000}} ] = - Api.bulk_create!( + Ash.bulk_create!( [ %{title: "something", uniq_one: "one", uniq_two: "two", price: 1000}, %{title: "else", uniq_one: "three", uniq_two: "four", price: 20_000} @@ -76,7 +76,7 @@ defmodule AshPostgres.BulkCreateTest do # id: org_id, # title: "Avengers" # }) - # |> Api.create!() + # |> Ash.create!() # assert [ # {:ok, @@ -94,7 +94,7 @@ defmodule AshPostgres.BulkCreateTest do # organization_id: org_id # }} # ] = - # Api.bulk_create!( + # Ash.bulk_create!( # [ # %{ # name: "Tony Stark", @@ -135,7 +135,7 @@ defmodule AshPostgres.BulkCreateTest do # role: "master in chief" # }} # ] = - # Api.bulk_create!( + # Ash.bulk_create!( # [ # %{ # name: "Tony Stark", @@ -169,7 +169,7 @@ defmodule AshPostgres.BulkCreateTest do # end test "bulk creates can create relationships" do - Api.bulk_create!( + Ash.bulk_create!( [%{title: "fred", rating: %{score: 5}}, %{title: "george", rating: %{score: 0}}], Post, :create @@ -182,14 +182,14 @@ defmodule AshPostgres.BulkCreateTest do Post |> Ash.Query.sort(:title) |> Ash.Query.load(:ratings) - |> Api.read!() + |> Ash.read!() end end describe "validation errors" do test "skips invalid by default" do assert %{records: [_], errors: [_]} = - Api.bulk_create!([%{title: "fred"}, %{title: "not allowed"}], Post, :create, + Ash.bulk_create!([%{title: "fred"}, %{title: "not allowed"}], Post, :create, return_records?: true, return_errors?: true ) @@ -197,7 +197,7 @@ defmodule AshPostgres.BulkCreateTest do test "returns errors in the stream" do assert [{:ok, _}, {:error, _}] = - Api.bulk_create!([%{title: "fred"}, %{title: "not allowed"}], Post, :create, + Ash.bulk_create!([%{title: "fred"}, %{title: "not allowed"}], Post, :create, return_records?: true, return_stream?: true, return_errors?: true @@ -209,7 +209,7 @@ defmodule AshPostgres.BulkCreateTest do describe "database errors" do test "database errors affect the entire batch" do # assert %{records: [_], errors: [_]} = - Api.bulk_create( + Ash.bulk_create( [%{title: "fred"}, %{title: "george", organization_id: Ash.UUID.generate()}], Post, :create, @@ -219,11 +219,11 @@ defmodule AshPostgres.BulkCreateTest do assert [] = Post |> Ash.Query.sort(:title) - |> Api.read!() + |> Ash.read!() end test "database errors don't affect other batches" do - Api.bulk_create( + Ash.bulk_create( [%{title: "george", organization_id: Ash.UUID.generate()}, %{title: "fred"}], Post, :create, @@ -234,7 +234,7 @@ defmodule AshPostgres.BulkCreateTest do assert [%{title: "fred"}] = Post |> Ash.Query.sort(:title) - |> Api.read!() + |> Ash.read!() end end end diff --git a/test/bulk_destroy_test.exs b/test/bulk_destroy_test.exs index 6fe4c8a..fa55a6a 100644 --- a/test/bulk_destroy_test.exs +++ b/test/bulk_destroy_test.exs @@ -1,50 +1,50 @@ defmodule AshPostgres.BulkDestroyTest do use AshPostgres.RepoCase, async: false - alias AshPostgres.Test.{Api, Post} + alias AshPostgres.Test.Post require Ash.Expr require Ash.Query test "bulk destroys can run with nothing in the table" do - Api.bulk_destroy!(Post, :update, %{title: "new_title"}) + Ash.bulk_destroy!(Post, :update, %{title: "new_title"}) end test "bulk destroys destroy everything pertaining to the query" do - Api.bulk_create!([%{title: "fred"}, %{title: "george"}], Post, :create) + Ash.bulk_create!([%{title: "fred"}, %{title: "george"}], Post, :create) - Api.bulk_destroy!(Post, :update, %{}) + Ash.bulk_destroy!(Post, :update, %{}) - assert Api.read!(Post) == [] + assert Ash.read!(Post) == [] end test "bulk destroys only apply to things that the query produces" do - Api.bulk_create!([%{title: "fred"}, %{title: "george"}], Post, :create) + Ash.bulk_create!([%{title: "fred"}, %{title: "george"}], Post, :create) Post |> Ash.Query.filter(title == "fred") - |> Api.bulk_destroy!(:update, %{}) + |> Ash.bulk_destroy!(:update, %{}) # 😢 sad - assert [%{title: "george"}] = Api.read!(Post) + assert [%{title: "george"}] = Ash.read!(Post) end test "the query can join to related tables when necessary" do - Api.bulk_create!([%{title: "fred"}, %{title: "george"}], Post, :create) + Ash.bulk_create!([%{title: "fred"}, %{title: "george"}], Post, :create) Post |> Ash.Query.filter(author.first_name == "fred" or title == "fred") - |> Api.bulk_destroy!(:update, %{}, return_records?: true) + |> Ash.bulk_destroy!(:update, %{}, return_records?: true) - assert [%{title: "george"}] = Api.read!(Post) + assert [%{title: "george"}] = Ash.read!(Post) end test "bulk destroys can be done even on stream inputs" do - Api.bulk_create!([%{title: "fred"}, %{title: "george"}], Post, :create) + Ash.bulk_create!([%{title: "fred"}, %{title: "george"}], Post, :create) Post - |> Api.read!() - |> Api.bulk_destroy!(:destroy, %{}) + |> Ash.read!() + |> Ash.bulk_destroy!(:destroy, %{}, strategy: :stream, return_errors?: true) - assert [] = Api.read!(Post) + assert [] = Ash.read!(Post) end end diff --git a/test/bulk_update_test.exs b/test/bulk_update_test.exs index d561167..e2650df 100644 --- a/test/bulk_update_test.exs +++ b/test/bulk_update_test.exs @@ -1,30 +1,30 @@ defmodule AshPostgres.BulkUpdateTest do use AshPostgres.RepoCase, async: false - alias AshPostgres.Test.{Api, Post} + alias AshPostgres.Test.Post require Ash.Expr require Ash.Query test "bulk updates can run with nothing in the table" do - Api.bulk_update!(Post, :update, %{title: "new_title"}) + Ash.bulk_update!(Post, :update, %{title: "new_title"}) end test "bulk updates update everything pertaining to the query" do - Api.bulk_create!([%{title: "fred"}, %{title: "george"}], Post, :create) + Ash.bulk_create!([%{title: "fred"}, %{title: "george"}], Post, :create) - Api.bulk_update!(Post, :update, %{}, + Ash.bulk_update!(Post, :update, %{}, atomic_update: %{title: Ash.Expr.expr(title <> "_stuff")} ) - posts = Api.read!(Post) + posts = Ash.read!(Post) assert Enum.all?(posts, &String.ends_with?(&1.title, "_stuff")) end test "a map can be given as input" do - Api.bulk_create!([%{title: "fred"}, %{title: "george"}], Post, :create) + Ash.bulk_create!([%{title: "fred"}, %{title: "george"}], Post, :create) Post - |> Api.bulk_update!( + |> Ash.bulk_update!( :update, %{list_of_stuff: [%{a: 1}]}, return_records?: true, @@ -36,25 +36,25 @@ defmodule AshPostgres.BulkUpdateTest do test "a map can be given as input on a regular update" do %{records: [post | _]} = - Api.bulk_create!([%{title: "fred"}, %{title: "george"}], Post, :create, + Ash.bulk_create!([%{title: "fred"}, %{title: "george"}], Post, :create, return_records?: true ) post |> Ash.Changeset.for_update(:update, %{list_of_stuff: [%{a: [:a, :b]}, %{a: [:c, :d]}]}) - |> Api.update!() + |> Ash.update!() end test "bulk updates only apply to things that the query produces" do - Api.bulk_create!([%{title: "fred"}, %{title: "george"}], Post, :create) + Ash.bulk_create!([%{title: "fred"}, %{title: "george"}], Post, :create) Post |> Ash.Query.filter(title == "fred") - |> Api.bulk_update!(:update, %{}, atomic_update: %{title: Ash.Expr.expr(title <> "_stuff")}) + |> Ash.bulk_update!(:update, %{}, atomic_update: %{title: Ash.Expr.expr(title <> "_stuff")}) titles = Post - |> Api.read!() + |> Ash.read!() |> Enum.map(& &1.title) |> Enum.sort() @@ -62,15 +62,15 @@ defmodule AshPostgres.BulkUpdateTest do end test "the query can join to related tables when necessary" do - Api.bulk_create!([%{title: "fred"}, %{title: "george"}], Post, :create) + Ash.bulk_create!([%{title: "fred"}, %{title: "george"}], Post, :create) Post |> Ash.Query.filter(author.first_name == "fred" or title == "fred") - |> Api.bulk_update!(:update, %{}, atomic_update: %{title: Ash.Expr.expr(title <> "_stuff")}) + |> Ash.bulk_update!(:update, %{}, atomic_update: %{title: Ash.Expr.expr(title <> "_stuff")}) titles = Post - |> Api.read!() + |> Ash.read!() |> Enum.map(& &1.title) |> Enum.sort() @@ -78,18 +78,19 @@ defmodule AshPostgres.BulkUpdateTest do end test "bulk updates can be done even on stream inputs" do - Api.bulk_create!([%{title: "fred"}, %{title: "george"}], Post, :create) + Ash.bulk_create!([%{title: "fred"}, %{title: "george"}], Post, :create) Post - |> Api.read!() - |> Api.bulk_update!(:update, %{}, + |> Ash.read!() + |> Ash.bulk_update!(:update, %{}, atomic_update: %{title: Ash.Expr.expr(title <> "_stuff")}, - return_records?: true + return_records?: true, + strategy: [:stream] ) titles = Post - |> Api.read!() + |> Ash.read!() |> Enum.map(& &1.title) |> Enum.sort() @@ -97,14 +98,17 @@ defmodule AshPostgres.BulkUpdateTest do end test "bulk updates that require initial data must use streaming" do - Api.bulk_create!([%{title: "fred"}, %{title: "george"}], Post, :create) + Ash.bulk_create!([%{title: "fred"}, %{title: "george"}], Post, :create) - Post - |> Ash.Query.for_read(:paginated, authorize?: true) - |> Api.bulk_update!(:requires_initial_data, %{}, - authorize?: true, - allow_stream_with: :full_read, - authorize_query?: false - ) + assert_raise Ash.Error.Invalid, ~r/had no matching bulk strategy that could be used/, fn -> + Post + |> Ash.Query.for_read(:paginated, authorize?: true) + |> Ash.bulk_update!(:requires_initial_data, %{}, + authorize?: true, + allow_stream_with: :full_read, + authorize_query?: false, + return_errors?: true + ) + end end end diff --git a/test/calculation_test.exs b/test/calculation_test.exs index 3b6344d..c29224c 100644 --- a/test/calculation_test.exs +++ b/test/calculation_test.exs @@ -1,6 +1,6 @@ defmodule AshPostgres.CalculationTest do use AshPostgres.RepoCase, async: false - alias AshPostgres.Test.{Account, Api, Author, Comment, Post, User} + alias AshPostgres.Test.{Account, Author, Comment, Post, User} require Ash.Query import Ash.Expr @@ -8,48 +8,48 @@ defmodule AshPostgres.CalculationTest do test "an expression calculation can be filtered on" do post = Post - |> Ash.Changeset.new(%{title: "match"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "match"}) + |> Ash.create!() post2 = Post - |> Ash.Changeset.new(%{title: "title2"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title2"}) + |> Ash.create!() post3 = Post - |> Ash.Changeset.new(%{title: "title3"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title3"}) + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "_"}) + |> Ash.Changeset.for_create(:create, %{title: "_"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "_"}) + |> Ash.Changeset.for_create(:create, %{title: "_"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "_"}) + |> Ash.Changeset.for_create(:create, %{title: "_"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() post |> Ash.Changeset.new() |> Ash.Changeset.manage_relationship(:linked_posts, [post2, post3], type: :append_and_remove) - |> Api.update!() + |> Ash.update!() post2 |> Ash.Changeset.new() |> Ash.Changeset.manage_relationship(:linked_posts, [post3], type: :append_and_remove) - |> Api.update!() + |> Ash.update!() assert [%{c_times_p: 6, title: "match"}] = Post |> Ash.Query.load(:c_times_p) - |> Api.read!() + |> Ash.read!() |> Enum.filter(&(&1.c_times_p == 6)) assert [ @@ -57,12 +57,12 @@ defmodule AshPostgres.CalculationTest do ] = Post |> Ash.Query.filter(c_times_p == 6) - |> Api.read!() + |> Ash.read!() assert [] = Post |> Ash.Query.filter(author: [has_posts: true]) - |> Api.read!() + |> Ash.read!() end test "calculations can refer to to_one path attributes in filters" do @@ -72,18 +72,18 @@ defmodule AshPostgres.CalculationTest do first_name: "Foo", bio: %{title: "Mr.", bio: "Bones"} }) - |> Api.create!() + |> Ash.create!() Post - |> Ash.Changeset.new(%{title: "match"}) + |> Ash.Changeset.for_create(:create, %{title: "match"}) |> Ash.Changeset.manage_relationship(:author, author, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() assert [%{author_first_name_calc: "Foo"}] = Post |> Ash.Query.filter(author_first_name_calc == "Foo") |> Ash.Query.load(:author_first_name_calc) - |> Api.read!() + |> Ash.read!() end test "calculations can refer to to_one path attributes in sorts" do @@ -93,44 +93,44 @@ defmodule AshPostgres.CalculationTest do first_name: "Foo", bio: %{title: "Mr.", bio: "Bones"} }) - |> Api.create!() + |> Ash.create!() Post - |> Ash.Changeset.new(%{title: "match"}) + |> Ash.Changeset.for_create(:create, %{title: "match"}) |> Ash.Changeset.manage_relationship(:author, author, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() assert [%{author_first_name_calc: "Foo"}] = Post |> Ash.Query.sort(:author_first_name_calc) |> Ash.Query.load(:author_first_name_calc) - |> Api.read!() + |> Ash.read!() end test "calculations can refer to embedded attributes" do author = Author |> Ash.Changeset.for_create(:create, %{bio: %{title: "Mr.", bio: "Bones"}}) - |> Api.create!() + |> Ash.create!() assert %{title: "Mr."} = Author |> Ash.Query.filter(id == ^author.id) |> Ash.Query.load(:title) - |> Api.read_one!() + |> Ash.read_one!() end test "calculations can use the || operator" do author = Author |> Ash.Changeset.for_create(:create, %{bio: %{title: "Mr.", bio: "Bones"}}) - |> Api.create!() + |> Ash.create!() assert %{first_name_or_bob: "bob"} = Author |> Ash.Query.filter(id == ^author.id) |> Ash.Query.load(:first_name_or_bob) - |> Api.read_one!() + |> Ash.read_one!() end test "calculations can use the && operator" do @@ -140,60 +140,60 @@ defmodule AshPostgres.CalculationTest do first_name: "fred", bio: %{title: "Mr.", bio: "Bones"} }) - |> Api.create!() + |> Ash.create!() assert %{first_name_and_bob: "bob"} = Author |> Ash.Query.filter(id == ^author.id) |> Ash.Query.load(:first_name_and_bob) - |> Api.read_one!() + |> Ash.read_one!() end test "calculations can be used in related filters" do post = Post - |> Ash.Changeset.new(%{title: "match"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "match"}) + |> Ash.create!() post2 = Post - |> Ash.Changeset.new(%{title: "title2"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title2"}) + |> Ash.create!() post3 = Post - |> Ash.Changeset.new(%{title: "title3"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title3"}) + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "match"}) + |> Ash.Changeset.for_create(:create, %{title: "match"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "match"}) + |> Ash.Changeset.for_create(:create, %{title: "match"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "match"}) + |> Ash.Changeset.for_create(:create, %{title: "match"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "no_match"}) + |> Ash.Changeset.for_create(:create, %{title: "no_match"}) |> Ash.Changeset.manage_relationship(:post, post2, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() post |> Ash.Changeset.new() |> Ash.Changeset.manage_relationship(:linked_posts, [post2, post3], type: :append_and_remove) - |> Api.update!() + |> Ash.update!() post2 |> Ash.Changeset.new() |> Ash.Changeset.manage_relationship(:linked_posts, [post3], type: :append_and_remove) - |> Api.update!() + |> Ash.update!() posts_query = Post @@ -202,7 +202,7 @@ defmodule AshPostgres.CalculationTest do assert %{post: %{c_times_p: 6}} = Comment |> Ash.Query.load(post: posts_query) - |> Api.read!() + |> Ash.read!() |> Enum.filter(&(&1.post.c_times_p == 6)) |> Enum.at(0) @@ -214,20 +214,20 @@ defmodule AshPostgres.CalculationTest do assert [ %{post: %{c_times_p: 6, title: "match"}} - ] = Api.read!(query) + ] = Ash.read!(query) - post |> Api.load!(:c_times_p) + post |> Ash.load!(:c_times_p) end test "concat calculation can be filtered on" do author = Author - |> Ash.Changeset.new(%{first_name: "is", last_name: "match"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{first_name: "is", last_name: "match"}) + |> Ash.create!() Author - |> Ash.Changeset.new(%{first_name: "not", last_name: "match"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{first_name: "not", last_name: "match"}) + |> Ash.create!() author_id = author.id @@ -235,60 +235,60 @@ defmodule AshPostgres.CalculationTest do Author |> Ash.Query.load(:full_name) |> Ash.Query.filter(full_name == "is match") - |> Api.read_one!() + |> Ash.read_one!() end test "calculations that refer to aggregates in comparison expressions can be filtered on" do Post |> Ash.Query.load(:has_future_comment) - |> Api.read!() + |> Ash.read!() end test "calculations that refer to aggregates can be authorized" do post = Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "comment"}) + |> Ash.Changeset.for_create(:create, %{title: "comment"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() assert %{has_future_comment: false} = Post |> Ash.Query.load([:has_future_comment, :latest_comment_created_at]) |> Ash.Query.for_read(:allow_any, %{}) - |> Api.read_one!(authorize?: true) + |> Ash.read_one!(authorize?: true) assert %{has_future_comment: true} = Post |> Ash.Query.load([:has_future_comment, :latest_comment_created_at]) |> Ash.Query.for_read(:allow_any, %{}) - |> Api.read_one!(authorize?: false) + |> Ash.read_one!(authorize?: false) assert %{has_future_comment: false} = Post |> Ash.Query.for_read(:allow_any, %{}) - |> Api.read_one!() - |> Api.load!([:has_future_comment, :latest_comment_created_at], authorize?: true) + |> Ash.read_one!() + |> Ash.load!([:has_future_comment, :latest_comment_created_at], authorize?: true) assert %{has_future_comment: true} = Post |> Ash.Query.for_read(:allow_any, %{}) - |> Api.read_one!() - |> Api.load!([:has_future_comment, :latest_comment_created_at], authorize?: false) + |> Ash.read_one!() + |> Ash.load!([:has_future_comment, :latest_comment_created_at], authorize?: false) end test "conditional calculations can be filtered on" do author = Author - |> Ash.Changeset.new(%{first_name: "tom"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{first_name: "tom"}) + |> Ash.create!() Author - |> Ash.Changeset.new(%{first_name: "tom", last_name: "holland"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{first_name: "tom", last_name: "holland"}) + |> Ash.create!() author_id = author.id @@ -296,45 +296,45 @@ defmodule AshPostgres.CalculationTest do Author |> Ash.Query.load([:conditional_full_name, :full_name]) |> Ash.Query.filter(conditional_full_name == "(none)") - |> Api.read_one!() + |> Ash.read_one!() end test "parameterized calculations can be filtered on" do Author - |> Ash.Changeset.new(%{first_name: "tom", last_name: "holland"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{first_name: "tom", last_name: "holland"}) + |> Ash.create!() assert %{param_full_name: "tom holland"} = Author |> Ash.Query.load(:param_full_name) - |> Api.read_one!() + |> Ash.read_one!() assert %{param_full_name: "tom~holland"} = Author |> Ash.Query.load(param_full_name: [separator: "~"]) - |> Api.read_one!() + |> Ash.read_one!() assert %{} = Author |> Ash.Query.filter(param_full_name(separator: "~") == "tom~holland") - |> Api.read_one!() + |> Ash.read_one!() end test "parameterized related calculations can be filtered on" do author = Author - |> Ash.Changeset.new(%{first_name: "tom", last_name: "holland"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{first_name: "tom", last_name: "holland"}) + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "match"}) + |> Ash.Changeset.for_create(:create, %{title: "match"}) |> Ash.Changeset.manage_relationship(:author, author, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() assert %{title: "match"} = Comment |> Ash.Query.filter(author.param_full_name(separator: "~") == "tom~holland") - |> Api.read_one!() + |> Ash.read_one!() assert %{title: "match"} = Comment @@ -342,93 +342,97 @@ defmodule AshPostgres.CalculationTest do author.param_full_name(separator: "~") == "tom~holland" and author.param_full_name(separator: " ") == "tom holland" ) - |> Api.read_one!() + |> Ash.read_one!() end test "parameterized calculations can be sorted on" do Author - |> Ash.Changeset.new(%{first_name: "tom", last_name: "holland"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{first_name: "tom", last_name: "holland"}) + |> Ash.create!() Author - |> Ash.Changeset.new(%{first_name: "abc", last_name: "def"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{first_name: "abc", last_name: "def"}) + |> Ash.create!() assert [%{first_name: "abc"}, %{first_name: "tom"}] = Author |> Ash.Query.sort(param_full_name: [separator: "~"]) - |> Api.read!() + |> Ash.read!() end test "calculations using if and literal boolean results can run" do Post |> Ash.Query.load(:was_created_in_the_last_month) |> Ash.Query.filter(was_created_in_the_last_month == true) - |> Api.read!() + |> Ash.read!() end test "nested conditional calculations can be loaded" do Author - |> Ash.Changeset.new(%{last_name: "holland"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{last_name: "holland"}) + |> Ash.create!() Author - |> Ash.Changeset.new(%{first_name: "tom"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{first_name: "tom"}) + |> Ash.create!() assert [%{nested_conditional: "No First Name"}, %{nested_conditional: "No Last Name"}] = Author |> Ash.Query.load(:nested_conditional) |> Ash.Query.sort(:nested_conditional) - |> Api.read!() + |> Ash.read!() end test "calculations load nullable timestamp aggregates compared to a fragment" do post = Post - |> Ash.Changeset.new(%{title: "aaa", score: 0}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "aaa", score: 0}) + |> Ash.create!() Post - |> Ash.Changeset.new(%{title: "aaa", score: 1}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "aaa", score: 1}) + |> Ash.create!() Post - |> Ash.Changeset.new(%{title: "bbb", score: 0}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "bbb", score: 0}) + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "aaa", likes: 1, arbitrary_timestamp: DateTime.now!("Etc/UTC")}) + |> Ash.Changeset.for_create(:create, %{ + title: "aaa", + likes: 1, + arbitrary_timestamp: DateTime.now!("Etc/UTC") + }) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "bbb", likes: 1}) + |> Ash.Changeset.for_create(:create, %{title: "bbb", likes: 1}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "aaa", likes: 2}) + |> Ash.Changeset.for_create(:create, %{title: "aaa", likes: 2}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() Post |> Ash.Query.load([:has_future_arbitrary_timestamp]) - |> Api.read!() + |> Ash.read!() end test "loading a calculation loads its dependent loads" do user = User |> Ash.Changeset.for_create(:create, %{is_active: true}) - |> Api.create!() + |> Ash.create!() account = Account |> Ash.Changeset.for_create(:create, %{is_active: true}) |> Ash.Changeset.manage_relationship(:user, user, type: :append_and_remove) - |> Api.create!() - |> Api.load!([:active]) + |> Ash.create!() + |> Ash.load!([:active]) assert account.active end @@ -442,7 +446,7 @@ defmodule AshPostgres.CalculationTest do last_name: "Jones", bio: %{title: "Mr.", bio: "Bones"} }) - |> Api.create!() + |> Ash.create!() assert %{ full_name_with_nils: "Bill Jones", @@ -452,7 +456,7 @@ defmodule AshPostgres.CalculationTest do |> Ash.Query.filter(id == ^author.id) |> Ash.Query.load(:full_name_with_nils) |> Ash.Query.load(:full_name_with_nils_no_joiner) - |> Api.read_one!() + |> Ash.read_one!() end test "with nil value" do @@ -462,7 +466,7 @@ defmodule AshPostgres.CalculationTest do first_name: "Bill", bio: %{title: "Mr.", bio: "Bones"} }) - |> Api.create!() + |> Ash.create!() assert %{ full_name_with_nils: "Bill", @@ -472,23 +476,23 @@ defmodule AshPostgres.CalculationTest do |> Ash.Query.filter(id == ^author.id) |> Ash.Query.load(:full_name_with_nils) |> Ash.Query.load(:full_name_with_nils_no_joiner) - |> Api.read_one!() + |> Ash.read_one!() end end test "arguments with cast_in_query?: false are not cast" do Post - |> Ash.Changeset.new(%{title: "match", score: 42}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "match", score: 42}) + |> Ash.create!() Post - |> Ash.Changeset.new(%{title: "not", score: 42}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "not", score: 42}) + |> Ash.create!() assert [post] = Post |> Ash.Query.filter(similarity(search: expr(query(search: "match")))) - |> Api.read!() + |> Ash.read!() assert post.title == "match" end @@ -502,7 +506,7 @@ defmodule AshPostgres.CalculationTest do last_name: "Jones", bio: %{title: "Mr.", bio: "Bones"} }) - |> Api.create!() + |> Ash.create!() assert %{ split_full_name: ["Bill", "Jones"] @@ -510,7 +514,7 @@ defmodule AshPostgres.CalculationTest do Author |> Ash.Query.filter(id == ^author.id) |> Ash.Query.load(:split_full_name) - |> Api.read_one!() + |> Ash.read_one!() end test "trimming whitespace" do @@ -521,7 +525,7 @@ defmodule AshPostgres.CalculationTest do last_name: "Jones ", bio: %{title: "Mr.", bio: "Bones"} }) - |> Api.create!() + |> Ash.create!() assert %{ split_full_name_trim: ["Bill", "Jones"], @@ -530,37 +534,37 @@ defmodule AshPostgres.CalculationTest do Author |> Ash.Query.filter(id == ^author.id) |> Ash.Query.load([:split_full_name_trim, :split_full_name]) - |> Api.read_one!() + |> Ash.read_one!() end end describe "count_nils/1" do test "counts nil values" do Post - |> Ash.Changeset.new(%{list_containing_nils: ["a", nil, "b", nil, "c"]}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{list_containing_nils: ["a", nil, "b", nil, "c"]}) + |> Ash.create!() Post - |> Ash.Changeset.new(%{list_containing_nils: ["a", nil, "b", "c"]}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{list_containing_nils: ["a", nil, "b", "c"]}) + |> Ash.create!() assert [_] = Post |> Ash.Query.filter(count_nils(list_containing_nils) == 2) - |> Api.read!() + |> Ash.read!() end end describe "-/1" do test "makes numbers negative" do Post - |> Ash.Changeset.new(%{title: "match", score: 42}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "match", score: 42}) + |> Ash.create!() assert [%{negative_score: -42}] = Post |> Ash.Query.load(:negative_score) - |> Api.read!() + |> Ash.read!() end end @@ -568,39 +572,39 @@ defmodule AshPostgres.CalculationTest do test "maps can reference filtered aggregates" do post = Post - |> Ash.Changeset.new(%{title: "match", score: 42}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "match", score: 42}) + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "foo", likes: 2}) + |> Ash.Changeset.for_create(:create, %{title: "foo", likes: 2}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "foo", likes: 2}) + |> Ash.Changeset.for_create(:create, %{title: "foo", likes: 2}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "bar", likes: 2}) + |> Ash.Changeset.for_create(:create, %{title: "bar", likes: 2}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() assert [%{agg_map: %{called_foo: 2, called_bar: 1}}] = Post |> Ash.Query.load(:agg_map) - |> Api.read!() + |> Ash.read!() end test "maps can be constructed" do Post - |> Ash.Changeset.new(%{title: "match", score: 42}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "match", score: 42}) + |> Ash.create!() assert [%{score_map: %{negative_score: %{foo: -42}}}] = Post |> Ash.Query.load(:score_map) - |> Api.read!() + |> Ash.read!() end end @@ -613,7 +617,7 @@ defmodule AshPostgres.CalculationTest do last_name: "Jones ", bio: %{title: "Mr.", bio: "Bones"} }) - |> Api.create!() + |> Ash.create!() assert %{ first_name_from_split: "Bill" @@ -621,15 +625,15 @@ defmodule AshPostgres.CalculationTest do Author |> Ash.Query.filter(id == ^author.id) |> Ash.Query.load([:first_name_from_split]) - |> Api.read_one!() + |> Ash.read_one!() end end test "dependent calc" do post = Post - |> Ash.Changeset.new(%{title: "match", price: 10_024}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "match", price: 10_024}) + |> Ash.create!() Post.get_by_id(post.id, query: Post |> Ash.Query.select([:id]) |> Ash.Query.load([:price_string_with_currency_sign]) @@ -639,10 +643,14 @@ defmodule AshPostgres.CalculationTest do test "nested get_path works" do assert "thing" = Post - |> Ash.Changeset.new(%{title: "match", price: 10_024, stuff: %{foo: %{bar: "thing"}}}) + |> Ash.Changeset.for_create(:create, %{ + title: "match", + price: 10_024, + stuff: %{foo: %{bar: "thing"}} + }) |> Ash.Changeset.deselect(:stuff) - |> Api.create!() - |> Api.load!(:foo_bar_from_stuff) + |> Ash.create!() + |> Ash.load!(:foo_bar_from_stuff) |> Map.get(:foo_bar_from_stuff) end @@ -654,19 +662,19 @@ defmodule AshPostgres.CalculationTest do last_name: "Jones", bio: %{title: "Mr.", bio: "Bones"} }) - |> Api.create!() + |> Ash.create!() assert %AshPostgres.Test.Money{} = Post - |> Ash.Changeset.new(%{title: "match", price: 10_024}) + |> Ash.Changeset.for_create(:create, %{title: "match", price: 10_024}) |> Ash.Changeset.manage_relationship(:author, author, type: :append_and_remove) - |> Api.create!() - |> Api.load!(:calc_returning_json) + |> Ash.create!() + |> Ash.load!(:calc_returning_json) |> Map.get(:calc_returning_json) assert [%AshPostgres.Test.Money{}] = author - |> Api.load!(posts: :calc_returning_json) + |> Ash.load!(posts: :calc_returning_json) |> Map.get(:posts) |> Enum.map(&Map.get(&1, :calc_returning_json)) end @@ -678,7 +686,7 @@ defmodule AshPostgres.CalculationTest do last_name: "Jones", bio: %{title: "Mr.", bio: "Bones"} }) - |> Api.create!() + |> Ash.create!() assert %{calculations: %{length: 9}} = Author @@ -687,7 +695,7 @@ defmodule AshPostgres.CalculationTest do expr(string_length(string_trim(first_name <> last_name <> " "))), :integer ) - |> Api.read_one!() + |> Ash.read_one!() end test "an expression calculation that loads a runtime calculation works" do @@ -697,12 +705,12 @@ defmodule AshPostgres.CalculationTest do last_name: "Jones", bio: %{title: "Mr.", bio: "Bones"} }) - |> Api.create!() + |> Ash.create!() assert [%{expr_referencing_runtime: "Bill Jones Bill Jones"}] = Author |> Ash.Query.load(:expr_referencing_runtime) - |> Api.read!() + |> Ash.read!() end test "lazy values are evaluated lazily" do @@ -712,7 +720,7 @@ defmodule AshPostgres.CalculationTest do last_name: "Jones", bio: %{title: "Mr.", bio: "Bones"} }) - |> Api.create!() + |> Ash.create!() assert %{calculations: %{string: "fred"}} = Author @@ -721,21 +729,21 @@ defmodule AshPostgres.CalculationTest do expr(lazy({__MODULE__, :fred, []})), :string ) - |> Api.read_one!() + |> Ash.read_one!() end test "exists with a relationship that has a filtered read action works" do post = Post |> Ash.Changeset.for_create(:create, %{}) - |> Api.create!() + |> Ash.create!() post_id = post.id assert [%{id: ^post_id}] = Post |> Ash.Query.filter(has_no_followers) - |> Api.read!() + |> Ash.read!() end def fred do diff --git a/test/complex_calculations_test.exs b/test/complex_calculations_test.exs index 829f3a5..8e67e7e 100644 --- a/test/complex_calculations_test.exs +++ b/test/complex_calculations_test.exs @@ -7,29 +7,29 @@ defmodule AshPostgres.Test.ComplexCalculationsTest do certification = AshPostgres.Test.ComplexCalculations.Certification |> Ash.Changeset.new() - |> AshPostgres.Test.ComplexCalculations.Api.create!() + |> Ash.create!() skill = AshPostgres.Test.ComplexCalculations.Skill |> Ash.Changeset.new() |> Ash.Changeset.manage_relationship(:certification, certification, type: :append) - |> AshPostgres.Test.ComplexCalculations.Api.create!() + |> Ash.create!() _documentation = AshPostgres.Test.ComplexCalculations.Documentation - |> Ash.Changeset.new(%{status: :demonstrated}) + |> Ash.Changeset.for_create(:create, %{status: :demonstrated}) |> Ash.Changeset.manage_relationship(:skill, skill, type: :append) - |> AshPostgres.Test.ComplexCalculations.Api.create!() + |> Ash.create!() skill = skill - |> AshPostgres.Test.ComplexCalculations.Api.load!([:latest_documentation_status]) + |> Ash.load!([:latest_documentation_status]) assert skill.latest_documentation_status == :demonstrated certification = certification - |> AshPostgres.Test.ComplexCalculations.Api.load!([ + |> Ash.load!([ :count_of_skills ]) @@ -37,7 +37,7 @@ defmodule AshPostgres.Test.ComplexCalculationsTest do certification = certification - |> AshPostgres.Test.ComplexCalculations.Api.load!([ + |> Ash.load!([ :count_of_approved_skills ]) @@ -45,7 +45,7 @@ defmodule AshPostgres.Test.ComplexCalculationsTest do certification = certification - |> AshPostgres.Test.ComplexCalculations.Api.load!([ + |> Ash.load!([ :count_of_documented_skills ]) @@ -53,7 +53,7 @@ defmodule AshPostgres.Test.ComplexCalculationsTest do certification = certification - |> AshPostgres.Test.ComplexCalculations.Api.load!([ + |> Ash.load!([ :count_of_documented_skills, :all_documentation_approved, :some_documentation_created @@ -66,35 +66,35 @@ defmodule AshPostgres.Test.ComplexCalculationsTest do channel = AshPostgres.Test.ComplexCalculations.Channel |> Ash.Changeset.new() - |> AshPostgres.Test.ComplexCalculations.Api.create!() + |> Ash.create!() user_1 = AshPostgres.Test.User |> Ash.Changeset.for_create(:create, %{name: "User 1"}) - |> AshPostgres.Test.Api.create!() + |> Ash.create!() user_2 = AshPostgres.Test.User |> Ash.Changeset.for_create(:create, %{name: "User 2"}) - |> AshPostgres.Test.Api.create!() + |> Ash.create!() channel_member_1 = AshPostgres.Test.ComplexCalculations.ChannelMember |> Ash.Changeset.new() |> Ash.Changeset.manage_relationship(:channel, channel, type: :append) |> Ash.Changeset.manage_relationship(:user, user_1, type: :append) - |> AshPostgres.Test.ComplexCalculations.Api.create!() + |> Ash.create!() channel_member_2 = AshPostgres.Test.ComplexCalculations.ChannelMember |> Ash.Changeset.new() |> Ash.Changeset.manage_relationship(:channel, channel, type: :append) |> Ash.Changeset.manage_relationship(:user, user_2, type: :append) - |> AshPostgres.Test.ComplexCalculations.Api.create!() + |> Ash.create!() channel = channel - |> AshPostgres.Test.ComplexCalculations.Api.load!([ + |> Ash.load!([ :first_member, :second_member ]) @@ -104,13 +104,13 @@ defmodule AshPostgres.Test.ComplexCalculationsTest do channel = channel - |> AshPostgres.Test.ComplexCalculations.Api.load!(:name, actor: user_1) + |> Ash.load!(:name, actor: user_1) assert channel.name == user_1.name channel = channel - |> AshPostgres.Test.ComplexCalculations.Api.load!(:name, actor: user_2) + |> Ash.load!(:name, actor: user_2) assert channel.name == user_2.name end @@ -119,31 +119,31 @@ defmodule AshPostgres.Test.ComplexCalculationsTest do dm_channel = AshPostgres.Test.ComplexCalculations.DMChannel |> Ash.Changeset.new() - |> AshPostgres.Test.ComplexCalculations.Api.create!() + |> Ash.create!() user_1 = AshPostgres.Test.User |> Ash.Changeset.for_create(:create, %{name: "User 1"}) - |> AshPostgres.Test.Api.create!() + |> Ash.create!() user_2 = AshPostgres.Test.User |> Ash.Changeset.for_create(:create, %{name: "User 2"}) - |> AshPostgres.Test.Api.create!() + |> Ash.create!() channel_member_1 = AshPostgres.Test.ComplexCalculations.ChannelMember |> Ash.Changeset.for_create(:create, %{channel_id: dm_channel.id, user_id: user_1.id}) - |> AshPostgres.Test.ComplexCalculations.Api.create!() + |> Ash.create!() channel_member_2 = AshPostgres.Test.ComplexCalculations.ChannelMember |> Ash.Changeset.for_create(:create, %{channel_id: dm_channel.id, user_id: user_2.id}) - |> AshPostgres.Test.ComplexCalculations.Api.create!() + |> Ash.create!() dm_channel = dm_channel - |> AshPostgres.Test.ComplexCalculations.Api.load!([ + |> Ash.load!([ :first_member, :second_member ]) @@ -153,24 +153,24 @@ defmodule AshPostgres.Test.ComplexCalculationsTest do dm_channel = dm_channel - |> AshPostgres.Test.ComplexCalculations.Api.load!(:name, actor: user_1) + |> Ash.load!(:name, actor: user_1) assert dm_channel.name == user_1.name dm_channel = dm_channel - |> AshPostgres.Test.ComplexCalculations.Api.load!(:name, actor: user_2) + |> Ash.load!(:name, actor: user_2) assert dm_channel.name == user_2.name channels = AshPostgres.Test.ComplexCalculations.Channel |> Ash.Query.for_read(:read) - |> AshPostgres.Test.ComplexCalculations.Api.read!() + |> Ash.read!() channels = channels - |> AshPostgres.Test.ComplexCalculations.Api.load!([dm_channel: :name], + |> Ash.load!([dm_channel: :name], actor: user_1 ) @@ -180,7 +180,7 @@ defmodule AshPostgres.Test.ComplexCalculationsTest do channel = channel - |> AshPostgres.Test.ComplexCalculations.Api.load!([:dm_name, :foo], actor: user_2) + |> Ash.load!([:dm_name, :foo], actor: user_2) assert channel.dm_name == user_2.name end @@ -188,92 +188,92 @@ defmodule AshPostgres.Test.ComplexCalculationsTest do test "calculations with parent filters can be filtered on themselves" do AshPostgres.Test.ComplexCalculations.DMChannel |> Ash.Changeset.new() - |> AshPostgres.Test.ComplexCalculations.Api.create!() + |> Ash.create!() assert [%{foo: "foobar"}] = AshPostgres.Test.ComplexCalculations.Channel |> Ash.Query.filter(foo == "foobar") - |> AshPostgres.Test.ComplexCalculations.Api.read!(load: :foo) + |> Ash.read!(load: :foo) end test "calculations with aggregates can be referenced from aggregates" do author = AshPostgres.Test.Author - |> Ash.Changeset.new(%{first_name: "is", last_name: "match"}) - |> AshPostgres.Test.Api.create!() + |> Ash.Changeset.for_create(:create, %{first_name: "is", last_name: "match"}) + |> Ash.create!() AshPostgres.Test.Post - |> Ash.Changeset.new(%{title: "match"}) + |> Ash.Changeset.for_create(:create, %{title: "match"}) |> Ash.Changeset.manage_relationship(:author, author, type: :append_and_remove) - |> AshPostgres.Test.Api.create!() + |> Ash.create!() assert [%{author_count_of_posts: 1}] = AshPostgres.Test.Post |> Ash.Query.load(:author_count_of_posts) - |> AshPostgres.Test.Api.read!() + |> Ash.read!() assert [%{author_count_of_posts: 1}] = AshPostgres.Test.Post - |> AshPostgres.Test.Api.read!() - |> AshPostgres.Test.Api.load!(:author_count_of_posts) + |> Ash.read!() + |> Ash.load!(:author_count_of_posts) assert [_] = AshPostgres.Test.Post |> Ash.Query.filter(author_count_of_posts == 1) - |> AshPostgres.Test.Api.read!() + |> Ash.read!() end test "calculations can reference aggregates from optimizable first aggregates" do author = AshPostgres.Test.Author - |> Ash.Changeset.new(%{first_name: "is", last_name: "match"}) - |> AshPostgres.Test.Api.create!() + |> Ash.Changeset.for_create(:create, %{first_name: "is", last_name: "match"}) + |> Ash.create!() AshPostgres.Test.Post - |> Ash.Changeset.new(%{title: "match"}) + |> Ash.Changeset.for_create(:create, %{title: "match"}) |> Ash.Changeset.manage_relationship(:author, author, type: :append_and_remove) - |> AshPostgres.Test.Api.create!() + |> Ash.create!() assert [%{author_count_of_posts_agg: 1}] = AshPostgres.Test.Post |> Ash.Query.load(:author_count_of_posts_agg) - |> AshPostgres.Test.Api.read!() + |> Ash.read!() assert [%{author_count_of_posts_agg: 1}] = AshPostgres.Test.Post - |> AshPostgres.Test.Api.read!() - |> AshPostgres.Test.Api.load!(:author_count_of_posts_agg) + |> Ash.read!() + |> Ash.load!(:author_count_of_posts_agg) assert [_] = AshPostgres.Test.Post |> Ash.Query.filter(author_count_of_posts_agg == 1) - |> AshPostgres.Test.Api.read!() + |> Ash.read!() end test "calculations can reference aggregates from non optimizable aggregates" do author = AshPostgres.Test.Author - |> Ash.Changeset.new(%{first_name: "is", last_name: "match"}) - |> AshPostgres.Test.Api.create!() + |> Ash.Changeset.for_create(:create, %{first_name: "is", last_name: "match"}) + |> Ash.create!() AshPostgres.Test.Post - |> Ash.Changeset.new(%{title: "match"}) + |> Ash.Changeset.for_create(:create, %{title: "match"}) |> Ash.Changeset.manage_relationship(:author, author, type: :append_and_remove) - |> AshPostgres.Test.Api.create!() + |> Ash.create!() assert [%{sum_of_author_count_of_posts: 1}] = AshPostgres.Test.Post |> Ash.Query.load(:sum_of_author_count_of_posts) - |> AshPostgres.Test.Api.read!() + |> Ash.read!() assert [%{sum_of_author_count_of_posts: 1}] = AshPostgres.Test.Post - |> AshPostgres.Test.Api.read!() - |> AshPostgres.Test.Api.load!(:sum_of_author_count_of_posts) + |> Ash.read!() + |> Ash.load!(:sum_of_author_count_of_posts) assert [_] = AshPostgres.Test.Post |> Ash.Query.filter(sum_of_author_count_of_posts == 1) - |> AshPostgres.Test.Api.read!() + |> Ash.read!() end end diff --git a/test/composite_type_test.exs b/test/composite_type_test.exs index 4f7e6a9..b1a3990 100644 --- a/test/composite_type_test.exs +++ b/test/composite_type_test.exs @@ -1,13 +1,13 @@ defmodule AshPostgres.Test.CompositeTypeTest do use AshPostgres.RepoCase - alias AshPostgres.Test.{Api, Post} + alias AshPostgres.Test.Post require Ash.Query test "can be cast and stored" do post = Post |> Ash.Changeset.for_create(:create, %{title: "locked", composite_point: %{x: 1, y: 2}}) - |> Api.create!() + |> Ash.create!() assert post.composite_point.x == 1 assert post.composite_point.y == 2 @@ -17,22 +17,22 @@ defmodule AshPostgres.Test.CompositeTypeTest do post = Post |> Ash.Changeset.for_create(:create, %{title: "locked", composite_point: %{x: 1, y: 2}}) - |> Api.create!() + |> Ash.create!() post_id = post.id - assert %{id: ^post_id} = Post |> Ash.Query.filter(composite_point[:x] == 1) |> Api.read_one!() - refute Post |> Ash.Query.filter(composite_point[:x] == 2) |> Api.read_one!() + assert %{id: ^post_id} = Post |> Ash.Query.filter(composite_point[:x] == 1) |> Ash.read_one!() + refute Post |> Ash.Query.filter(composite_point[:x] == 2) |> Ash.read_one!() end test "composite types can be constructed" do Post |> Ash.Changeset.for_create(:create, %{title: "locked", composite_point: %{x: 1, y: 2}}) - |> Api.create!() + |> Ash.create!() assert %{composite_origin: %{x: 0, y: 0}} = Post |> Ash.Query.load(:composite_origin) - |> Api.read_one!() + |> Ash.read_one!() end end diff --git a/test/constraint_test.exs b/test/constraint_test.exs index dd3b187..b2ec9fb 100644 --- a/test/constraint_test.exs +++ b/test/constraint_test.exs @@ -1,15 +1,15 @@ defmodule AshPostgres.ConstraintTest do @moduledoc false use AshPostgres.RepoCase, async: false - alias AshPostgres.Test.{Api, Post} + alias AshPostgres.Test.Post require Ash.Query test "constraint messages are properly raised" do assert_raise Ash.Error.Invalid, ~r/yo, bad price/, fn -> Post - |> Ash.Changeset.new(%{title: "title", price: -1}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title", price: -1}) + |> Ash.create!() end end end diff --git a/test/custom_index_test.exs b/test/custom_index_test.exs index 4c721a4..1b02181 100644 --- a/test/custom_index_test.exs +++ b/test/custom_index_test.exs @@ -1,24 +1,28 @@ defmodule AshPostgres.Test.CustomIndexTest do use AshPostgres.RepoCase, async: false - alias AshPostgres.Test.{Api, Post} + alias AshPostgres.Test.Post require Ash.Query test "unique constraint errors are properly caught" do Post - |> Ash.Changeset.new(%{title: "first", uniq_custom_one: "what", uniq_custom_two: "what2"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{ + title: "first", + uniq_custom_one: "what", + uniq_custom_two: "what2" + }) + |> Ash.create!() assert_raise Ash.Error.Invalid, ~r/Invalid value provided for uniq_custom_one: dude what the heck/, fn -> Post - |> Ash.Changeset.new(%{ + |> Ash.Changeset.for_create(:create, %{ title: "first", uniq_custom_one: "what", uniq_custom_two: "what2" }) - |> Api.create!() + |> Ash.create!() end end end diff --git a/test/distinct_test.exs b/test/distinct_test.exs index 1f77997..bbc9a1c 100644 --- a/test/distinct_test.exs +++ b/test/distinct_test.exs @@ -1,26 +1,26 @@ defmodule AshPostgres.DistinctTest do @moduledoc false use AshPostgres.RepoCase, async: false - alias AshPostgres.Test.{Api, Post} + alias AshPostgres.Test.Post require Ash.Query setup do Post - |> Ash.Changeset.new(%{title: "title", score: 1}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title", score: 1}) + |> Ash.create!() Post - |> Ash.Changeset.new(%{title: "title", score: 1}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title", score: 1}) + |> Ash.create!() Post - |> Ash.Changeset.new(%{title: "foo", score: 2}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "foo", score: 2}) + |> Ash.create!() Post - |> Ash.Changeset.new(%{title: "foo", score: 2}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "foo", score: 2}) + |> Ash.create!() :ok end @@ -30,7 +30,7 @@ defmodule AshPostgres.DistinctTest do Post |> Ash.Query.distinct(:title) |> Ash.Query.sort(:title) - |> Api.read!() + |> Ash.read!() assert [%{title: "foo"}, %{title: "title"}] = results end @@ -40,7 +40,7 @@ defmodule AshPostgres.DistinctTest do Post |> Ash.Query.distinct(:title) |> Ash.Query.sort(title: :desc) - |> Api.read!() + |> Ash.read!() assert [%{title: "title"}, %{title: "foo"}] = results end @@ -51,7 +51,7 @@ defmodule AshPostgres.DistinctTest do |> Ash.Query.distinct(:title) |> Ash.Query.sort(id: :desc) |> Ash.Query.limit(3) - |> Api.read!() + |> Ash.read!() assert [_, _] = results end @@ -62,7 +62,7 @@ defmodule AshPostgres.DistinctTest do |> Ash.Query.distinct(:title) |> Ash.Query.sort(id: :desc) |> Ash.Query.limit(3) - |> Api.read!() + |> Ash.read!() assert [_, _] = results end @@ -73,7 +73,7 @@ defmodule AshPostgres.DistinctTest do |> Ash.Query.distinct(:title) |> Ash.Query.sort(id: :desc) |> Ash.Query.limit(1) - |> Api.read!() + |> Ash.read!() assert [_] = results end @@ -84,7 +84,7 @@ defmodule AshPostgres.DistinctTest do |> Ash.Query.distinct(:negative_score) |> Ash.Query.sort(:negative_score) |> Ash.Query.load(:negative_score) - |> Api.read!() + |> Ash.read!() assert [ %{title: "foo", negative_score: -2}, @@ -96,7 +96,7 @@ defmodule AshPostgres.DistinctTest do |> Ash.Query.distinct(:negative_score) |> Ash.Query.sort(negative_score: :desc) |> Ash.Query.load(:negative_score) - |> Api.read!() + |> Ash.read!() assert [ %{title: "title", negative_score: -1}, @@ -108,7 +108,7 @@ defmodule AshPostgres.DistinctTest do |> Ash.Query.distinct(:negative_score) |> Ash.Query.sort(:title) |> Ash.Query.load(:negative_score) - |> Api.read!() + |> Ash.read!() assert [ %{title: "foo", negative_score: -2}, @@ -118,29 +118,29 @@ defmodule AshPostgres.DistinctTest do test "distinct, join filters and sort can be combined" do Post - |> Ash.Changeset.new(%{title: "a", score: 2}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "a", score: 2}) + |> Ash.create!() Post - |> Ash.Changeset.new(%{title: "a", score: 1}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "a", score: 1}) + |> Ash.create!() assert [] = Post |> Ash.Query.distinct(:negative_score) |> Ash.Query.filter(author.first_name == "a") |> Ash.Query.sort(:negative_score) - |> Api.read!() + |> Ash.read!() end test "distinct sort is applied" do Post - |> Ash.Changeset.new(%{title: "a", score: 2}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "a", score: 2}) + |> Ash.create!() Post - |> Ash.Changeset.new(%{title: "a", score: 1}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "a", score: 1}) + |> Ash.create!() results = Post @@ -148,7 +148,7 @@ defmodule AshPostgres.DistinctTest do |> Ash.Query.distinct_sort(:title) |> Ash.Query.sort(:negative_score) |> Ash.Query.load(:negative_score) - |> Api.read!() + |> Ash.read!() assert [ %{title: "a", negative_score: -2}, @@ -161,7 +161,7 @@ defmodule AshPostgres.DistinctTest do |> Ash.Query.distinct_sort(title: :desc) |> Ash.Query.sort(:negative_score) |> Ash.Query.load(:negative_score) - |> Api.read!() + |> Ash.read!() assert [ %{title: "foo", negative_score: -2}, @@ -173,7 +173,7 @@ defmodule AshPostgres.DistinctTest do results = Post |> Ash.Query.distinct(:title) - |> Api.read!() + |> Ash.read!() assert [_, _] = results end diff --git a/test/embeddable_resource_test.exs b/test/embeddable_resource_test.exs index 2201acb..4edb090 100644 --- a/test/embeddable_resource_test.exs +++ b/test/embeddable_resource_test.exs @@ -1,34 +1,34 @@ defmodule AshPostgres.EmbeddableResourceTest do @moduledoc false use AshPostgres.RepoCase, async: false - alias AshPostgres.Test.{Api, Author, Bio, Post} + alias AshPostgres.Test.{Author, Bio, Post} require Ash.Query setup do post = Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() %{post: post} end test "calculations can load json", %{post: post} do assert %{calc_returning_json: %AshPostgres.Test.Money{amount: 100, currency: :usd}} = - Api.load!(post, :calc_returning_json) + Ash.load!(post, :calc_returning_json) end test "embeds with list attributes set to nil are loaded as nil" do - post = + author = Author - |> Ash.Changeset.new(%{bio: %Bio{list_of_strings: nil}}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{bio: %Bio{list_of_strings: nil}}) + |> Ash.create!() - assert is_nil(post.bio.list_of_strings) + assert is_nil(author.bio.list_of_strings) - post = Api.reload!(post) + author = Ash.reload!(author) - assert is_nil(post.bio.list_of_strings) + assert is_nil(author.bio.list_of_strings) end end diff --git a/test/enum_test.exs b/test/enum_test.exs index 9ee180a..537944c 100644 --- a/test/enum_test.exs +++ b/test/enum_test.exs @@ -1,13 +1,13 @@ defmodule AshPostgres.EnumTest do @moduledoc false use AshPostgres.RepoCase, async: false - alias AshPostgres.Test.{Api, Post} + alias AshPostgres.Test.Post require Ash.Query test "valid values are properly inserted" do Post - |> Ash.Changeset.new(%{title: "title", status: :open}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title", status: :open}) + |> Ash.create!() end end diff --git a/test/error_expr_test.exs b/test/error_expr_test.exs index 9e9b565..a45c1a4 100644 --- a/test/error_expr_test.exs +++ b/test/error_expr_test.exs @@ -1,28 +1,28 @@ defmodule AshPostgres.ErrorExprTest do use AshPostgres.RepoCase, async: false - alias AshPostgres.Test.{Api, Post} + alias AshPostgres.Test.Post require Ash.Query import Ash.Expr test "exceptions in filters are treated as regular Ash exceptions" do Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() assert_raise Ash.Error.Invalid, ~r/this is bad!/, fn -> Post |> Ash.Query.filter( error(Ash.Error.Query.InvalidFilterValue, message: "this is bad!", value: 10) ) - |> Api.read!() + |> Ash.read!() end end test "exceptions in calculations are treated as regular Ash exceptions" do Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() assert_raise Ash.Error.Invalid, ~r/this is bad!/, fn -> Post @@ -31,15 +31,15 @@ defmodule AshPostgres.ErrorExprTest do expr(error(Ash.Error.Query.InvalidFilterValue, message: "this is bad!", value: 10)), :string ) - |> Api.read!() + |> Ash.read!() |> Enum.map(& &1.calculations) end end test "exceptions in calculations are treated as regular Ash exceptions in transactions" do Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() assert_raise Ash.Error.Invalid, ~r/this is bad!/, fn -> AshPostgres.TestRepo.transaction!(fn -> @@ -49,7 +49,7 @@ defmodule AshPostgres.ErrorExprTest do expr(error(Ash.Error.Query.InvalidFilterValue, message: "this is bad!", value: 10)), :string ) - |> Api.read!() + |> Ash.read!() |> Enum.map(& &1.calculations) end) end diff --git a/test/filter_field_policy_test.exs b/test/filter_field_policy_test.exs index 35b29e5..a69f242 100644 --- a/test/filter_field_policy_test.exs +++ b/test/filter_field_policy_test.exs @@ -1,7 +1,7 @@ defmodule FilterFieldPolicyTest do use AshPostgres.RepoCase, async: false - alias AshPostgres.Test.{Api, Organization, Post, User} + alias AshPostgres.Test.{Organization, Post, User} require Ash.Query @@ -9,15 +9,15 @@ defmodule FilterFieldPolicyTest do organization = Organization |> Ash.Changeset.for_create(:create, %{name: "test_org"}) - |> Api.create!() + |> Ash.create!() User |> Ash.Changeset.for_create(:create, %{organization_id: organization.id, name: "foo bar"}) - |> Api.create!() + |> Ash.create!() Post |> Ash.Changeset.for_create(:create, %{organization_id: organization.id}) - |> Api.create!() + |> Ash.create!() filter = Ash.Filter.parse_input!(Post, %{organization: %{name: %{ilike: "%org"}}}) @@ -25,7 +25,7 @@ defmodule FilterFieldPolicyTest do Post |> Ash.Query.do_filter(filter) |> Ash.Query.for_read(:allow_any) - |> Api.read!(actor: %{id: "test"}) + |> Ash.read!(actor: %{id: "test"}) filter = Ash.Filter.parse_input!(Post, %{organization: %{users: %{name: %{ilike: "%bar"}}}}) @@ -33,6 +33,6 @@ defmodule FilterFieldPolicyTest do Post |> Ash.Query.do_filter(filter) |> Ash.Query.for_read(:allow_any) - |> Api.read!(actor: %{id: "test"}) + |> Ash.read!(actor: %{id: "test"}) end end diff --git a/test/filter_test.exs b/test/filter_test.exs index bc535bd..199c35a 100644 --- a/test/filter_test.exs +++ b/test/filter_test.exs @@ -1,20 +1,21 @@ defmodule AshPostgres.FilterTest do use AshPostgres.RepoCase, async: false - alias AshPostgres.Test.{Api, Author, Comment, Post} + alias AshPostgres.Test.{Author, Comment, Post} + alias AshPostgres.Test.ComplexCalculations.{Channel, ChannelMember} require Ash.Query describe "with no filter applied" do test "with no data" do - assert [] = Api.read!(Post) + assert [] = Ash.read!(Post) end test "with data" do Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() - assert [%Post{title: "title"}] = Api.read!(Post) + assert [%Post{title: "title"}] = Ash.read!(Post) end end @@ -23,7 +24,7 @@ defmodule AshPostgres.FilterTest do assert_raise Ash.Error.Invalid, fn -> Post |> Ash.Query.filter(id == "foo") - |> Api.read!() + |> Ash.read!() end end end @@ -41,7 +42,7 @@ defmodule AshPostgres.FilterTest do assert_raise Ash.Error.Query.InvalidExpression, fn -> Post |> Ash.Query.filter(category == "blah") - |> Api.read!() + |> Ash.read!() end end end @@ -51,33 +52,33 @@ defmodule AshPostgres.FilterTest do results = Post |> Ash.Query.filter(title == "title") - |> Api.read!() + |> Ash.read!() assert [] = results end test "with data that matches" do Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() results = Post |> Ash.Query.filter(title == "title") - |> Api.read!() + |> Ash.read!() assert [%Post{title: "title"}] = results end test "with some data that matches and some data that doesnt" do Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() results = Post |> Ash.Query.filter(title == "no_title") - |> Api.read!() + |> Ash.read!() assert [] = results end @@ -85,18 +86,18 @@ defmodule AshPostgres.FilterTest do test "with related data that doesn't match" do post = Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "not match"}) + |> Ash.Changeset.for_create(:create, %{title: "not match"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() results = Post |> Ash.Query.filter(comments.title == "match") - |> Api.read!() + |> Ash.read!() assert [] = results end @@ -104,31 +105,31 @@ defmodule AshPostgres.FilterTest do test "with related data two steps away that matches" do author = Author - |> Ash.Changeset.new(%{first_name: "match"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{first_name: "match"}) + |> Ash.create!() post = Post - |> Ash.Changeset.new(%{title: "title"}) + |> Ash.Changeset.for_create(:create, %{title: "title"}) |> Ash.Changeset.manage_relationship(:author, author, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() Post - |> Ash.Changeset.new(%{title: "title2"}) + |> Ash.Changeset.for_create(:create, %{title: "title2"}) |> Ash.Changeset.manage_relationship(:linked_posts, [post], type: :append_and_remove) |> Ash.Changeset.manage_relationship(:author, author, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "not match"}) + |> Ash.Changeset.for_create(:create, %{title: "not match"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) |> Ash.Changeset.manage_relationship(:author, author, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() results = Comment |> Ash.Query.filter(author.posts.linked_posts.title == "title") - |> Api.read!() + |> Ash.read!() assert [_] = results end @@ -136,18 +137,18 @@ defmodule AshPostgres.FilterTest do test "with related data that does match" do post = Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "match"}) + |> Ash.Changeset.for_create(:create, %{title: "match"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() results = Post |> Ash.Query.filter(comments.title == "match") - |> Api.read!() + |> Ash.read!() assert [%Post{title: "title"}] = results end @@ -155,23 +156,23 @@ defmodule AshPostgres.FilterTest do test "with related data that does and doesn't match" do post = Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "match"}) + |> Ash.Changeset.for_create(:create, %{title: "match"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "not match"}) + |> Ash.Changeset.for_create(:create, %{title: "not match"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() results = Post |> Ash.Query.filter(comments.title == "match") - |> Api.read!() + |> Ash.read!() assert [%Post{title: "title"}] = results end @@ -180,22 +181,22 @@ defmodule AshPostgres.FilterTest do describe "in" do test "it properly filters" do Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() Post - |> Ash.Changeset.new(%{title: "title1"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title1"}) + |> Ash.create!() Post - |> Ash.Changeset.new(%{title: "title2"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title2"}) + |> Ash.create!() assert [%Post{title: "title1"}, %Post{title: "title2"}] = Post |> Ash.Query.filter(title in ["title1", "title2"]) |> Ash.Query.sort(title: :asc) - |> Api.read!() + |> Ash.read!() end end @@ -204,37 +205,37 @@ defmodule AshPostgres.FilterTest do results = Post |> Ash.Query.filter(title == "title" or score == 1) - |> Api.read!() + |> Ash.read!() assert [] = results end test "with data that doesn't match" do Post - |> Ash.Changeset.new(%{title: "no title", score: 2}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "no title", score: 2}) + |> Ash.create!() results = Post |> Ash.Query.filter(title == "title" or score == 1) - |> Api.read!() + |> Ash.read!() assert [] = results end test "with data that matches both conditions" do Post - |> Ash.Changeset.new(%{title: "title", score: 0}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title", score: 0}) + |> Ash.create!() Post - |> Ash.Changeset.new(%{score: 1, title: "nothing"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{score: 1, title: "nothing"}) + |> Ash.create!() results = Post |> Ash.Query.filter(title == "title" or score == 1) - |> Api.read!() + |> Ash.read!() |> Enum.sort_by(& &1.score) assert [%Post{title: "title", score: 0}, %Post{title: "nothing", score: 1}] = results @@ -242,17 +243,17 @@ defmodule AshPostgres.FilterTest do test "with data that matches one condition and data that matches nothing" do Post - |> Ash.Changeset.new(%{title: "title", score: 0}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title", score: 0}) + |> Ash.create!() Post - |> Ash.Changeset.new(%{score: 2, title: "nothing"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{score: 2, title: "nothing"}) + |> Ash.create!() results = Post |> Ash.Query.filter(title == "title" or score == 1) - |> Api.read!() + |> Ash.read!() |> Enum.sort_by(& &1.score) assert [%Post{title: "title", score: 0}] = results @@ -261,18 +262,18 @@ defmodule AshPostgres.FilterTest do test "with related data in an or statement that matches, while basic filter doesn't match" do post = Post - |> Ash.Changeset.new(%{title: "doesn't match"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "doesn't match"}) + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "match"}) + |> Ash.Changeset.for_create(:create, %{title: "match"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() results = Post |> Ash.Query.filter(title == "match" or comments.title == "match") - |> Api.read!() + |> Ash.read!() assert [%Post{title: "doesn't match"}] = results end @@ -280,18 +281,18 @@ defmodule AshPostgres.FilterTest do test "with related data in an or statement that doesn't match, while basic filter does match" do post = Post - |> Ash.Changeset.new(%{title: "match"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "match"}) + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "doesn't match"}) + |> Ash.Changeset.for_create(:create, %{title: "doesn't match"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() results = Post |> Ash.Query.filter(title == "match" or comments.title == "match") - |> Api.read!() + |> Ash.read!() assert [%Post{title: "match"}] = results end @@ -299,25 +300,25 @@ defmodule AshPostgres.FilterTest do test "with related data and an inner join condition" do post = Post - |> Ash.Changeset.new(%{title: "match"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "match"}) + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "match"}) + |> Ash.Changeset.for_create(:create, %{title: "match"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() results = Post |> Ash.Query.filter(title == comments.title) - |> Api.read!() + |> Ash.read!() assert [%Post{title: "match"}] = results results = Post |> Ash.Query.filter(title != comments.title) - |> Api.read!() + |> Ash.read!() assert [] = results end @@ -329,13 +330,13 @@ defmodule AshPostgres.FilterTest do |> Ash.Changeset.for_create(:create, bio: %{title: "Dr.", bio: "Strange", years_of_experience: 10} ) - |> Api.create!() + |> Ash.create!() Author |> Ash.Changeset.for_create(:create, bio: %{title: "Highlander", bio: "There can be only one."} ) - |> Api.create!() + |> Ash.create!() :ok end @@ -344,151 +345,151 @@ defmodule AshPostgres.FilterTest do assert [%{bio: %{title: "Dr."}}] = Author |> Ash.Query.filter(bio[:title] == "Dr.") - |> Api.read!() + |> Ash.read!() end test "works using simple equality for integers" do assert [%{bio: %{title: "Dr."}}] = Author |> Ash.Query.filter(bio[:years_of_experience] == 10) - |> Api.read!() + |> Ash.read!() end test "works using an expression" do assert [%{bio: %{title: "Highlander"}}] = Author |> Ash.Query.filter(contains(type(bio[:bio], :string), "only one.")) - |> Api.read!() + |> Ash.read!() end test "calculations that use embeds can be filtered on" do assert [%{bio: %{title: "Dr."}}] = Author |> Ash.Query.filter(title == "Dr.") - |> Api.read!() + |> Ash.read!() end end describe "basic expressions" do test "basic expressions work" do Post - |> Ash.Changeset.new(%{title: "match", score: 4}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "match", score: 4}) + |> Ash.create!() Post - |> Ash.Changeset.new(%{title: "non_match", score: 2}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "non_match", score: 2}) + |> Ash.create!() assert [%{title: "match"}] = Post |> Ash.Query.filter(score + 1 == 5) - |> Api.read!() + |> Ash.read!() end end describe "case insensitive fields" do test "it matches case insensitively" do Post - |> Ash.Changeset.new(%{title: "match", category: "FoObAr"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "match", category: "FoObAr"}) + |> Ash.create!() Post - |> Ash.Changeset.new(%{category: "bazbuz"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{category: "bazbuz"}) + |> Ash.create!() assert [%{title: "match"}] = Post |> Ash.Query.filter(category == "fOoBaR") - |> Api.read!() + |> Ash.read!() end end describe "contains/2" do test "it works when it matches" do Post - |> Ash.Changeset.new(%{title: "match"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "match"}) + |> Ash.create!() Post - |> Ash.Changeset.new(%{title: "bazbuz"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "bazbuz"}) + |> Ash.create!() assert [%{title: "match"}] = Post |> Ash.Query.filter(contains(title, "atc")) - |> Api.read!() + |> Ash.read!() end test "it works when a case insensitive string is provided as a value" do Post - |> Ash.Changeset.new(%{title: "match"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "match"}) + |> Ash.create!() Post - |> Ash.Changeset.new(%{title: "bazbuz"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "bazbuz"}) + |> Ash.create!() assert [%{title: "match"}] = Post |> Ash.Query.filter(contains(title, ^%Ash.CiString{string: "ATC"})) - |> Api.read!() + |> Ash.read!() end test "it works on a case insensitive column" do Post - |> Ash.Changeset.new(%{category: "match"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{category: "match"}) + |> Ash.create!() Post - |> Ash.Changeset.new(%{category: "bazbuz"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{category: "bazbuz"}) + |> Ash.create!() assert [%{category: %Ash.CiString{string: "match"}}] = Post |> Ash.Query.filter(contains(category, ^"ATC")) - |> Api.read!() + |> Ash.read!() end test "it works on a case insensitive calculation" do Post - |> Ash.Changeset.new(%{category: "match"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{category: "match"}) + |> Ash.create!() Post - |> Ash.Changeset.new(%{category: "bazbuz"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{category: "bazbuz"}) + |> Ash.create!() assert [%{category: %Ash.CiString{string: "match"}}] = Post |> Ash.Query.filter(contains(category_label, ^"ATC")) - |> Api.read!() + |> Ash.read!() end test "it works on related values" do post = Post - |> Ash.Changeset.new(%{title: "match"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "match"}) + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "abba"}) + |> Ash.Changeset.for_create(:create, %{title: "abba"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() post2 = Post - |> Ash.Changeset.new(%{title: "no_match"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "no_match"}) + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "acca"}) + |> Ash.Changeset.for_create(:create, %{title: "acca"}) |> Ash.Changeset.manage_relationship(:post, post2, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() assert [%{title: "match"}] = Post |> Ash.Query.filter(contains(comments.title, ^"bb")) - |> Api.read!() + |> Ash.read!() end end @@ -496,46 +497,46 @@ defmodule AshPostgres.FilterTest do test "it works with a list attribute" do author1 = Author - |> Ash.Changeset.new(%{badges: [:author_of_the_year]}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{badges: [:author_of_the_year]}) + |> Ash.create!() _author2 = Author - |> Ash.Changeset.new(%{badges: []}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{badges: []}) + |> Ash.create!() author1_id = author1.id assert [%{id: ^author1_id}] = Author |> Ash.Query.filter(length(badges) > 0) - |> Api.read!() + |> Ash.read!() end test "it works with nil" do author1 = Author - |> Ash.Changeset.new(%{badges: [:author_of_the_year]}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{badges: [:author_of_the_year]}) + |> Ash.create!() _author2 = Author |> Ash.Changeset.new() - |> Api.create!() + |> Ash.create!() author1_id = author1.id assert [%{id: ^author1_id}] = Author |> Ash.Query.filter(length(badges || []) > 0) - |> Api.read!() + |> Ash.read!() end test "it works with a list" do author1 = Author |> Ash.Changeset.new() - |> Api.create!() + |> Ash.create!() author1_id = author1.id @@ -544,23 +545,23 @@ defmodule AshPostgres.FilterTest do assert [%{id: ^author1_id}] = Author |> Ash.Query.filter(length(^explicit_list) > 0) - |> Api.read!() + |> Ash.read!() assert [] = Author |> Ash.Query.filter(length(^explicit_list) > 1) - |> Api.read!() + |> Ash.read!() end test "it raises with bad values" do Author |> Ash.Changeset.new() - |> Api.create!() + |> Ash.create!() assert_raise(Ash.Error.Unknown, fn -> Author |> Ash.Query.filter(length(first_name) > 0) - |> Api.read!() + |> Ash.read!() end) end end @@ -569,116 +570,116 @@ defmodule AshPostgres.FilterTest do test "it works with single relationships" do post = Post - |> Ash.Changeset.new(%{title: "match"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "match"}) + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "abba"}) + |> Ash.Changeset.for_create(:create, %{title: "abba"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() post2 = Post - |> Ash.Changeset.new(%{title: "no_match"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "no_match"}) + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "acca"}) + |> Ash.Changeset.for_create(:create, %{title: "acca"}) |> Ash.Changeset.manage_relationship(:post, post2, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() assert [%{title: "match"}] = Post |> Ash.Query.filter(exists(comments, title == ^"abba")) - |> Api.read!() + |> Ash.read!() end test "it works with many to many relationships" do post = Post - |> Ash.Changeset.new(%{title: "a"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "a"}) + |> Ash.create!() Post - |> Ash.Changeset.new(%{title: "b"}) + |> Ash.Changeset.for_create(:create, %{title: "b"}) |> Ash.Changeset.manage_relationship(:linked_posts, [post], type: :append_and_remove) - |> Api.create!() + |> Ash.create!() assert [%{title: "b"}] = Post |> Ash.Query.filter(exists(linked_posts, title == ^"a")) - |> Api.read!() + |> Ash.read!() end test "it works with join association relationships" do post = Post - |> Ash.Changeset.new(%{title: "a"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "a"}) + |> Ash.create!() Post - |> Ash.Changeset.new(%{title: "b"}) + |> Ash.Changeset.for_create(:create, %{title: "b"}) |> Ash.Changeset.manage_relationship(:linked_posts, [post], type: :append_and_remove) - |> Api.create!() + |> Ash.create!() assert [%{title: "b"}] = Post |> Ash.Query.filter(exists(linked_posts, title == ^"a")) - |> Api.read!() + |> Ash.read!() end test "it works with nested relationships as the path" do post = Post - |> Ash.Changeset.new(%{title: "a"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "a"}) + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "comment"}) + |> Ash.Changeset.for_create(:create, %{title: "comment"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() Post - |> Ash.Changeset.new(%{title: "b"}) + |> Ash.Changeset.for_create(:create, %{title: "b"}) |> Ash.Changeset.manage_relationship(:linked_posts, [post], type: :append_and_remove) - |> Api.create!() + |> Ash.create!() assert [%{title: "b"}] = Post |> Ash.Query.filter(exists(linked_posts.comments, title == ^"comment")) - |> Api.read!() + |> Ash.read!() end test "it works with an `at_path`" do post = Post - |> Ash.Changeset.new(%{title: "a"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "a"}) + |> Ash.create!() other_post = Post - |> Ash.Changeset.new(%{title: "other_a"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "other_a"}) + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "comment"}) + |> Ash.Changeset.for_create(:create, %{title: "comment"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "comment"}) + |> Ash.Changeset.for_create(:create, %{title: "comment"}) |> Ash.Changeset.manage_relationship(:post, other_post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() Post - |> Ash.Changeset.new(%{title: "b"}) + |> Ash.Changeset.for_create(:create, %{title: "b"}) |> Ash.Changeset.manage_relationship(:linked_posts, [post], type: :append_and_remove) - |> Api.create!() + |> Ash.create!() Post - |> Ash.Changeset.new(%{title: "b"}) + |> Ash.Changeset.for_create(:create, %{title: "b"}) |> Ash.Changeset.manage_relationship(:linked_posts, [other_post], type: :append_and_remove) - |> Api.create!() + |> Ash.create!() assert [%{title: "b"}] = Post @@ -686,7 +687,7 @@ defmodule AshPostgres.FilterTest do linked_posts.title == "a" and linked_posts.exists(comments, title == ^"comment") ) - |> Api.read!() + |> Ash.read!() assert [%{title: "b"}] = Post @@ -694,90 +695,90 @@ defmodule AshPostgres.FilterTest do linked_posts.title == "a" and linked_posts.exists(comments, title == ^"comment") ) - |> Api.read!() + |> Ash.read!() end test "it works with nested relationships inside of exists" do post = Post - |> Ash.Changeset.new(%{title: "a"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "a"}) + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "comment"}) + |> Ash.Changeset.for_create(:create, %{title: "comment"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() Post - |> Ash.Changeset.new(%{title: "b"}) + |> Ash.Changeset.for_create(:create, %{title: "b"}) |> Ash.Changeset.manage_relationship(:linked_posts, [post], type: :append_and_remove) - |> Api.create!() + |> Ash.create!() assert [%{title: "b"}] = Post |> Ash.Query.filter(exists(linked_posts, comments.title == ^"comment")) - |> Api.read!() + |> Ash.read!() end test "it works with aggregates inside of exists" do post = Post - |> Ash.Changeset.new(%{title: "a", category: "foo"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "a", category: "foo"}) + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "comment"}) + |> Ash.Changeset.for_create(:create, %{title: "comment"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() Post - |> Ash.Changeset.new(%{title: "b"}) + |> Ash.Changeset.for_create(:create, %{title: "b"}) |> Ash.Changeset.manage_relationship(:linked_posts, [post], type: :append_and_remove) - |> Api.create!() + |> Ash.create!() assert [%{title: "b"}] = Post |> Ash.Query.filter( exists(linked_posts.comments, title == ^"comment" and post_category == "foo") ) - |> Api.read!() + |> Ash.read!() end end describe "filtering on enum types" do test "it allows simple filtering" do Post - |> Ash.Changeset.new(status_enum: "open") - |> Api.create!() + |> Ash.Changeset.for_create(:create, status_enum: "open") + |> Ash.create!() assert %{status_enum: :open} = Post |> Ash.Query.filter(status_enum == ^"open") - |> Api.read_one!() + |> Ash.read_one!() end test "it allows simple filtering without casting" do Post - |> Ash.Changeset.new(status_enum_no_cast: "open") - |> Api.create!() + |> Ash.Changeset.for_create(:create, status_enum_no_cast: "open") + |> Ash.create!() assert %{status_enum_no_cast: :open} = Post |> Ash.Query.filter(status_enum_no_cast == ^"open") - |> Api.read_one!() + |> Ash.read_one!() end end describe "atom filters" do test "it works on matches" do Post - |> Ash.Changeset.new(%{title: "match"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "match"}) + |> Ash.create!() result = Post |> Ash.Query.filter(type == :sponsored) - |> Api.read!() + |> Ash.read!() assert [%Post{title: "match"}] = result end @@ -786,40 +787,40 @@ defmodule AshPostgres.FilterTest do describe "like and ilike" do test "like builds and matches" do Post - |> Ash.Changeset.new(%{title: "MaTcH"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "MaTcH"}) + |> Ash.create!() results = Post |> Ash.Query.filter(like(title, "%aTc%")) - |> Api.read!() + |> Ash.read!() assert [%Post{title: "MaTcH"}] = results results = Post |> Ash.Query.filter(like(title, "%atc%")) - |> Api.read!() + |> Ash.read!() assert [] = results end test "ilike builds and matches" do Post - |> Ash.Changeset.new(%{title: "MaTcH"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "MaTcH"}) + |> Ash.create!() results = Post |> Ash.Query.filter(ilike(title, "%aTc%")) - |> Api.read!() + |> Ash.read!() assert [%Post{title: "MaTcH"}] = results results = Post |> Ash.Query.filter(ilike(title, "%atc%")) - |> Api.read!() + |> Ash.read!() assert [%Post{title: "MaTcH"}] = results end @@ -828,26 +829,26 @@ defmodule AshPostgres.FilterTest do describe "trigram_similarity" do test "it works on matches" do Post - |> Ash.Changeset.new(%{title: "match"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "match"}) + |> Ash.create!() results = Post |> Ash.Query.filter(trigram_similarity(title, "match") > 0.9) - |> Api.read!() + |> Ash.read!() assert [%Post{title: "match"}] = results end test "it works on non-matches" do Post - |> Ash.Changeset.new(%{title: "match"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "match"}) + |> Ash.create!() results = Post |> Ash.Query.filter(trigram_similarity(title, "match") < 0.1) - |> Api.read!() + |> Ash.read!() assert [] = results end @@ -857,139 +858,136 @@ defmodule AshPostgres.FilterTest do test "double replacement works" do post = Post - |> Ash.Changeset.new(%{title: "match", score: 4}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "match", score: 4}) + |> Ash.create!() Post - |> Ash.Changeset.new(%{title: "non_match", score: 2}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "non_match", score: 2}) + |> Ash.create!() assert [%{title: "match"}] = Post |> Ash.Query.filter(fragment("? = ?", title, ^post.title)) - |> Api.read!() + |> Ash.read!() assert [] = Post |> Ash.Query.filter(fragment("? = ?", title, "nope")) - |> Api.read!() + |> Ash.read!() end end test "filtering allows filtering on list aggregates with filters" do post = Post - |> Ash.Changeset.new(%{title: "match"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "match"}) + |> Ash.create!() post_id = post.id Comment - |> Ash.Changeset.new(%{title: "match", likes: 5}) + |> Ash.Changeset.for_create(:create, %{title: "match", likes: 5}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "non_match", likes: 5}) + |> Ash.Changeset.for_create(:create, %{title: "non_match", likes: 5}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() post2 = Post - |> Ash.Changeset.new(%{title: "non_match"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "non_match"}) + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "non_match", likes: 5}) + |> Ash.Changeset.for_create(:create, %{title: "non_match", likes: 5}) |> Ash.Changeset.manage_relationship(:post, post2, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() assert [%{id: ^post_id}] = Post |> Ash.Query.filter("match" in comment_titles_with_5_likes) - |> Api.read!() + |> Ash.read!() end test "filtering allows filtering on count aggregates with filters" do post = Post - |> Ash.Changeset.new(%{title: "match"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "match"}) + |> Ash.create!() post_id = post.id Comment - |> Ash.Changeset.new(%{title: "title"}) + |> Ash.Changeset.for_create(:create, %{title: "title"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "title"}) + |> Ash.Changeset.for_create(:create, %{title: "title"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() post2 = Post - |> Ash.Changeset.new(%{title: "non_match"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "non_match"}) + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "title"}) + |> Ash.Changeset.for_create(:create, %{title: "title"}) |> Ash.Changeset.manage_relationship(:post, post2, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() assert [%{id: ^post_id}] = Post |> Ash.Query.filter(count_of_comments_that_have_a_post == 2) - |> Api.read!() + |> Ash.read!() end describe "filtering on relationships that themselves have filters" do test "it doesn't raise an error" do Comment |> Ash.Query.filter(not is_nil(popular_ratings.id)) - |> Api.read!() + |> Ash.read!() end test "it doesn't raise an error when nested" do Post |> Ash.Query.filter(not is_nil(comments.popular_ratings.id)) - |> Api.read!() + |> Ash.read!() end test "aggregates using them don't raise errors" do Comment |> Ash.Query.load(:co_popular_comments) - |> Api.read!() + |> Ash.read!() end test "filtering on aggregates using them doesn't raise errors" do Comment |> Ash.Query.filter(co_popular_comments > 1) - |> Api.read!() + |> Ash.read!() end end test "can reference related items from a relationship expression" do Post |> Ash.Query.filter(comments_with_high_rating.title == "foo") - |> Api.read!() + |> Ash.read!() end test "filter by has_one from_many?" do - alias Ash.Changeset - alias AshPostgres.Test.ComplexCalculations.{Api, Channel, ChannelMember} - [_cm1, cm2 | _] = for _ <- 1..5 do - c = Changeset.for_create(Channel, :create, %{}) |> Api.create!() - Changeset.for_create(ChannelMember, :create, %{channel_id: c.id}) |> Api.create!() + c = Ash.Changeset.for_create(Channel, :create, %{}) |> Ash.create!() + Ash.Changeset.for_create(ChannelMember, :create, %{channel_id: c.id}) |> Ash.create!() end assert Channel |> Ash.Query.for_read(:read) |> Ash.Query.filter(first_member.id != ^cm2.id) - |> Api.read!() + |> Ash.read!() |> length == 4 end end diff --git a/test/load_test.exs b/test/load_test.exs index f01e95b..079a214 100644 --- a/test/load_test.exs +++ b/test/load_test.exs @@ -1,6 +1,6 @@ defmodule AshPostgres.Test.LoadTest do use AshPostgres.RepoCase, async: false - alias AshPostgres.Test.{Api, Comment, Post, Record, TempEntity} + alias AshPostgres.Test.{Comment, Post, Record, TempEntity} require Ash.Query @@ -8,18 +8,18 @@ defmodule AshPostgres.Test.LoadTest do assert %Post{comments: %Ash.NotLoaded{type: :relationship}} = post = Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "match"}) + |> Ash.Changeset.for_create(:create, %{title: "match"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() results = Post |> Ash.Query.load(:comments) - |> Api.read!() + |> Ash.read!() assert [%Post{comments: [%{title: "match"}]}] = results end @@ -28,18 +28,18 @@ defmodule AshPostgres.Test.LoadTest do assert %Comment{post: %Ash.NotLoaded{type: :relationship}} = comment = Comment - |> Ash.Changeset.new(%{}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{}) + |> Ash.create!() Post - |> Ash.Changeset.new(%{title: "match"}) + |> Ash.Changeset.for_create(:create, %{title: "match"}) |> Ash.Changeset.manage_relationship(:comments, [comment], type: :append_and_remove) - |> Api.create!() + |> Ash.create!() results = Comment |> Ash.Query.load(:post) - |> Api.read!() + |> Ash.read!() assert [%Comment{post: %{title: "match"}}] = results end @@ -47,29 +47,29 @@ defmodule AshPostgres.Test.LoadTest do test "many_to_many loads work" do source_post = Post - |> Ash.Changeset.new(%{title: "source"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "source"}) + |> Ash.create!() destination_post = Post - |> Ash.Changeset.new(%{title: "destination"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "destination"}) + |> Ash.create!() destination_post2 = Post - |> Ash.Changeset.new(%{title: "destination"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "destination"}) + |> Ash.create!() source_post |> Ash.Changeset.new() |> Ash.Changeset.manage_relationship(:linked_posts, [destination_post, destination_post2], type: :append_and_remove ) - |> Api.update!() + |> Ash.update!() results = source_post - |> Api.load!(:linked_posts) + |> Ash.load!(:linked_posts) assert %{linked_posts: [%{title: "destination"}, %{title: "destination"}]} = results end @@ -77,29 +77,29 @@ defmodule AshPostgres.Test.LoadTest do test "many_to_many loads work when nested" do source_post = Post - |> Ash.Changeset.new(%{title: "source"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "source"}) + |> Ash.create!() destination_post = Post - |> Ash.Changeset.new(%{title: "destination"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "destination"}) + |> Ash.create!() source_post |> Ash.Changeset.new() |> Ash.Changeset.manage_relationship(:linked_posts, [destination_post], type: :append_and_remove ) - |> Api.update!() + |> Ash.update!() destination_post |> Ash.Changeset.new() |> Ash.Changeset.manage_relationship(:linked_posts, [source_post], type: :append_and_remove) - |> Api.update!() + |> Ash.update!() results = source_post - |> Api.load!(linked_posts: :linked_posts) + |> Ash.load!(linked_posts: :linked_posts) assert %{linked_posts: [%{title: "destination", linked_posts: [%{title: "source"}]}]} = results @@ -109,75 +109,75 @@ defmodule AshPostgres.Test.LoadTest do test "parent references are resolved" do post1 = Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() post2 = Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() post2_id = post2.id post3 = Post - |> Ash.Changeset.new(%{title: "no match"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "no match"}) + |> Ash.create!() assert [%{posts_with_matching_title: [%{id: ^post2_id}]}] = Post |> Ash.Query.load(:posts_with_matching_title) |> Ash.Query.filter(id == ^post1.id) - |> Api.read!() + |> Ash.read!() assert [%{posts_with_matching_title: []}] = Post |> Ash.Query.load(:posts_with_matching_title) |> Ash.Query.filter(id == ^post3.id) - |> Api.read!() + |> Ash.read!() end test "parent references work when joining for filters" do %{id: post1_id} = Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() post2 = Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() Post - |> Ash.Changeset.new(%{title: "no match"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "no match"}) + |> Ash.create!() Post - |> Ash.Changeset.new(%{title: "no match"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "no match"}) + |> Ash.create!() assert [%{id: ^post1_id}] = Post |> Ash.Query.filter(posts_with_matching_title.id == ^post2.id) - |> Api.read!() + |> Ash.read!() end test "lateral join loads (loads with limits or offsets) are supported" do assert %Post{comments: %Ash.NotLoaded{type: :relationship}} = post = Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "abc"}) + |> Ash.Changeset.for_create(:create, %{title: "abc"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "def"}) + |> Ash.Changeset.for_create(:create, %{title: "def"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() comments_query = Comment @@ -187,7 +187,7 @@ defmodule AshPostgres.Test.LoadTest do results = Post |> Ash.Query.load(comments: comments_query) - |> Api.read!() + |> Ash.read!() assert [%Post{comments: [%{title: "abc"}]}] = results @@ -199,7 +199,7 @@ defmodule AshPostgres.Test.LoadTest do results = Post |> Ash.Query.load(comments: comments_query) - |> Api.read!() + |> Ash.read!() assert [%Post{comments: [%{title: "def"}]}] = results @@ -211,7 +211,7 @@ defmodule AshPostgres.Test.LoadTest do results = Post |> Ash.Query.load(comments: comments_query) - |> Api.read!() + |> Ash.read!() assert [%Post{comments: [%{title: "def"}, %{title: "abc"}]}] = results end @@ -219,25 +219,25 @@ defmodule AshPostgres.Test.LoadTest do test "loading many to many relationships on records works without loading its join relationship when using code interface" do source_post = Post - |> Ash.Changeset.new(%{title: "source"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "source"}) + |> Ash.create!() destination_post = Post - |> Ash.Changeset.new(%{title: "abc"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "abc"}) + |> Ash.create!() destination_post2 = Post - |> Ash.Changeset.new(%{title: "def"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "def"}) + |> Ash.create!() source_post |> Ash.Changeset.new() |> Ash.Changeset.manage_relationship(:linked_posts, [destination_post, destination_post2], type: :append_and_remove ) - |> Api.update!() + |> Ash.update!() assert %{linked_posts: [_, _]} = Post.get_by_id!(source_post.id, load: [:linked_posts]) end @@ -245,25 +245,25 @@ defmodule AshPostgres.Test.LoadTest do test "lateral join loads with many to many relationships are supported" do source_post = Post - |> Ash.Changeset.new(%{title: "source"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "source"}) + |> Ash.create!() destination_post = Post - |> Ash.Changeset.new(%{title: "abc"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "abc"}) + |> Ash.create!() destination_post2 = Post - |> Ash.Changeset.new(%{title: "def"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "def"}) + |> Ash.create!() source_post |> Ash.Changeset.new() |> Ash.Changeset.manage_relationship(:linked_posts, [destination_post, destination_post2], type: :append_and_remove ) - |> Api.update!() + |> Ash.update!() linked_posts_query = Post @@ -272,7 +272,7 @@ defmodule AshPostgres.Test.LoadTest do results = source_post - |> Api.load!(linked_posts: linked_posts_query) + |> Ash.load!(linked_posts: linked_posts_query) assert %{linked_posts: [%{title: "abc"}]} = results @@ -283,7 +283,7 @@ defmodule AshPostgres.Test.LoadTest do results = source_post - |> Api.load!(linked_posts: linked_posts_query) + |> Ash.load!(linked_posts: linked_posts_query) assert %{linked_posts: [%{title: "abc"}, %{title: "def"}]} = results end @@ -291,25 +291,25 @@ defmodule AshPostgres.Test.LoadTest do test "lateral join loads with many to many relationships are supported with aggregates" do source_post = Post - |> Ash.Changeset.new(%{title: "source"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "source"}) + |> Ash.create!() destination_post = Post - |> Ash.Changeset.new(%{title: "abc"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "abc"}) + |> Ash.create!() destination_post2 = Post - |> Ash.Changeset.new(%{title: "def"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "def"}) + |> Ash.create!() source_post |> Ash.Changeset.new() |> Ash.Changeset.manage_relationship(:linked_posts, [destination_post, destination_post2], type: :append_and_remove ) - |> Api.update!() + |> Ash.update!() linked_posts_query = Post @@ -318,7 +318,7 @@ defmodule AshPostgres.Test.LoadTest do results = source_post - |> Api.load!(linked_posts: linked_posts_query) + |> Ash.load!(linked_posts: linked_posts_query) assert %{linked_posts: [%{title: "abc"}]} = results @@ -330,16 +330,18 @@ defmodule AshPostgres.Test.LoadTest do results = source_post - |> Api.load!(linked_posts: linked_posts_query) + |> Ash.load!(linked_posts: linked_posts_query) assert %{linked_posts: [%{title: "abc"}, %{title: "def"}]} = results end test "lateral join loads with read action from a custom table and schema" do - record = Record |> Ash.Changeset.new(%{full_name: "name"}) |> Api.create!() - temp_entity = TempEntity |> Ash.Changeset.new(%{full_name: "name"}) |> Api.create!() + record = Record |> Ash.Changeset.for_create(:create, %{full_name: "name"}) |> Ash.create!() - assert %{entity: entity} = Api.load!(record, :entity) + temp_entity = + TempEntity |> Ash.Changeset.for_create(:create, %{full_name: "name"}) |> Ash.create!() + + assert %{entity: entity} = Ash.load!(record, :entity) assert temp_entity.id == entity.id end diff --git a/test/lock_test.exs b/test/lock_test.exs index 36dd97f..f36c8ed 100644 --- a/test/lock_test.exs +++ b/test/lock_test.exs @@ -1,6 +1,6 @@ defmodule AshPostgres.Test.LockTest do use AshPostgres.RepoCase, async: false - alias AshPostgres.Test.{Api, Post} + alias AshPostgres.Test.Post require Ash.Query setup do @@ -17,7 +17,7 @@ defmodule AshPostgres.Test.LockTest do Post |> Ash.Changeset.for_create(:create, %{title: "locked"}) |> Ash.Changeset.set_context(%{data_layer: %{repo: AshPostgres.TestNoSandboxRepo}}) - |> Api.create!() + |> Ash.create!() task1 = Task.async(fn -> @@ -26,7 +26,7 @@ defmodule AshPostgres.Test.LockTest do |> Ash.Query.lock("FOR UPDATE NOWAIT") |> Ash.Query.set_context(%{data_layer: %{repo: AshPostgres.TestNoSandboxRepo}}) |> Ash.Query.filter(id == ^post.id) - |> Api.read!() + |> Ash.read!() :timer.sleep(1000) :ok @@ -43,7 +43,7 @@ defmodule AshPostgres.Test.LockTest do |> Ash.Query.lock("FOR UPDATE NOWAIT") |> Ash.Query.set_context(%{data_layer: %{repo: AshPostgres.TestNoSandboxRepo}}) |> Ash.Query.filter(id == ^post.id) - |> Api.read!() + |> Ash.read!() end) rescue e -> diff --git a/test/manual_relationships_test.exs b/test/manual_relationships_test.exs index 7b1b8d2..0783c94 100644 --- a/test/manual_relationships_test.exs +++ b/test/manual_relationships_test.exs @@ -1,6 +1,6 @@ defmodule AshPostgres.Test.ManualRelationshipsTest do use AshPostgres.RepoCase, async: false - alias AshPostgres.Test.{Api, Comment, Post} + alias AshPostgres.Test.{Comment, Post} require Ash.Query @@ -8,102 +8,102 @@ defmodule AshPostgres.Test.ManualRelationshipsTest do test "aggregates can be loaded with no data" do post = Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() assert %{count_of_comments_containing_title: 0} = - Api.load!(post, :count_of_comments_containing_title) + Ash.load!(post, :count_of_comments_containing_title) end test "aggregates can be loaded with data" do post = Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "title2"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title2"}) + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "title2"}) + |> Ash.Changeset.for_create(:create, %{title: "title2"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "no match"}) + |> Ash.Changeset.for_create(:create, %{title: "no match"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() assert %{count_of_comments_containing_title: 1} = - Api.load!(post, :count_of_comments_containing_title) + Ash.load!(post, :count_of_comments_containing_title) end test "relationships can be filtered on with no data" do Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() assert [] = - Post |> Ash.Query.filter(comments_containing_title.title == "title") |> Api.read!() + Post |> Ash.Query.filter(comments_containing_title.title == "title") |> Ash.read!() end test "aggregates can be filtered on with no data" do Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() - assert [] = Post |> Ash.Query.filter(count_of_comments_containing_title == 1) |> Api.read!() + assert [] = Post |> Ash.Query.filter(count_of_comments_containing_title == 1) |> Ash.read!() end test "aggregates can be filtered on with data" do post = Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "title2"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title2"}) + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "title2"}) + |> Ash.Changeset.for_create(:create, %{title: "title2"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "no match"}) + |> Ash.Changeset.for_create(:create, %{title: "no match"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() assert [_] = - Post |> Ash.Query.filter(count_of_comments_containing_title == 1) |> Api.read!() + Post |> Ash.Query.filter(count_of_comments_containing_title == 1) |> Ash.read!() end test "relationships can be filtered on with data" do post = Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "title2"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title2"}) + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "title2"}) + |> Ash.Changeset.for_create(:create, %{title: "title2"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "no match"}) + |> Ash.Changeset.for_create(:create, %{title: "no match"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() assert [_] = Post |> Ash.Query.filter(comments_containing_title.title == "title2") - |> Api.read!() + |> Ash.read!() end end @@ -111,128 +111,128 @@ defmodule AshPostgres.Test.ManualRelationshipsTest do test "aggregates can be loaded with no data" do post = Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() comment = Comment - |> Ash.Changeset.new(%{title: "no match"}) + |> Ash.Changeset.for_create(:create, %{title: "no match"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() assert %{count_of_comments_containing_title: 0} = - Api.load!(comment, :count_of_comments_containing_title) + Ash.load!(comment, :count_of_comments_containing_title) end test "aggregates can be loaded with data" do post = Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "title2"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title2"}) + |> Ash.create!() comment = Comment - |> Ash.Changeset.new(%{title: "title2"}) + |> Ash.Changeset.for_create(:create, %{title: "title2"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "no match"}) + |> Ash.Changeset.for_create(:create, %{title: "no match"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() assert %{count_of_comments_containing_title: 1} = - Api.load!(comment, :count_of_comments_containing_title) + Ash.load!(comment, :count_of_comments_containing_title) end test "aggregates can be filtered on with no data" do post = Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "no match"}) + |> Ash.Changeset.for_create(:create, %{title: "no match"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() assert [] = Comment |> Ash.Query.filter(count_of_comments_containing_title == 1) - |> Api.read!() + |> Ash.read!() end test "relationships can be filtered on with no data" do post = Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "no match"}) + |> Ash.Changeset.for_create(:create, %{title: "no match"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() assert [] = Comment |> Ash.Query.filter(post.comments_containing_title.title == "title2") - |> Api.read!() + |> Ash.read!() end test "aggregates can be filtered on with data" do post = Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "title2"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title2"}) + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "title2"}) + |> Ash.Changeset.for_create(:create, %{title: "title2"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "no match"}) + |> Ash.Changeset.for_create(:create, %{title: "no match"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() assert [_, _] = Comment |> Ash.Query.filter(count_of_comments_containing_title == 1) - |> Api.read!() + |> Ash.read!() end test "relationships can be filtered on with data" do post = Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "title2"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title2"}) + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "title2"}) + |> Ash.Changeset.for_create(:create, %{title: "title2"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "no match"}) + |> Ash.Changeset.for_create(:create, %{title: "no match"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() assert [_, _] = Comment |> Ash.Query.filter(post.comments_containing_title.title == "title2") - |> Api.read!() + |> Ash.read!() end end @@ -240,128 +240,128 @@ defmodule AshPostgres.Test.ManualRelationshipsTest do test "aggregates can be loaded with no data" do post = Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() comment = Comment - |> Ash.Changeset.new(%{title: "no match"}) + |> Ash.Changeset.for_create(:create, %{title: "no match"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() assert %{posts_for_comments_containing_title: []} = - Api.load!(comment, :posts_for_comments_containing_title) + Ash.load!(comment, :posts_for_comments_containing_title) end test "aggregates can be loaded with data" do post = Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "title2"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title2"}) + |> Ash.create!() comment = Comment - |> Ash.Changeset.new(%{title: "title2"}) + |> Ash.Changeset.for_create(:create, %{title: "title2"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "no match"}) + |> Ash.Changeset.for_create(:create, %{title: "no match"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() assert %{posts_for_comments_containing_title: ["title"]} = - Api.load!(comment, :posts_for_comments_containing_title) + Ash.load!(comment, :posts_for_comments_containing_title) end test "aggregates can be filtered on with no data" do post = Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "no match"}) + |> Ash.Changeset.for_create(:create, %{title: "no match"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() assert [] = Comment |> Ash.Query.filter("title" in posts_for_comments_containing_title) - |> Api.read!() + |> Ash.read!() end test "relationships can be filtered on with no data" do post = Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "no match"}) + |> Ash.Changeset.for_create(:create, %{title: "no match"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() assert [] = Comment |> Ash.Query.filter(post.comments_containing_title.post.title == "title") - |> Api.read!() + |> Ash.read!() end test "aggregates can be filtered on with data" do post = Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "title2"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title2"}) + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "title2"}) + |> Ash.Changeset.for_create(:create, %{title: "title2"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "no match"}) + |> Ash.Changeset.for_create(:create, %{title: "no match"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() assert [_, _] = Comment |> Ash.Query.filter(post.comments_containing_title.post.title == "title") - |> Api.read!() + |> Ash.read!() end test "relationships can be filtered on with data" do post = Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "title2"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title2"}) + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "title2"}) + |> Ash.Changeset.for_create(:create, %{title: "title2"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "no match"}) + |> Ash.Changeset.for_create(:create, %{title: "no match"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() assert [_, _] = Comment |> Ash.Query.filter(post.comments_containing_title.post.title == "title") - |> Api.read!() + |> Ash.read!() end end end diff --git a/test/manual_update_test.exs b/test/manual_update_test.exs index c41445e..e5a286c 100644 --- a/test/manual_update_test.exs +++ b/test/manual_update_test.exs @@ -4,18 +4,18 @@ defmodule AshPostgres.ManualUpdateTest do test "Manual update defined in a module to update an attribute" do post = AshPostgres.Test.Post - |> Ash.Changeset.new(%{title: "match"}) - |> AshPostgres.Test.Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "match"}) + |> Ash.create!() AshPostgres.Test.Comment - |> Ash.Changeset.new(%{title: "_"}) + |> Ash.Changeset.for_create(:create, %{title: "_"}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> AshPostgres.Test.Api.create!() + |> Ash.create!() post = post |> Ash.Changeset.for_update(:manual_update) - |> AshPostgres.Test.Api.update!() + |> Ash.update!() assert post.title == "manual" diff --git a/test/migration_generator_test.exs b/test/migration_generator_test.exs index eb0810c..751c24f 100644 --- a/test/migration_generator_test.exs +++ b/test/migration_generator_test.exs @@ -10,6 +10,7 @@ defmodule AshPostgres.MigrationGeneratorTest do defmodule unquote(mod) do use Ash.Resource, + domain: nil, data_layer: AshPostgres.DataLayer postgres do @@ -34,25 +35,17 @@ defmodule AshPostgres.MigrationGeneratorTest do end end - defmacrop defapi(resources) do + defmacrop defdomain(resources) do quote do Code.compiler_options(ignore_module_conflict: true) - defmodule Registry do - use Ash.Registry - - entries do - for resource <- unquote(resources) do - entry(resource) - end - end - end - - defmodule Api do - use Ash.Api + defmodule Domain do + use Ash.Domain resources do - registry(Registry) + for resource <- unquote(resources) do + resource(resource) + end end end @@ -65,7 +58,7 @@ defmodule AshPostgres.MigrationGeneratorTest do Code.compiler_options(ignore_module_conflict: true) defmodule unquote(mod) do - use Ash.Resource, data_layer: AshPostgres.DataLayer + use Ash.Resource, data_layer: AshPostgres.DataLayer, domain: nil postgres do table unquote(table) @@ -104,19 +97,19 @@ defmodule AshPostgres.MigrationGeneratorTest do attributes do uuid_primary_key(:id) - attribute(:title, :string) - attribute(:second_title, :string) - attribute(:title_with_source, :string, source: :t_w_s) - attribute(:title_with_default, :string) - attribute(:email, Test.Support.Types.Email) + attribute(:title, :string, public?: true) + attribute(:second_title, :string, public?: true) + attribute(:title_with_source, :string, source: :t_w_s, public?: true) + attribute(:title_with_default, :string, public?: true) + attribute(:email, Test.Support.Types.Email, public?: true) end end - defapi([Post]) + defdomain([Post]) Mix.shell(Mix.Shell.Process) - AshPostgres.MigrationGenerator.generate(Api, + AshPostgres.MigrationGenerator.generate(Domain, snapshot_path: "test_snapshots_path", migration_path: "test_migration_path", quiet: true, @@ -193,12 +186,12 @@ defmodule AshPostgres.MigrationGeneratorTest do attributes do uuid_primary_key(:id) - attribute(:title, :string) - attribute(:second_title, :string) + attribute(:title, :string, public?: true) + attribute(:second_title, :string, public?: true) end end - defapi([Post]) + defdomain([Post]) Mix.shell(Mix.Shell.Process) @@ -210,7 +203,7 @@ defmodule AshPostgres.MigrationGeneratorTest do """ ) - AshPostgres.MigrationGenerator.generate(Api, + AshPostgres.MigrationGenerator.generate(Domain, snapshot_path: "test_snapshots_path", migration_path: "test_migration_path", quiet: true, @@ -271,14 +264,14 @@ defmodule AshPostgres.MigrationGeneratorTest do attributes do uuid_primary_key(:id) - attribute(:title, :string) + attribute(:title, :string, public?: true) end end - defapi([Post]) + defdomain([Post]) Mix.shell(Mix.Shell.Process) - AshPostgres.MigrationGenerator.generate(Api, + AshPostgres.MigrationGenerator.generate(Domain, snapshot_path: "test_snapshots_path", migration_path: "test_migration_path", quiet: true, @@ -316,14 +309,14 @@ defmodule AshPostgres.MigrationGeneratorTest do attributes do uuid_primary_key(:id) - attribute(:title, :string) + attribute(:title, :string, public?: true) end end - defapi([Post]) + defdomain([Post]) Mix.shell(Mix.Shell.Process) - AshPostgres.MigrationGenerator.generate(Api, + AshPostgres.MigrationGenerator.generate(Domain, snapshot_path: "test_snapshots_path", migration_path: "test_migration_path", quiet: true, @@ -357,15 +350,15 @@ defmodule AshPostgres.MigrationGeneratorTest do attributes do uuid_primary_key(:id) - attribute(:title, :string) + attribute(:title, :string, public?: true) end end - defapi([Post]) + defdomain([Post]) Mix.shell(Mix.Shell.Process) - AshPostgres.MigrationGenerator.generate(Api, + AshPostgres.MigrationGenerator.generate(Domain, snapshot_path: "test_snapshots_path", migration_path: "test_migration_path", quiet: true, @@ -383,15 +376,15 @@ defmodule AshPostgres.MigrationGeneratorTest do attributes do uuid_primary_key(:id) - attribute(:name, :string, allow_nil?: false) + attribute(:name, :string, allow_nil?: false, public?: true) end end - defapi([Post]) + defdomain([Post]) send(self(), {:mix_shell_input, :yes?, true}) - AshPostgres.MigrationGenerator.generate(Api, + AshPostgres.MigrationGenerator.generate(Domain, snapshot_path: "test_snapshots_path", migration_path: "test_migration_path", quiet: true, @@ -412,15 +405,15 @@ defmodule AshPostgres.MigrationGeneratorTest do attributes do uuid_primary_key(:id) - attribute(:name, :string, allow_nil?: false, default: "fred") + attribute(:name, :string, allow_nil?: false, default: "fred", public?: true) end end - defapi([Post]) + defdomain([Post]) send(self(), {:mix_shell_input, :yes?, true}) - AshPostgres.MigrationGenerator.generate(Api, + AshPostgres.MigrationGenerator.generate(Domain, snapshot_path: "test_snapshots_path", migration_path: "test_migration_path", quiet: true, @@ -449,15 +442,15 @@ defmodule AshPostgres.MigrationGeneratorTest do attributes do uuid_primary_key(:id) - attribute(:title, :string) + attribute(:title, :string, public?: true) end end - defapi([Post]) + defdomain([Post]) Mix.shell(Mix.Shell.Process) - AshPostgres.MigrationGenerator.generate(Api, + AshPostgres.MigrationGenerator.generate(Domain, snapshot_path: "test_snapshots_path", migration_path: "test_migration_path", quiet: true, @@ -479,13 +472,13 @@ defmodule AshPostgres.MigrationGeneratorTest do attributes do uuid_primary_key(:id) - attribute(:title, :string) + attribute(:title, :string, public?: true) end end - defapi([Post]) + defdomain([Post]) - AshPostgres.MigrationGenerator.generate(Api, + AshPostgres.MigrationGenerator.generate(Domain, snapshot_path: "test_snapshots_path", migration_path: "test_migration_path", quiet: true, @@ -507,14 +500,14 @@ defmodule AshPostgres.MigrationGeneratorTest do attributes do uuid_primary_key(:id) - attribute(:title, :string) - attribute(:name, :string, allow_nil?: false) + attribute(:title, :string, public?: true) + attribute(:name, :string, allow_nil?: false, public?: true) end end - defapi([Post]) + defdomain([Post]) - AshPostgres.MigrationGenerator.generate(Api, + AshPostgres.MigrationGenerator.generate(Domain, snapshot_path: "test_snapshots_path", migration_path: "test_migration_path", quiet: true, @@ -532,15 +525,15 @@ defmodule AshPostgres.MigrationGeneratorTest do defposts do attributes do uuid_primary_key(:id) - attribute(:name, :string, allow_nil?: false) + attribute(:name, :string, allow_nil?: false, public?: true) end end - defapi([Post]) + defdomain([Post]) send(self(), {:mix_shell_input, :yes?, true}) - AshPostgres.MigrationGenerator.generate(Api, + AshPostgres.MigrationGenerator.generate(Domain, snapshot_path: "test_snapshots_path", migration_path: "test_migration_path", quiet: true, @@ -557,15 +550,15 @@ defmodule AshPostgres.MigrationGeneratorTest do defposts do attributes do uuid_primary_key(:id) - attribute(:name, :string, allow_nil?: false) + attribute(:name, :string, allow_nil?: false, public?: true) end end - defapi([Post]) + defdomain([Post]) send(self(), {:mix_shell_input, :yes?, false}) - AshPostgres.MigrationGenerator.generate(Api, + AshPostgres.MigrationGenerator.generate(Domain, snapshot_path: "test_snapshots_path", migration_path: "test_migration_path", quiet: true, @@ -583,17 +576,17 @@ defmodule AshPostgres.MigrationGeneratorTest do defposts do attributes do uuid_primary_key(:id) - attribute(:name, :string, allow_nil?: false) - attribute(:subject, :string, allow_nil?: false) + attribute(:name, :string, allow_nil?: false, public?: true) + attribute(:subject, :string, allow_nil?: false, public?: true) end end - defapi([Post]) + defdomain([Post]) send(self(), {:mix_shell_input, :yes?, true}) send(self(), {:mix_shell_input, :prompt, "subject"}) - AshPostgres.MigrationGenerator.generate(Api, + AshPostgres.MigrationGenerator.generate(Domain, snapshot_path: "test_snapshots_path", migration_path: "test_migration_path", quiet: true, @@ -614,16 +607,16 @@ defmodule AshPostgres.MigrationGeneratorTest do defposts do attributes do uuid_primary_key(:id) - attribute(:name, :string, allow_nil?: false) - attribute(:subject, :string, allow_nil?: false) + attribute(:name, :string, allow_nil?: false, public?: true) + attribute(:subject, :string, allow_nil?: false, public?: true) end end - defapi([Post]) + defdomain([Post]) send(self(), {:mix_shell_input, :yes?, false}) - AshPostgres.MigrationGenerator.generate(Api, + AshPostgres.MigrationGenerator.generate(Domain, snapshot_path: "test_snapshots_path", migration_path: "test_migration_path", quiet: true, @@ -641,21 +634,21 @@ defmodule AshPostgres.MigrationGeneratorTest do defposts do attributes do uuid_primary_key(:id) - attribute(:title, :string) - attribute(:foobar, :string) + attribute(:title, :string, public?: true) + attribute(:foobar, :string, public?: true) end end defposts Post2 do attributes do uuid_primary_key(:id) - attribute(:name, :string) + attribute(:name, :string, public?: true) end end - defapi([Post, Post2]) + defdomain([Post, Post2]) - AshPostgres.MigrationGenerator.generate(Api, + AshPostgres.MigrationGenerator.generate(Domain, snapshot_path: "test_snapshots_path", migration_path: "test_migration_path", quiet: true, @@ -676,7 +669,7 @@ defmodule AshPostgres.MigrationGeneratorTest do defposts do attributes do uuid_primary_key(:id) - attribute(:title, :string) + attribute(:title, :string, public?: true) end identities do @@ -687,7 +680,7 @@ defmodule AshPostgres.MigrationGeneratorTest do defposts Post2 do attributes do uuid_primary_key(:id) - attribute(:name, :string) + attribute(:name, :string, public?: true) end identities do @@ -695,9 +688,9 @@ defmodule AshPostgres.MigrationGeneratorTest do end end - defapi([Post, Post2]) + defdomain([Post, Post2]) - AshPostgres.MigrationGenerator.generate(Api, + AshPostgres.MigrationGenerator.generate(Domain, snapshot_path: "test_snapshots_path", migration_path: "test_migration_path", quiet: true, @@ -728,8 +721,8 @@ defmodule AshPostgres.MigrationGeneratorTest do defposts do attributes do uuid_primary_key(:id) - attribute(:title, :string) - attribute(:example, :string, allow_nil?: false) + attribute(:title, :string, public?: true) + attribute(:example, :string, allow_nil?: false, public?: true) end end @@ -739,9 +732,9 @@ defmodule AshPostgres.MigrationGeneratorTest do end end - defapi([Post, Post2]) + defdomain([Post, Post2]) - AshPostgres.MigrationGenerator.generate(Api, + AshPostgres.MigrationGenerator.generate(Domain, snapshot_path: "test_snapshots_path", migration_path: "test_migration_path", quiet: true, @@ -767,16 +760,22 @@ defmodule AshPostgres.MigrationGeneratorTest do defposts do attributes do - attribute(:id, :integer, generated?: true, allow_nil?: false, primary_key?: true) - attribute(:views, :integer) + attribute(:id, :integer, + generated?: true, + allow_nil?: false, + primary_key?: true, + public?: true + ) + + attribute(:views, :integer, public?: true) end end - defapi([Post]) + defdomain([Post]) Mix.shell(Mix.Shell.Process) - AshPostgres.MigrationGenerator.generate(Api, + AshPostgres.MigrationGenerator.generate(Domain, snapshot_path: "test_snapshots_path", migration_path: "test_migration_path", quiet: true, @@ -802,18 +801,18 @@ defmodule AshPostgres.MigrationGeneratorTest do defposts do attributes do uuid_primary_key(:id) - attribute(:title, :string) + attribute(:title, :string, public?: true) end end - defapi([Post]) + defdomain([Post]) - [api: Api] + [domain: Domain] end - test "returns code(1) if snapshots and resources don't fit", %{api: api} do + test "returns code(1) if snapshots and resources don't fit", %{domain: domain} do assert catch_exit( - AshPostgres.MigrationGenerator.generate(api, + AshPostgres.MigrationGenerator.generate(domain, snapshot_path: "test_snapshot_path", migration_path: "test_migration_path", check: true @@ -837,25 +836,25 @@ defmodule AshPostgres.MigrationGeneratorTest do defposts do attributes do uuid_primary_key(:id) - attribute(:title, :string) - attribute(:foobar, :string) + attribute(:title, :string, public?: true) + attribute(:foobar, :string, public?: true) end end defposts Post2 do attributes do uuid_primary_key(:id) - attribute(:name, :string) + attribute(:name, :string, public?: true) end relationships do - belongs_to(:post, Post) + belongs_to(:post, Post, public?: true) end end - defapi([Post, Post2]) + defdomain([Post, Post2]) - AshPostgres.MigrationGenerator.generate(Api, + AshPostgres.MigrationGenerator.generate(Domain, snapshot_path: "test_snapshots_path", migration_path: "test_migration_path", quiet: true, @@ -871,26 +870,26 @@ defmodule AshPostgres.MigrationGeneratorTest do test "references are inferred automatically if the attribute has a different type" do defposts do attributes do - attribute(:id, :string, primary_key?: true, allow_nil?: false) - attribute(:title, :string) - attribute(:foobar, :string) + attribute(:id, :string, primary_key?: true, allow_nil?: false, public?: true) + attribute(:title, :string, public?: true) + attribute(:foobar, :string, public?: true) end end defposts Post2 do attributes do - attribute(:id, :string, primary_key?: true, allow_nil?: false) - attribute(:name, :string) + attribute(:id, :string, primary_key?: true, allow_nil?: false, public?: true) + attribute(:name, :string, public?: true) end relationships do - belongs_to(:post, Post, attribute_type: :string) + belongs_to(:post, Post, attribute_type: :string, public?: true) end end - defapi([Post, Post2]) + defdomain([Post, Post2]) - AshPostgres.MigrationGenerator.generate(Api, + AshPostgres.MigrationGenerator.generate(Domain, snapshot_path: "test_snapshots_path", migration_path: "test_migration_path", quiet: true, @@ -907,20 +906,22 @@ defmodule AshPostgres.MigrationGeneratorTest do defposts do attributes do uuid_primary_key(:id) - attribute(:key_id, :uuid, allow_nil?: false) - attribute(:foobar, :string) + attribute(:key_id, :uuid, allow_nil?: false, public?: true) + attribute(:foobar, :string, public?: true) end end defposts Post2 do attributes do uuid_primary_key(:id) - attribute(:name, :string) - attribute(:related_key_id, :uuid) + attribute(:name, :string, public?: true) + attribute(:related_key_id, :uuid, public?: true) end relationships do - belongs_to(:post, Post) + belongs_to(:post, Post) do + public?(true) + end end postgres do @@ -930,9 +931,9 @@ defmodule AshPostgres.MigrationGeneratorTest do end end - defapi([Post, Post2]) + defdomain([Post, Post2]) - AshPostgres.MigrationGenerator.generate(Api, + AshPostgres.MigrationGenerator.generate(Domain, snapshot_path: "test_snapshots_path", migration_path: "test_migration_path", quiet: true, @@ -948,8 +949,8 @@ defmodule AshPostgres.MigrationGeneratorTest do test "references merge :match_with and multitenancy attribute" do defresource Org, "orgs" do attributes do - uuid_primary_key(:id, writable?: true) - attribute(:name, :string) + uuid_primary_key(:id, writable?: true, public?: true) + attribute(:name, :string, public?: true) end multitenancy do @@ -961,10 +962,10 @@ defmodule AshPostgres.MigrationGeneratorTest do defresource User, "users" do attributes do uuid_primary_key(:id, writable?: true) - attribute(:secondary_id, :uuid) - attribute(:name, :string) - attribute(:org_id, :uuid) - attribute(:key_id, :uuid) + attribute(:secondary_id, :uuid, public?: true) + attribute(:name, :string, public?: true) + attribute(:org_id, :uuid, public?: true) + attribute(:key_id, :uuid, public?: true) end multitenancy do @@ -973,16 +974,18 @@ defmodule AshPostgres.MigrationGeneratorTest do end relationships do - belongs_to(:org, Org) + belongs_to(:org, Org) do + public?(true) + end end end defresource UserThing, "user_things" do attributes do - attribute(:id, :string, primary_key?: true, allow_nil?: false) - attribute(:name, :string) - attribute(:org_id, :uuid) - attribute(:related_key_id, :uuid) + attribute(:id, :string, primary_key?: true, allow_nil?: false, public?: true) + attribute(:name, :string, public?: true) + attribute(:org_id, :uuid, public?: true) + attribute(:related_key_id, :uuid, public?: true) end multitenancy do @@ -991,8 +994,11 @@ defmodule AshPostgres.MigrationGeneratorTest do end relationships do - belongs_to(:org, Org) - belongs_to(:user, User, destination_attribute: :secondary_id) + belongs_to(:org, Org) do + public?(true) + end + + belongs_to(:user, User, destination_attribute: :secondary_id, public?: true) end postgres do @@ -1002,9 +1008,9 @@ defmodule AshPostgres.MigrationGeneratorTest do end end - defapi([Org, User, UserThing]) + defdomain([Org, User, UserThing]) - AshPostgres.MigrationGenerator.generate(Api, + AshPostgres.MigrationGenerator.generate(Domain, snapshot_path: "test_snapshots_path", migration_path: "test_migration_path", quiet: true, @@ -1021,7 +1027,7 @@ defmodule AshPostgres.MigrationGeneratorTest do defresource Org, "orgs" do attributes do uuid_primary_key(:id, writable?: true) - attribute(:name, :string) + attribute(:name, :string, public?: true) end multitenancy do @@ -1033,10 +1039,10 @@ defmodule AshPostgres.MigrationGeneratorTest do defresource User, "users" do attributes do uuid_primary_key(:id, writable?: true) - attribute(:secondary_id, :uuid) - attribute(:name, :string) - attribute(:org_id, :uuid) - attribute(:key_id, :uuid) + attribute(:secondary_id, :uuid, public?: true) + attribute(:name, :string, public?: true) + attribute(:org_id, :uuid, public?: true) + attribute(:key_id, :uuid, public?: true) end multitenancy do @@ -1049,13 +1055,15 @@ defmodule AshPostgres.MigrationGeneratorTest do end relationships do - belongs_to(:org, Org) + belongs_to(:org, Org) do + public?(true) + end end end - defapi([Org, User]) + defdomain([Org, User]) - AshPostgres.MigrationGenerator.generate(Api, + AshPostgres.MigrationGenerator.generate(Domain, snapshot_path: "test_snapshots_path", migration_path: "test_migration_path", quiet: true, @@ -1072,25 +1080,27 @@ defmodule AshPostgres.MigrationGeneratorTest do defposts do attributes do uuid_primary_key(:id) - attribute(:title, :string) - attribute(:foobar, :string) + attribute(:title, :string, public?: true) + attribute(:foobar, :string, public?: true) end end defposts Post2 do attributes do uuid_primary_key(:id) - attribute(:name, :string) + attribute(:name, :string, public?: true) end relationships do - belongs_to(:post, Post) + belongs_to(:post, Post) do + public?(true) + end end end - defapi([Post, Post2]) + defdomain([Post, Post2]) - AshPostgres.MigrationGenerator.generate(Api, + AshPostgres.MigrationGenerator.generate(Domain, snapshot_path: "test_snapshots_path", migration_path: "test_migration_path", quiet: true, @@ -1106,15 +1116,17 @@ defmodule AshPostgres.MigrationGeneratorTest do attributes do uuid_primary_key(:id) - attribute(:name, :string) + attribute(:name, :string, public?: true) end relationships do - belongs_to(:post, Post) + belongs_to(:post, Post) do + public?(true) + end end end - AshPostgres.MigrationGenerator.generate(Api, + AshPostgres.MigrationGenerator.generate(Domain, snapshot_path: "test_snapshots_path", migration_path: "test_migration_path", quiet: true, @@ -1145,7 +1157,7 @@ defmodule AshPostgres.MigrationGeneratorTest do defresource Org, "orgs" do attributes do uuid_primary_key(:id, writable?: true) - attribute(:name, :string) + attribute(:name, :string, public?: true) end multitenancy do @@ -1157,9 +1169,9 @@ defmodule AshPostgres.MigrationGeneratorTest do defresource User, "users" do attributes do uuid_primary_key(:id, writable?: true) - attribute(:secondary_id, :uuid) - attribute(:name, :string) - attribute(:org_id, :uuid) + attribute(:secondary_id, :uuid, public?: true) + attribute(:name, :string, public?: true) + attribute(:org_id, :uuid, public?: true) end multitenancy do @@ -1168,15 +1180,17 @@ defmodule AshPostgres.MigrationGeneratorTest do end relationships do - belongs_to(:org, Org) + belongs_to(:org, Org) do + public?(true) + end end end defresource UserThing1, "user_things1" do attributes do - attribute(:id, :string, primary_key?: true, allow_nil?: false) - attribute(:name, :string) - attribute(:org_id, :uuid) + attribute(:id, :string, primary_key?: true, allow_nil?: false, public?: true) + attribute(:name, :string, public?: true) + attribute(:org_id, :uuid, public?: true) end multitenancy do @@ -1185,15 +1199,18 @@ defmodule AshPostgres.MigrationGeneratorTest do end relationships do - belongs_to(:org, Org) - belongs_to(:user, User, destination_attribute: :secondary_id) + belongs_to(:org, Org) do + public?(true) + end + + belongs_to(:user, User, destination_attribute: :secondary_id, public?: true) end end defresource UserThing2, "user_things2" do attributes do uuid_primary_key(:id, writable?: true) - attribute(:name, :string) + attribute(:name, :string, public?: true) end multitenancy do @@ -1202,14 +1219,19 @@ defmodule AshPostgres.MigrationGeneratorTest do end relationships do - belongs_to(:org, Org) - belongs_to(:user, User) + belongs_to(:org, Org) do + public?(true) + end + + belongs_to(:user, User) do + public?(true) + end end end - defapi([Org, User, UserThing1, UserThing2]) + defdomain([Org, User, UserThing1, UserThing2]) - AshPostgres.MigrationGenerator.generate(Api, + AshPostgres.MigrationGenerator.generate(Domain, snapshot_path: "test_snapshots_path", migration_path: "test_migration_path", quiet: true, @@ -1238,7 +1260,7 @@ defmodule AshPostgres.MigrationGeneratorTest do defposts do attributes do uuid_primary_key(:id) - attribute(:price, :integer) + attribute(:price, :integer, public?: true) end postgres do @@ -1248,9 +1270,9 @@ defmodule AshPostgres.MigrationGeneratorTest do end end - defapi([Post]) + defdomain([Post]) - AshPostgres.MigrationGenerator.generate(Api, + AshPostgres.MigrationGenerator.generate(Domain, snapshot_path: "test_snapshots_path", migration_path: "test_migration_path", quiet: true, @@ -1270,7 +1292,7 @@ defmodule AshPostgres.MigrationGeneratorTest do defposts do attributes do uuid_primary_key(:id) - attribute(:price, :integer) + attribute(:price, :integer, public?: true) end postgres do @@ -1280,9 +1302,9 @@ defmodule AshPostgres.MigrationGeneratorTest do end end - defapi([Post]) + defdomain([Post]) - AshPostgres.MigrationGenerator.generate(Api, + AshPostgres.MigrationGenerator.generate(Domain, snapshot_path: "test_snapshots_path", migration_path: "test_migration_path", quiet: true, @@ -1309,7 +1331,7 @@ defmodule AshPostgres.MigrationGeneratorTest do defposts do attributes do uuid_primary_key(:id) - attribute(:price, :integer) + attribute(:price, :integer, public?: true) end postgres do @@ -1319,9 +1341,9 @@ defmodule AshPostgres.MigrationGeneratorTest do end end - defapi([Post]) + defdomain([Post]) - AshPostgres.MigrationGenerator.generate(Api, + AshPostgres.MigrationGenerator.generate(Domain, snapshot_path: "test_snapshots_path", migration_path: "test_migration_path", quiet: true, @@ -1331,11 +1353,11 @@ defmodule AshPostgres.MigrationGeneratorTest do defposts do attributes do uuid_primary_key(:id) - attribute(:price, :integer) + attribute(:price, :integer, public?: true) end end - AshPostgres.MigrationGenerator.generate(Api, + AshPostgres.MigrationGenerator.generate(Domain, snapshot_path: "test_snapshots_path", migration_path: "test_migration_path", quiet: true, @@ -1362,6 +1384,7 @@ defmodule AshPostgres.MigrationGeneratorTest do defmodule Comment do use Ash.Resource, + domain: nil, data_layer: AshPostgres.DataLayer postgres do @@ -1371,7 +1394,7 @@ defmodule AshPostgres.MigrationGeneratorTest do attributes do uuid_primary_key(:id) - attribute(:resource_id, :uuid) + attribute(:resource_id, :uuid, public?: true) end actions do @@ -1381,6 +1404,7 @@ defmodule AshPostgres.MigrationGeneratorTest do defmodule Post do use Ash.Resource, + domain: nil, data_layer: AshPostgres.DataLayer postgres do @@ -1398,27 +1422,29 @@ defmodule AshPostgres.MigrationGeneratorTest do relationships do has_many(:comments, Comment, + public?: true, destination_attribute: :resource_id, relationship_context: %{data_layer: %{table: "post_comments"}} ) belongs_to(:best_comment, Comment, + public?: true, destination_attribute: :id, relationship_context: %{data_layer: %{table: "post_comments"}} ) end end - defapi([Post, Comment]) + defdomain([Post, Comment]) - AshPostgres.MigrationGenerator.generate(Api, + AshPostgres.MigrationGenerator.generate(Domain, snapshot_path: "test_snapshots_path", migration_path: "test_migration_path", quiet: true, format: false ) - [api: Api] + [domain: Domain] end test "it uses the relationship's table context if it is set" do @@ -1441,22 +1467,32 @@ defmodule AshPostgres.MigrationGeneratorTest do defposts do attributes do uuid_primary_key(:id) - attribute(:start_date, :date, default: ~D[2022-04-19]) - attribute(:start_time, :time, default: ~T[08:30:45]) - attribute(:timestamp, :utc_datetime, default: ~U[2022-02-02 08:30:30Z]) - attribute(:timestamp_naive, :naive_datetime, default: ~N[2022-02-02 08:30:30]) - attribute(:number, :integer, default: 5) - attribute(:fraction, :float, default: 0.25) - attribute(:decimal, :decimal, default: Decimal.new("123.4567890987654321987")) - attribute(:name, :string, default: "Fred") - attribute(:tag, :atom, default: :value) - attribute(:enabled, :boolean, default: false) + attribute(:start_date, :date, default: ~D[2022-04-19], public?: true) + attribute(:start_time, :time, default: ~T[08:30:45], public?: true) + attribute(:timestamp, :utc_datetime, default: ~U[2022-02-02 08:30:30Z], public?: true) + + attribute(:timestamp_naive, :naive_datetime, + default: ~N[2022-02-02 08:30:30], + public?: true + ) + + attribute(:number, :integer, default: 5, public?: true) + attribute(:fraction, :float, default: 0.25, public?: true) + + attribute(:decimal, :decimal, + default: Decimal.new("123.4567890987654321987"), + public?: true + ) + + attribute(:name, :string, default: "Fred", public?: true) + attribute(:tag, :atom, default: :value, public?: true) + attribute(:enabled, :boolean, default: false, public?: true) end end - defapi([Post]) + defdomain([Post]) - AshPostgres.MigrationGenerator.generate(Api, + AshPostgres.MigrationGenerator.generate(Domain, snapshot_path: "test_snapshots_path", migration_path: "test_migration_path", quiet: true, @@ -1502,15 +1538,15 @@ defmodule AshPostgres.MigrationGeneratorTest do defposts do attributes do uuid_primary_key(:id) - attribute(:product_code, :term, default: {"xyz"}) + attribute(:product_code, :term, default: {"xyz"}, public?: true) end end - defapi([Post]) + defdomain([Post]) log = capture_log(fn -> - AshPostgres.MigrationGenerator.generate(Api, + AshPostgres.MigrationGenerator.generate(Domain, snapshot_path: "test_snapshots_path", migration_path: "test_migration_path", quiet: true, @@ -1539,12 +1575,13 @@ defmodule AshPostgres.MigrationGeneratorTest do defposts do attributes do uuid_primary_key(:id) - attribute(:title, :string) + attribute(:title, :string, public?: true) end end defmodule Comment do use Ash.Resource, + domain: nil, data_layer: AshPostgres.DataLayer postgres do @@ -1557,15 +1594,17 @@ defmodule AshPostgres.MigrationGeneratorTest do end relationships do - belongs_to(:post, Post) + belongs_to(:post, Post) do + public?(true) + end end end - defapi([Post, Comment]) + defdomain([Post, Comment]) Mix.shell(Mix.Shell.Process) - AshPostgres.MigrationGenerator.generate(Api, + AshPostgres.MigrationGenerator.generate(Domain, snapshot_path: "test_snapshots_path", migration_path: "test_migration_path", quiet: true, @@ -1578,14 +1617,20 @@ defmodule AshPostgres.MigrationGeneratorTest do test "when changing the primary key, it changes properly" do defposts do attributes do - attribute(:id, :uuid, primary_key?: false, default: &Ecto.UUID.generate/0) + attribute(:id, :uuid, + primary_key?: false, + default: &Ecto.UUID.generate/0, + public?: true + ) + uuid_primary_key(:guid) - attribute(:title, :string) + attribute(:title, :string, public?: true) end end defmodule Comment do use Ash.Resource, + domain: nil, data_layer: AshPostgres.DataLayer postgres do @@ -1598,13 +1643,15 @@ defmodule AshPostgres.MigrationGeneratorTest do end relationships do - belongs_to(:post, Post) + belongs_to(:post, Post) do + public?(true) + end end end - defapi([Post, Comment]) + defdomain([Post, Comment]) - AshPostgres.MigrationGenerator.generate(Api, + AshPostgres.MigrationGenerator.generate(Domain, snapshot_path: "test_snapshots_path", migration_path: "test_migration_path", quiet: true, diff --git a/test/multitenancy_test.exs b/test/multitenancy_test.exs index 9fd5605..70cdbf7 100644 --- a/test/multitenancy_test.exs +++ b/test/multitenancy_test.exs @@ -1,18 +1,18 @@ defmodule AshPostgres.Test.MultitenancyTest do use AshPostgres.RepoCase, async: false - alias AshPostgres.MultitenancyTest.{Api, Org, Post, User} + alias AshPostgres.MultitenancyTest.{Org, Post, User} setup do org1 = Org - |> Ash.Changeset.new(name: "test1") - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{name: "test1"}) + |> Ash.create!() org2 = Org - |> Ash.Changeset.new(name: "test2") - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{name: "test2"}) + |> Ash.create!() [org1: org1, org2: org2] end @@ -34,17 +34,17 @@ defmodule AshPostgres.Test.MultitenancyTest do assert [%{id: ^org_id}] = Org |> Ash.Query.set_tenant(tenant(org1)) - |> Api.read!() + |> Ash.read!() end test "context multitenancy works with policies", %{org1: org1} do Post - |> Ash.Changeset.new(name: "foo") + |> Ash.Changeset.for_create(:create, %{name: "foo"}) |> Ash.Changeset.set_tenant(tenant(org1)) - |> Api.create!() + |> Ash.create!() |> Ash.Changeset.for_update(:update_with_policy, %{}, authorize?: true) |> Ash.Changeset.set_tenant(tenant(org1)) - |> Api.update!() + |> Ash.update!() end test "attribute multitenancy is set on creation" do @@ -52,29 +52,29 @@ defmodule AshPostgres.Test.MultitenancyTest do org = Org - |> Ash.Changeset.new(name: "test3") + |> Ash.Changeset.for_create(:create, %{name: "test3"}) |> Ash.Changeset.set_tenant("org_#{uuid}") - |> Api.create!() + |> Ash.create!() assert org.id == uuid end test "schema multitenancy works", %{org1: org1, org2: org2} do Post - |> Ash.Changeset.new(name: "foo") + |> Ash.Changeset.for_create(:create, %{name: "foo"}) |> Ash.Changeset.set_tenant(tenant(org1)) - |> Api.create!() + |> Ash.create!() - assert [_] = Post |> Ash.Query.set_tenant(tenant(org1)) |> Api.read!() - assert [] = Post |> Ash.Query.set_tenant(tenant(org2)) |> Api.read!() + assert [_] = Post |> Ash.Query.set_tenant(tenant(org1)) |> Ash.read!() + assert [] = Post |> Ash.Query.set_tenant(tenant(org2)) |> Ash.read!() end test "schema rename on update works", %{org1: org1} do new_uuid = Ash.UUID.generate() org1 - |> Ash.Changeset.new(id: new_uuid) - |> Api.update!() + |> Ash.Changeset.for_update(:update, %{id: new_uuid}) + |> Ash.update!() new_tenant = "org_#{new_uuid}" @@ -91,106 +91,106 @@ defmodule AshPostgres.Test.MultitenancyTest do org = Org |> Ash.Changeset.new() - |> Api.create!() + |> Ash.create!() user = User |> Ash.Changeset.new() |> Ash.Changeset.manage_relationship(:org, org, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() - assert Api.load!(user, :org).org.id == org.id + assert Ash.load!(user, :org).org.id == org.id end test "loading context multitenant resources from attribute multitenant resources works" do org = Org |> Ash.Changeset.new() - |> Api.create!() + |> Ash.create!() user1 = User - |> Ash.Changeset.new(%{name: "a"}) + |> Ash.Changeset.for_create(:create, %{name: "a"}) |> Ash.Changeset.manage_relationship(:org, org, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() user2 = User - |> Ash.Changeset.new(%{name: "b"}) + |> Ash.Changeset.for_create(:create, %{name: "b"}) |> Ash.Changeset.manage_relationship(:org, org, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() user1_id = user1.id user2_id = user2.id assert [%{id: ^user1_id}, %{id: ^user2_id}] = - Api.load!(org, users: Ash.Query.sort(User, :name)).users + Ash.load!(org, users: Ash.Query.sort(User, :name)).users end test "manage_relationship from context multitenant resource to attribute multitenant resource doesn't raise an error" do - org = Org |> Ash.Changeset.new() |> Api.create!() - user = User |> Ash.Changeset.new() |> Api.create!() + org = Org |> Ash.Changeset.new() |> Ash.create!() + user = User |> Ash.Changeset.new() |> Ash.create!() Post |> Ash.Changeset.for_create(:create, %{}, tenant: tenant(org)) |> Ash.Changeset.manage_relationship(:user, user, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() end test "loading attribute multitenant resources with limits from context multitenant resources works" do org = Org |> Ash.Changeset.new() - |> Api.create!() + |> Ash.create!() user = User |> Ash.Changeset.new() |> Ash.Changeset.manage_relationship(:org, org, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() - assert Api.load!(user, :org).org.id == org.id + assert Ash.load!(user, :org).org.id == org.id end test "loading context multitenant resources with limits from attribute multitenant resources works" do org = Org |> Ash.Changeset.new() - |> Api.create!() + |> Ash.create!() user1 = User - |> Ash.Changeset.new(%{name: "a"}) + |> Ash.Changeset.for_create(:create, %{name: "a"}) |> Ash.Changeset.manage_relationship(:org, org, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() user2 = User - |> Ash.Changeset.new(%{name: "b"}) + |> Ash.Changeset.for_create(:create, %{name: "b"}) |> Ash.Changeset.manage_relationship(:org, org, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() user1_id = user1.id user2_id = user2.id assert [%{id: ^user1_id}, %{id: ^user2_id}] = - Api.load!(org, users: Ash.Query.sort(Ash.Query.limit(User, 10), :name)).users + Ash.load!(org, users: Ash.Query.sort(Ash.Query.limit(User, 10), :name)).users end test "unique constraints are properly scoped", %{org1: org1} do post = Post - |> Ash.Changeset.new(%{}) + |> Ash.Changeset.for_create(:create, %{}) |> Ash.Changeset.set_tenant(tenant(org1)) - |> Api.create!() + |> Ash.create!() assert_raise Ash.Error.Invalid, ~r/Invalid value provided for id: has already been taken/, fn -> Post - |> Ash.Changeset.new(%{id: post.id}) + |> Ash.Changeset.for_create(:create, %{id: post.id}) |> Ash.Changeset.set_tenant(tenant(org1)) - |> Api.create!() + |> Ash.create!() end end end diff --git a/test/polymorphism_test.exs b/test/polymorphism_test.exs index e176719..4612a3c 100644 --- a/test/polymorphism_test.exs +++ b/test/polymorphism_test.exs @@ -1,29 +1,29 @@ defmodule AshPostgres.PolymorphismTest do use AshPostgres.RepoCase, async: false - alias AshPostgres.Test.{Api, Post, Rating} + alias AshPostgres.Test.{Post, Rating} require Ash.Query test "you can create related data" do Post |> Ash.Changeset.for_create(:create, rating: %{score: 10}) - |> Api.create!() + |> Ash.create!() assert [%{score: 10}] = Rating |> Ash.Query.set_context(%{data_layer: %{table: "post_ratings"}}) - |> Api.read!() + |> Ash.read!() end test "you can read related data" do Post |> Ash.Changeset.for_create(:create, rating: %{score: 10}) - |> Api.create!() + |> Ash.create!() assert [%{score: 10}] = Post |> Ash.Query.load(:ratings) - |> Api.read_one!() + |> Ash.read_one!() |> Map.get(:ratings) end end diff --git a/test/primary_key_test.exs b/test/primary_key_test.exs index 7f5ba71..af12e79 100644 --- a/test/primary_key_test.exs +++ b/test/primary_key_test.exs @@ -1,16 +1,17 @@ defmodule AshPostgres.Test.PrimaryKeyTest do @moduledoc false use AshPostgres.RepoCase, async: false - alias AshPostgres.Test.{Api, IntegerPost, Post, PostView} + alias AshPostgres.Test.{IntegerPost, Post, PostView} require Ash.Query test "creates record with integer primary key" do - assert %IntegerPost{} = IntegerPost |> Ash.Changeset.new(%{title: "title"}) |> Api.create!() + assert %IntegerPost{} = + IntegerPost |> Ash.Changeset.for_create(:create, %{title: "title"}) |> Ash.create!() end test "creates record with uuid primary key" do - assert %Post{} = Post |> Ash.Changeset.new(%{title: "title"}) |> Api.create!() + assert %Post{} = Post |> Ash.Changeset.for_create(:create, %{title: "title"}) |> Ash.create!() end describe "resources without a primary key" do @@ -18,12 +19,12 @@ defmodule AshPostgres.Test.PrimaryKeyTest do post = Post |> Ash.Changeset.for_action(:create, %{title: "not very interesting"}) - |> Api.create!() + |> Ash.create!() assert {:ok, view} = PostView |> Ash.Changeset.for_action(:create, %{browser: :firefox, post_id: post.id}) - |> Api.create() + |> Ash.create() assert view.browser == :firefox assert view.post_id == post.id @@ -34,14 +35,14 @@ defmodule AshPostgres.Test.PrimaryKeyTest do post = Post |> Ash.Changeset.for_action(:create, %{title: "not very interesting"}) - |> Api.create!() + |> Ash.create!() expected = PostView |> Ash.Changeset.for_action(:create, %{browser: :firefox, post_id: post.id}) - |> Api.create!() + |> Ash.create!() - assert {:ok, [actual]} = Api.read(PostView) + assert {:ok, [actual]} = Ash.read(PostView) assert actual.time == expected.time assert actual.browser == expected.browser diff --git a/test/references_test.exs b/test/references_test.exs index b192597..afb89ac 100644 --- a/test/references_test.exs +++ b/test/references_test.exs @@ -8,11 +8,12 @@ defmodule AshPostgres.ReferencesTest do defmodule Org do @moduledoc false use Ash.Resource, + domain: nil, data_layer: AshPostgres.DataLayer attributes do uuid_primary_key(:id, writable?: true) - attribute(:name, :string) + attribute(:name, :string, public?: true) end multitenancy do @@ -33,14 +34,15 @@ defmodule AshPostgres.ReferencesTest do defmodule User do @moduledoc false use Ash.Resource, + domain: nil, data_layer: AshPostgres.DataLayer attributes do uuid_primary_key(:id, writable?: true) - attribute(:secondary_id, :uuid) - attribute(:foo_id, :uuid) - attribute(:name, :string) - attribute(:org_id, :uuid) + attribute(:secondary_id, :uuid, public?: true) + attribute(:foo_id, :uuid, public?: true) + attribute(:name, :string, public?: true) + attribute(:org_id, :uuid, public?: true) end multitenancy do @@ -49,7 +51,9 @@ defmodule AshPostgres.ReferencesTest do end relationships do - belongs_to(:org, Org) + belongs_to(:org, Org) do + public?(true) + end end postgres do @@ -66,13 +70,14 @@ defmodule AshPostgres.ReferencesTest do defmodule UserThing do @moduledoc false use Ash.Resource, + domain: nil, data_layer: AshPostgres.DataLayer attributes do - attribute(:id, :string, primary_key?: true, allow_nil?: false) - attribute(:name, :string) - attribute(:org_id, :uuid) - attribute(:foo_id, :uuid) + attribute(:id, :string, primary_key?: true, allow_nil?: false, public?: true) + attribute(:name, :string, public?: true) + attribute(:org_id, :uuid, public?: true) + attribute(:foo_id, :uuid, public?: true) end multitenancy do diff --git a/test/rel_with_parent_filter_test.exs b/test/rel_with_parent_filter_test.exs index 4ac3aa7..ef8a384 100644 --- a/test/rel_with_parent_filter_test.exs +++ b/test/rel_with_parent_filter_test.exs @@ -1,7 +1,7 @@ defmodule AshPostgres.RelWithParentFilterTest do use AshPostgres.RepoCase, async: false - alias AshPostgres.Test.{Api, Author} + alias AshPostgres.Test.Author require Ash.Query @@ -9,11 +9,11 @@ defmodule AshPostgres.RelWithParentFilterTest do %{id: author_id} = Author |> Ash.Changeset.for_create(:create, %{first_name: "John", last_name: "Doe"}) - |> Api.create!() + |> Ash.create!() Author |> Ash.Changeset.for_create(:create, %{first_name: "John"}) - |> Api.create!() + |> Ash.create!() # here we get the expected result of 1 because it is done in the same query assert %{num_of_authors_with_same_first_name: 1} = @@ -21,18 +21,18 @@ defmodule AshPostgres.RelWithParentFilterTest do |> Ash.Query.for_read(:read) |> Ash.Query.filter(id == ^author_id) |> Ash.Query.load(:num_of_authors_with_same_first_name) - |> Api.read_one!() + |> Ash.read_one!() end test "filter on relationship using parent works as expected when loading relationship" do %{id: author_id} = Author |> Ash.Changeset.for_create(:create, %{first_name: "John", last_name: "Doe"}) - |> Api.create!() + |> Ash.create!() Author |> Ash.Changeset.for_create(:create, %{first_name: "John"}) - |> Api.create!() + |> Ash.create!() assert %{authors_with_same_first_name: authors} = Author @@ -43,7 +43,7 @@ defmodule AshPostgres.RelWithParentFilterTest do # but when doing that it does a inner lateral join # instead of using the id from the parent relationship |> Ash.Query.load(:authors_with_same_first_name) - |> Api.read_one!() + |> Ash.read_one!() assert length(authors) == 1 end diff --git a/test/schema_test.exs b/test/schema_test.exs index 1dfa052..c8be1cf 100644 --- a/test/schema_test.exs +++ b/test/schema_test.exs @@ -1,12 +1,12 @@ defmodule AshPostgres.SchemaTest do @moduledoc false use AshPostgres.RepoCase, async: false - alias AshPostgres.Test.{Api, Author, Profile} + alias AshPostgres.Test.{Author, Profile} require Ash.Query setup do - [author: Api.create!(Ash.Changeset.for_create(Author, :create, %{}))] + [author: Ash.create!(Ash.Changeset.for_create(Author, :create, %{}))] end test "data can be created", %{author: author} do @@ -14,16 +14,16 @@ defmodule AshPostgres.SchemaTest do Profile |> Ash.Changeset.for_create(:create, %{description: "foo"}) |> Ash.Changeset.manage_relationship(:author, author, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() end test "data can be read", %{author: author} do Profile |> Ash.Changeset.for_create(:create, %{description: "foo"}) |> Ash.Changeset.manage_relationship(:author, author, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() - assert [%{description: "foo"}] = Profile |> Api.read!() + assert [%{description: "foo"}] = Profile |> Ash.read!() end test "they can be filtered across", %{author: author} do @@ -31,33 +31,33 @@ defmodule AshPostgres.SchemaTest do Profile |> Ash.Changeset.for_create(:create, %{description: "foo"}) |> Ash.Changeset.manage_relationship(:author, author, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() - Api.create!(Ash.Changeset.for_create(Author, :create, %{})) + Ash.create!(Ash.Changeset.for_create(Author, :create, %{})) assert [_] = Author |> Ash.Query.filter(profile.id == ^profile.id) - |> Api.read!() + |> Ash.read!() assert [_] = Profile |> Ash.Query.filter(author.id == ^author.id) - |> Api.read!() + |> Ash.read!() end test "aggregates work across schemas", %{author: author} do Profile |> Ash.Changeset.for_create(:create, %{description: "foo"}) |> Ash.Changeset.manage_relationship(:author, author, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() assert [%{profile_description: "foo"}] = Author |> Ash.Query.filter(profile_description == "foo") |> Ash.Query.load(:profile_description) - |> Api.read!() + |> Ash.read!() - assert %{profile_description: "foo"} = Api.load!(author, :profile_description) + assert %{profile_description: "foo"} = Ash.load!(author, :profile_description) end end diff --git a/test/select_test.exs b/test/select_test.exs index 5287b5f..1d30aae 100644 --- a/test/select_test.exs +++ b/test/select_test.exs @@ -1,15 +1,15 @@ defmodule AshPostgres.SelectTest do @moduledoc false use AshPostgres.RepoCase, async: false - alias AshPostgres.Test.{Api, Post} + alias AshPostgres.Test.Post require Ash.Query test "values not selected in the query are not present in the response" do Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() - assert [%{title: nil}] = Api.read!(Ash.Query.select(Post, :id)) + assert [%{title: %Ash.NotLoaded{}}] = Ash.read!(Ash.Query.select(Post, :id)) end end diff --git a/test/sort_test.exs b/test/sort_test.exs index 25f6a8b..1d190e8 100644 --- a/test/sort_test.exs +++ b/test/sort_test.exs @@ -1,30 +1,30 @@ defmodule AshPostgres.SortTest do @moduledoc false use AshPostgres.RepoCase, async: false - alias AshPostgres.Test.{Api, Comment, Post, PostLink} + alias AshPostgres.Test.{Comment, Post, PostLink} require Ash.Query require Ash.Sort test "multi-column sorts work" do Post - |> Ash.Changeset.new(%{title: "aaa", score: 0}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "aaa", score: 0}) + |> Ash.create!() Post - |> Ash.Changeset.new(%{title: "aaa", score: 1}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "aaa", score: 1}) + |> Ash.create!() Post - |> Ash.Changeset.new(%{title: "bbb", score: 0}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "bbb", score: 0}) + |> Ash.create!() assert [ %{title: "aaa", score: 0}, %{title: "aaa", score: 1}, %{title: "bbb"} ] = - Api.read!( + Ash.read!( Post |> Ash.Query.load(:count_of_comments) |> Ash.Query.sort(title: :asc, score: :asc) @@ -34,31 +34,31 @@ defmodule AshPostgres.SortTest do test "multi-column sorts work on inclusion" do post = Post - |> Ash.Changeset.new(%{title: "aaa", score: 0}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "aaa", score: 0}) + |> Ash.create!() Post - |> Ash.Changeset.new(%{title: "aaa", score: 1}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "aaa", score: 1}) + |> Ash.create!() Post - |> Ash.Changeset.new(%{title: "bbb", score: 0}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "bbb", score: 0}) + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "aaa", likes: 1}) + |> Ash.Changeset.for_create(:create, %{title: "aaa", likes: 1}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "bbb", likes: 1}) + |> Ash.Changeset.for_create(:create, %{title: "bbb", likes: 1}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() Comment - |> Ash.Changeset.new(%{title: "aaa", likes: 2}) + |> Ash.Changeset.for_create(:create, %{title: "aaa", likes: 2}) |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) - |> Api.create!() + |> Ash.create!() posts = Post @@ -71,7 +71,7 @@ defmodule AshPostgres.SortTest do |> Ash.Query.limit(1) ]) |> Ash.Query.sort([:title, :score]) - |> Api.read!() + |> Ash.read!() assert [ %{title: "aaa", comments: [%{title: "aaa"}]}, @@ -82,23 +82,23 @@ defmodule AshPostgres.SortTest do test "multicolumn sort works with a select statement" do Post - |> Ash.Changeset.new(%{title: "aaa", score: 0}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "aaa", score: 0}) + |> Ash.create!() Post - |> Ash.Changeset.new(%{title: "aaa", score: 1}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "aaa", score: 1}) + |> Ash.create!() Post - |> Ash.Changeset.new(%{title: "bbb", score: 0}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "bbb", score: 0}) + |> Ash.create!() assert [ %{title: "aaa", score: 0}, %{title: "aaa", score: 1}, %{title: "bbb"} ] = - Api.read!( + Ash.read!( Post |> Ash.Query.sort(title: :asc, score: :asc) |> Ash.Query.select([:title, :score]) @@ -108,43 +108,43 @@ defmodule AshPostgres.SortTest do test "sorting when joining to a many to many relationship sorts properly" do post1 = Post - |> Ash.Changeset.new(%{title: "aaa", score: 0}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "aaa", score: 0}) + |> Ash.create!() post2 = Post - |> Ash.Changeset.new(%{title: "bbb", score: 1}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "bbb", score: 1}) + |> Ash.create!() post3 = Post - |> Ash.Changeset.new(%{title: "ccc", score: 0}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "ccc", score: 0}) + |> Ash.create!() PostLink |> Ash.Changeset.new() |> Ash.Changeset.manage_relationship(:source_post, post1, type: :append) |> Ash.Changeset.manage_relationship(:destination_post, post3, type: :append) - |> Api.create!() + |> Ash.create!() PostLink |> Ash.Changeset.new() |> Ash.Changeset.manage_relationship(:source_post, post2, type: :append) |> Ash.Changeset.manage_relationship(:destination_post, post2, type: :append) - |> Api.create!() + |> Ash.create!() PostLink |> Ash.Changeset.new() |> Ash.Changeset.manage_relationship(:source_post, post3, type: :append) |> Ash.Changeset.manage_relationship(:destination_post, post1, type: :append) - |> Api.create!() + |> Ash.create!() assert [ %{title: "aaa"}, %{title: "bbb"}, %{title: "ccc"} ] = - Api.read!( + Ash.read!( Post |> Ash.Query.sort(title: :asc) |> Ash.Query.filter(linked_posts.title in ["aaa", "bbb", "ccc"]) @@ -155,7 +155,7 @@ defmodule AshPostgres.SortTest do %{title: "bbb"}, %{title: "aaa"} ] = - Api.read!( + Ash.read!( Post |> Ash.Query.sort(title: :desc) |> Ash.Query.filter(linked_posts.title in ["aaa", "bbb", "ccc"] or title == "aaa") @@ -166,7 +166,7 @@ defmodule AshPostgres.SortTest do %{title: "bbb"}, %{title: "aaa"} ] = - Api.read!( + Ash.read!( Post |> Ash.Query.sort(title: :desc) |> Ash.Query.filter( @@ -180,48 +180,48 @@ defmodule AshPostgres.SortTest do Post |> Ash.Query.load(:count_of_comments) |> Ash.Query.sort(:c_times_p) - |> Api.read!() + |> Ash.read!() end test "calculations can sort on expressions" do post1 = Post - |> Ash.Changeset.new(%{title: "aaa", score: 0}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "aaa", score: 0}) + |> Ash.create!() post2 = Post - |> Ash.Changeset.new(%{title: "bbb", score: 1}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "bbb", score: 1}) + |> Ash.create!() post3 = Post - |> Ash.Changeset.new(%{title: "ccc", score: 0}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "ccc", score: 0}) + |> Ash.create!() PostLink |> Ash.Changeset.new() |> Ash.Changeset.manage_relationship(:source_post, post1, type: :append) |> Ash.Changeset.manage_relationship(:destination_post, post3, type: :append) - |> Api.create!() + |> Ash.create!() PostLink |> Ash.Changeset.new() |> Ash.Changeset.manage_relationship(:source_post, post2, type: :append) |> Ash.Changeset.manage_relationship(:destination_post, post2, type: :append) - |> Api.create!() + |> Ash.create!() PostLink |> Ash.Changeset.new() |> Ash.Changeset.manage_relationship(:source_post, post3, type: :append) |> Ash.Changeset.manage_relationship(:destination_post, post1, type: :append) - |> Api.create!() + |> Ash.create!() posts_query = Ash.Query.sort(Post, Ash.Sort.expr_sort(source(post_links.state))) Post |> Ash.Query.load(linked_posts: posts_query) - |> Api.read!() + |> Ash.read!() end end diff --git a/test/support/api.ex b/test/support/api.ex deleted file mode 100644 index 270256f..0000000 --- a/test/support/api.ex +++ /dev/null @@ -1,8 +0,0 @@ -defmodule AshPostgres.Test.Api do - @moduledoc false - use Ash.Api - - resources do - registry(AshPostgres.Test.Registry) - end -end diff --git a/test/support/complex_calculations/api.ex b/test/support/complex_calculations/api.ex deleted file mode 100644 index d7202c4..0000000 --- a/test/support/complex_calculations/api.ex +++ /dev/null @@ -1,8 +0,0 @@ -defmodule AshPostgres.Test.ComplexCalculations.Api do - @moduledoc false - use Ash.Api - - resources do - registry(AshPostgres.Test.ComplexCalculations.Registry) - end -end diff --git a/test/support/complex_calculations/domain.ex b/test/support/complex_calculations/domain.ex new file mode 100644 index 0000000..76d066c --- /dev/null +++ b/test/support/complex_calculations/domain.ex @@ -0,0 +1,17 @@ +defmodule AshPostgres.Test.ComplexCalculations.Domain do + @moduledoc false + use Ash.Domain + + resources do + resource(AshPostgres.Test.ComplexCalculations.Certification) + resource(AshPostgres.Test.ComplexCalculations.Skill) + resource(AshPostgres.Test.ComplexCalculations.Documentation) + resource(AshPostgres.Test.ComplexCalculations.Channel) + resource(AshPostgres.Test.ComplexCalculations.DMChannel) + resource(AshPostgres.Test.ComplexCalculations.ChannelMember) + end + + authorization do + authorize(:when_requested) + end +end diff --git a/test/support/complex_calculations/registry.ex b/test/support/complex_calculations/registry.ex deleted file mode 100644 index 29f3afc..0000000 --- a/test/support/complex_calculations/registry.ex +++ /dev/null @@ -1,13 +0,0 @@ -defmodule AshPostgres.Test.ComplexCalculations.Registry do - @moduledoc false - use Ash.Registry - - entries do - entry(AshPostgres.Test.ComplexCalculations.Certification) - entry(AshPostgres.Test.ComplexCalculations.Skill) - entry(AshPostgres.Test.ComplexCalculations.Documentation) - entry(AshPostgres.Test.ComplexCalculations.Channel) - entry(AshPostgres.Test.ComplexCalculations.DMChannel) - entry(AshPostgres.Test.ComplexCalculations.ChannelMember) - end -end diff --git a/test/support/complex_calculations/resources/certification.ex b/test/support/complex_calculations/resources/certification.ex index 72de4f8..d41ca98 100644 --- a/test/support/complex_calculations/resources/certification.ex +++ b/test/support/complex_calculations/resources/certification.ex @@ -1,8 +1,11 @@ defmodule AshPostgres.Test.ComplexCalculations.Certification do @moduledoc false - use Ash.Resource, data_layer: AshPostgres.DataLayer + use Ash.Resource, + domain: AshPostgres.Test.ComplexCalculations.Domain, + data_layer: AshPostgres.DataLayer actions do + default_accept(:*) defaults([:create, :read, :update, :destroy]) end @@ -43,6 +46,8 @@ defmodule AshPostgres.Test.ComplexCalculations.Certification do end relationships do - has_many(:skills, AshPostgres.Test.ComplexCalculations.Skill) + has_many(:skills, AshPostgres.Test.ComplexCalculations.Skill) do + public?(true) + end end end diff --git a/test/support/complex_calculations/resources/channel.ex b/test/support/complex_calculations/resources/channel.ex index 6d9d3a8..eed9187 100644 --- a/test/support/complex_calculations/resources/channel.ex +++ b/test/support/complex_calculations/resources/channel.ex @@ -1,20 +1,22 @@ defmodule AshPostgres.Test.ComplexCalculations.Channel do @moduledoc false use Ash.Resource, + domain: AshPostgres.Test.ComplexCalculations.Domain, data_layer: AshPostgres.DataLayer, authorizers: [Ash.Policy.Authorizer] require Ash.Expr actions do + default_accept(:*) defaults([:create, :read, :update, :destroy]) end attributes do uuid_primary_key(:id) - create_timestamp(:created_at, private?: false) - update_timestamp(:updated_at, private?: false) + create_timestamp(:created_at, public?: true) + update_timestamp(:updated_at, public?: true) end postgres do @@ -23,30 +25,36 @@ defmodule AshPostgres.Test.ComplexCalculations.Channel do end relationships do - has_many(:channel_members, AshPostgres.Test.ComplexCalculations.ChannelMember) + has_many(:channel_members, AshPostgres.Test.ComplexCalculations.ChannelMember) do + public?(true) + end has_one :first_member, AshPostgres.Test.ComplexCalculations.ChannelMember do + public?(true) destination_attribute(:channel_id) from_many?(true) sort(created_at: :asc) end has_one :second_member, AshPostgres.Test.ComplexCalculations.ChannelMember do + public?(true) destination_attribute(:channel_id) from_many?(true) sort(created_at: :desc) end has_one :dm_channel, AshPostgres.Test.ComplexCalculations.DMChannel do - api(AshPostgres.Test.ComplexCalculations.Api) + public?(true) + domain(AshPostgres.Test.ComplexCalculations.Domain) destination_attribute(:id) end has_one :dm_channel_with_same_id, AshPostgres.Test.ComplexCalculations.DMChannel do + public?(true) no_attributes?(true) from_many?(true) filter(expr(parent(id) == id)) - api(AshPostgres.Test.ComplexCalculations.Api) + domain(AshPostgres.Test.ComplexCalculations.Domain) end end diff --git a/test/support/complex_calculations/resources/channel_member.ex b/test/support/complex_calculations/resources/channel_member.ex index 0d78a29..69e631e 100644 --- a/test/support/complex_calculations/resources/channel_member.ex +++ b/test/support/complex_calculations/resources/channel_member.ex @@ -1,18 +1,21 @@ defmodule AshPostgres.Test.ComplexCalculations.ChannelMember do @moduledoc false use Ash.Resource, + domain: AshPostgres.Test.ComplexCalculations.Domain, data_layer: AshPostgres.DataLayer, authorizers: [Ash.Policy.Authorizer] actions do + default_accept(:*) + defaults([:create, :read, :update, :destroy]) end attributes do uuid_primary_key(:id) - create_timestamp(:created_at, private?: false) - update_timestamp(:updated_at, private?: false) + create_timestamp(:created_at, public?: true) + update_timestamp(:updated_at, public?: true) end postgres do @@ -21,8 +24,8 @@ defmodule AshPostgres.Test.ComplexCalculations.ChannelMember do end relationships do - belongs_to(:user, AshPostgres.Test.User, api: AshPostgres.Test.Api, attribute_writable?: true) + belongs_to(:user, AshPostgres.Test.User, domain: AshPostgres.Test.Domain, public?: true) - belongs_to(:channel, AshPostgres.Test.ComplexCalculations.Channel, attribute_writable?: true) + belongs_to(:channel, AshPostgres.Test.ComplexCalculations.Channel, public?: true) end end diff --git a/test/support/complex_calculations/resources/dm_channel.ex b/test/support/complex_calculations/resources/dm_channel.ex index b8b74ad..ed3a639 100644 --- a/test/support/complex_calculations/resources/dm_channel.ex +++ b/test/support/complex_calculations/resources/dm_channel.ex @@ -1,20 +1,23 @@ defmodule AshPostgres.Test.ComplexCalculations.DMChannel do @moduledoc false use Ash.Resource, + domain: AshPostgres.Test.ComplexCalculations.Domain, data_layer: AshPostgres.DataLayer, authorizers: [Ash.Policy.Authorizer] require Ash.Expr actions do + default_accept(:*) + defaults([:create, :read, :update, :destroy]) end attributes do uuid_primary_key(:id) - create_timestamp(:created_at, private?: false) - update_timestamp(:updated_at, private?: false) + create_timestamp(:created_at, public?: true) + update_timestamp(:updated_at, public?: true) end postgres do @@ -24,16 +27,19 @@ defmodule AshPostgres.Test.ComplexCalculations.DMChannel do relationships do has_many :channel_members, AshPostgres.Test.ComplexCalculations.ChannelMember do + public?(true) destination_attribute(:channel_id) end has_one :first_member, AshPostgres.Test.ComplexCalculations.ChannelMember do + public?(true) destination_attribute(:channel_id) from_many?(true) sort(created_at: :asc) end has_one :second_member, AshPostgres.Test.ComplexCalculations.ChannelMember do + public?(true) destination_attribute(:channel_id) from_many?(true) sort(created_at: :desc) diff --git a/test/support/complex_calculations/resources/documentation.ex b/test/support/complex_calculations/resources/documentation.ex index 757f09b..7ec7940 100644 --- a/test/support/complex_calculations/resources/documentation.ex +++ b/test/support/complex_calculations/resources/documentation.ex @@ -1,8 +1,12 @@ defmodule AshPostgres.Test.ComplexCalculations.Documentation do @moduledoc false - use Ash.Resource, data_layer: AshPostgres.DataLayer + use Ash.Resource, + domain: AshPostgres.Test.ComplexCalculations.Domain, + data_layer: AshPostgres.DataLayer actions do + default_accept(:*) + defaults([:create, :read, :update, :destroy]) end @@ -15,12 +19,13 @@ defmodule AshPostgres.Test.ComplexCalculations.Documentation do constraints: [ one_of: [:demonstrated, :performed, :approved, :reopened] ], + public?: true, allow_nil?: false ) - attribute(:documented_at, :utc_datetime_usec) - create_timestamp(:inserted_at, private?: false) - update_timestamp(:updated_at, private?: false) + attribute(:documented_at, :utc_datetime_usec, public?: true) + create_timestamp(:inserted_at, public?: true, writable?: true) + update_timestamp(:updated_at, public?: true, writable?: true) end calculations do @@ -43,6 +48,8 @@ defmodule AshPostgres.Test.ComplexCalculations.Documentation do end relationships do - belongs_to(:skill, AshPostgres.Test.ComplexCalculations.Skill) + belongs_to(:skill, AshPostgres.Test.ComplexCalculations.Skill) do + public?(true) + end end end diff --git a/test/support/complex_calculations/resources/skill.ex b/test/support/complex_calculations/resources/skill.ex index 5a38037..415a87b 100644 --- a/test/support/complex_calculations/resources/skill.ex +++ b/test/support/complex_calculations/resources/skill.ex @@ -1,8 +1,12 @@ defmodule AshPostgres.Test.ComplexCalculations.Skill do @moduledoc false - use Ash.Resource, data_layer: AshPostgres.DataLayer + use Ash.Resource, + domain: AshPostgres.Test.ComplexCalculations.Domain, + data_layer: AshPostgres.DataLayer actions do + default_accept(:*) + defaults([:create, :read, :update, :destroy]) end @@ -14,7 +18,7 @@ defmodule AshPostgres.Test.ComplexCalculations.Skill do attributes do uuid_primary_key(:id) - attribute(:removed, :boolean, default: false, allow_nil?: false) + attribute(:removed, :boolean, default: false, allow_nil?: false, public?: true) end calculations do @@ -37,13 +41,17 @@ defmodule AshPostgres.Test.ComplexCalculations.Skill do end relationships do - belongs_to(:certification, AshPostgres.Test.ComplexCalculations.Certification) + belongs_to(:certification, AshPostgres.Test.ComplexCalculations.Certification) do + public?(true) + end has_many :documentations, AshPostgres.Test.ComplexCalculations.Documentation do + public?(true) sort(timestamp: :desc, inserted_at: :desc) end has_one :latest_documentation, AshPostgres.Test.ComplexCalculations.Documentation do + public?(true) sort(timestamp: :desc, inserted_at: :desc) end end diff --git a/test/support/concat.ex b/test/support/concat.ex index af107ad..353bbfa 100644 --- a/test/support/concat.ex +++ b/test/support/concat.ex @@ -1,6 +1,6 @@ defmodule AshPostgres.Test.Concat do @moduledoc false - use Ash.Calculation + use Ash.Resource.Calculation require Ash.Query def init(opts) do @@ -11,16 +11,16 @@ defmodule AshPostgres.Test.Concat do end end - def expression(opts, %{separator: separator}) do + def expression(opts, %{arguments: %{separator: separator}}) do Enum.reduce(opts[:keys], nil, fn key, expr -> if expr do if separator do - Ash.Query.expr(^expr <> ^separator <> ref(^key)) + expr(^expr <> ^separator <> ^ref(key)) else - Ash.Query.expr(^expr <> ref(^key)) + expr(^expr <> ^ref(key)) end else - Ash.Query.expr(ref(^key)) + expr(^ref(key)) end end) end diff --git a/test/support/domain.ex b/test/support/domain.ex new file mode 100644 index 0000000..9b7e905 --- /dev/null +++ b/test/support/domain.ex @@ -0,0 +1,27 @@ +defmodule AshPostgres.Test.Domain do + @moduledoc false + use Ash.Domain + + resources do + resource(AshPostgres.Test.Post) + resource(AshPostgres.Test.Comment) + resource(AshPostgres.Test.IntegerPost) + resource(AshPostgres.Test.Rating) + resource(AshPostgres.Test.PostLink) + resource(AshPostgres.Test.PostView) + resource(AshPostgres.Test.Author) + resource(AshPostgres.Test.Profile) + resource(AshPostgres.Test.User) + resource(AshPostgres.Test.Account) + resource(AshPostgres.Test.Organization) + resource(AshPostgres.Test.Manager) + resource(AshPostgres.Test.Entity) + resource(AshPostgres.Test.TempEntity) + resource(AshPostgres.Test.Record) + resource(AshPostgres.Test.PostFollower) + end + + authorization do + authorize(:when_requested) + end +end diff --git a/test/support/multitenancy/api.ex b/test/support/multitenancy/api.ex deleted file mode 100644 index b0bebca..0000000 --- a/test/support/multitenancy/api.ex +++ /dev/null @@ -1,8 +0,0 @@ -defmodule AshPostgres.MultitenancyTest.Api do - @moduledoc false - use Ash.Api - - resources do - registry(AshPostgres.MultitenancyTest.Registry) - end -end diff --git a/test/support/multitenancy/domain.ex b/test/support/multitenancy/domain.ex new file mode 100644 index 0000000..6384d0d --- /dev/null +++ b/test/support/multitenancy/domain.ex @@ -0,0 +1,10 @@ +defmodule AshPostgres.MultitenancyTest.Domain do + @moduledoc false + use Ash.Domain + + resources do + resource(AshPostgres.MultitenancyTest.Org) + resource(AshPostgres.MultitenancyTest.User) + resource(AshPostgres.MultitenancyTest.Post) + end +end diff --git a/test/support/multitenancy/registry.ex b/test/support/multitenancy/registry.ex deleted file mode 100644 index 0a8eef5..0000000 --- a/test/support/multitenancy/registry.ex +++ /dev/null @@ -1,10 +0,0 @@ -defmodule AshPostgres.MultitenancyTest.Registry do - @moduledoc false - use Ash.Registry - - entries do - entry(AshPostgres.MultitenancyTest.Org) - entry(AshPostgres.MultitenancyTest.User) - entry(AshPostgres.MultitenancyTest.Post) - end -end diff --git a/test/support/multitenancy/resources/org.ex b/test/support/multitenancy/resources/org.ex index fc04c8c..1ac913a 100644 --- a/test/support/multitenancy/resources/org.ex +++ b/test/support/multitenancy/resources/org.ex @@ -1,6 +1,7 @@ defmodule AshPostgres.MultitenancyTest.Org do @moduledoc false use Ash.Resource, + domain: AshPostgres.MultitenancyTest.Domain, data_layer: AshPostgres.DataLayer identities do @@ -9,10 +10,12 @@ defmodule AshPostgres.MultitenancyTest.Org do attributes do uuid_primary_key(:id, writable?: true) - attribute(:name, :string) + attribute(:name, :string, public?: true) end actions do + default_accept(:*) + defaults([:create, :read, :update, :destroy]) end @@ -33,8 +36,15 @@ defmodule AshPostgres.MultitenancyTest.Org do end relationships do - has_many(:posts, AshPostgres.MultitenancyTest.Post, destination_attribute: :org_id) - has_many(:users, AshPostgres.MultitenancyTest.User, destination_attribute: :org_id) + has_many(:posts, AshPostgres.MultitenancyTest.Post, + destination_attribute: :org_id, + public?: true + ) + + has_many(:users, AshPostgres.MultitenancyTest.User, + destination_attribute: :org_id, + public?: true + ) end def tenant("org_" <> tenant) do diff --git a/test/support/multitenancy/resources/post.ex b/test/support/multitenancy/resources/post.ex index 963e54b..84452d8 100644 --- a/test/support/multitenancy/resources/post.ex +++ b/test/support/multitenancy/resources/post.ex @@ -1,6 +1,7 @@ defmodule AshPostgres.MultitenancyTest.Post do @moduledoc false use Ash.Resource, + domain: AshPostgres.MultitenancyTest.Domain, data_layer: AshPostgres.DataLayer, authorizers: [Ash.Policy.Authorizer] @@ -17,10 +18,12 @@ defmodule AshPostgres.MultitenancyTest.Post do attributes do uuid_primary_key(:id, writable?: true) - attribute(:name, :string) + attribute(:name, :string, public?: true) end actions do + default_accept(:*) + defaults([:create, :read, :update, :destroy]) update(:update_with_policy) @@ -38,8 +41,14 @@ defmodule AshPostgres.MultitenancyTest.Post do end relationships do - belongs_to(:org, AshPostgres.MultitenancyTest.Org) - belongs_to(:user, AshPostgres.MultitenancyTest.User) - has_one(:self, __MODULE__, destination_attribute: :id, source_attribute: :id) + belongs_to(:org, AshPostgres.MultitenancyTest.Org) do + public?(true) + end + + belongs_to(:user, AshPostgres.MultitenancyTest.User) do + public?(true) + end + + has_one(:self, __MODULE__, destination_attribute: :id, source_attribute: :id, public?: true) end end diff --git a/test/support/multitenancy/resources/user.ex b/test/support/multitenancy/resources/user.ex index 9fd1c41..05ab967 100644 --- a/test/support/multitenancy/resources/user.ex +++ b/test/support/multitenancy/resources/user.ex @@ -1,12 +1,13 @@ defmodule AshPostgres.MultitenancyTest.User do @moduledoc false use Ash.Resource, + domain: AshPostgres.MultitenancyTest.Domain, data_layer: AshPostgres.DataLayer attributes do uuid_primary_key(:id, writable?: true) - attribute(:name, :string) - attribute(:org_id, :uuid) + attribute(:name, :string, public?: true) + attribute(:org_id, :uuid, public?: true) end postgres do @@ -15,6 +16,8 @@ defmodule AshPostgres.MultitenancyTest.User do end actions do + default_accept(:*) + defaults([:create, :read, :update, :destroy]) end @@ -28,7 +31,9 @@ defmodule AshPostgres.MultitenancyTest.User do end relationships do - belongs_to(:org, AshPostgres.MultitenancyTest.Org) + belongs_to(:org, AshPostgres.MultitenancyTest.Org) do + public?(true) + end end def parse_tenant("org_" <> id), do: id diff --git a/test/support/registry.ex b/test/support/registry.ex deleted file mode 100644 index 9502fd6..0000000 --- a/test/support/registry.ex +++ /dev/null @@ -1,23 +0,0 @@ -defmodule AshPostgres.Test.Registry do - @moduledoc false - use Ash.Registry - - entries do - entry(AshPostgres.Test.Post) - entry(AshPostgres.Test.Comment) - entry(AshPostgres.Test.IntegerPost) - entry(AshPostgres.Test.Rating) - entry(AshPostgres.Test.PostLink) - entry(AshPostgres.Test.PostView) - entry(AshPostgres.Test.Author) - entry(AshPostgres.Test.Profile) - entry(AshPostgres.Test.User) - entry(AshPostgres.Test.Account) - entry(AshPostgres.Test.Organization) - entry(AshPostgres.Test.Manager) - entry(AshPostgres.Test.Entity) - entry(AshPostgres.Test.TempEntity) - entry(AshPostgres.Test.Record) - entry(AshPostgres.Test.PostFollower) - end -end diff --git a/test/support/relationships/comments_containing_title.ex b/test/support/relationships/comments_containing_title.ex index e0ca6a5..a58a6b9 100644 --- a/test/support/relationships/comments_containing_title.ex +++ b/test/support/relationships/comments_containing_title.ex @@ -13,7 +13,7 @@ defmodule AshPostgres.Test.Post.CommentsContainingTitle do query |> Ash.Query.filter(post_id in ^post_ids) |> Ash.Query.filter(contains(title, post.title)) - |> AshPostgres.Test.Api.read!(actor: actor, authorize?: authorize?) + |> Ash.read!(actor: actor, authorize?: authorize?) |> Enum.group_by(& &1.post_id)} end diff --git a/test/support/resources/account.ex b/test/support/resources/account.ex index 7f30bf2..c771b9c 100644 --- a/test/support/resources/account.ex +++ b/test/support/resources/account.ex @@ -1,8 +1,12 @@ defmodule AshPostgres.Test.Account do @moduledoc false - use Ash.Resource, data_layer: AshPostgres.DataLayer + use Ash.Resource, + domain: AshPostgres.Test.Domain, + data_layer: AshPostgres.DataLayer actions do + default_accept(:*) + defaults([:create, :read, :update, :destroy]) end @@ -12,7 +16,7 @@ defmodule AshPostgres.Test.Account do attributes do uuid_primary_key(:id) - attribute(:is_active, :boolean) + attribute(:is_active, :boolean, public?: true) end calculations do @@ -30,6 +34,8 @@ defmodule AshPostgres.Test.Account do end relationships do - belongs_to(:user, AshPostgres.Test.User) + belongs_to(:user, AshPostgres.Test.User) do + public?(true) + end end end diff --git a/test/support/resources/author.ex b/test/support/resources/author.ex index 51d3218..3c2dd82 100644 --- a/test/support/resources/author.ex +++ b/test/support/resources/author.ex @@ -1,11 +1,12 @@ defmodule AshPostgres.Test.Author do @moduledoc false use Ash.Resource, + domain: AshPostgres.Test.Domain, data_layer: AshPostgres.DataLayer defmodule RuntimeFullName do @moduledoc false - use Ash.Calculation + use Ash.Resource.Calculation def calculate(records, _, _) do Enum.map(records, fn record -> @@ -21,21 +22,29 @@ defmodule AshPostgres.Test.Author do attributes do uuid_primary_key(:id, writable?: true) - attribute(:first_name, :string) - attribute(:last_name, :string) - attribute(:bio, AshPostgres.Test.Bio) - attribute(:badges, {:array, :atom}) + attribute(:first_name, :string, public?: true) + attribute(:last_name, :string, public?: true) + attribute(:bio, AshPostgres.Test.Bio, public?: true) + attribute(:badges, {:array, :atom}, public?: true) end actions do + default_accept(:*) + defaults([:create, :read, :update, :destroy]) end relationships do - has_one(:profile, AshPostgres.Test.Profile) - has_many(:posts, AshPostgres.Test.Post) + has_one(:profile, AshPostgres.Test.Profile) do + public?(true) + end + + has_many(:posts, AshPostgres.Test.Post) do + public?(true) + end has_many :authors_with_same_first_name, __MODULE__ do + public?(true) source_attribute(:first_name) destination_attribute(:first_name) filter(expr(parent(id) != id)) diff --git a/test/support/resources/bio.ex b/test/support/resources/bio.ex index 9f89fbe..59dd2df 100644 --- a/test/support/resources/bio.ex +++ b/test/support/resources/bio.ex @@ -3,15 +3,18 @@ defmodule AshPostgres.Test.Bio do use Ash.Resource, data_layer: :embedded actions do + default_accept(:*) + defaults([:create, :read, :update, :destroy]) end attributes do - attribute(:title, :string) - attribute(:bio, :string) - attribute(:years_of_experience, :integer) + attribute(:title, :string, public?: true) + attribute(:bio, :string, public?: true) + attribute(:years_of_experience, :integer, public?: true) attribute :list_of_strings, {:array, :string} do + public?(true) allow_nil?(true) default(nil) end diff --git a/test/support/resources/comment.ex b/test/support/resources/comment.ex index a7029ac..c8888a8 100644 --- a/test/support/resources/comment.ex +++ b/test/support/resources/comment.ex @@ -1,6 +1,7 @@ defmodule AshPostgres.Test.Comment do @moduledoc false use Ash.Resource, + domain: AshPostgres.Test.Domain, data_layer: AshPostgres.DataLayer, authorizers: [ Ash.Policy.Authorizer @@ -23,6 +24,7 @@ defmodule AshPostgres.Test.Comment do end actions do + default_accept(:*) defaults([:read, :update, :destroy]) create :create do @@ -35,10 +37,10 @@ defmodule AshPostgres.Test.Comment do attributes do uuid_primary_key(:id) - attribute(:title, :string) - attribute(:likes, :integer) - attribute(:arbitrary_timestamp, :utc_datetime_usec) - create_timestamp(:created_at, writable?: true) + attribute(:title, :string, public?: true) + attribute(:likes, :integer, public?: true) + attribute(:arbitrary_timestamp, :utc_datetime_usec, public?: true) + create_timestamp(:created_at, writable?: true, public?: true) end aggregates do @@ -49,15 +51,22 @@ defmodule AshPostgres.Test.Comment do end relationships do - belongs_to(:post, AshPostgres.Test.Post) - belongs_to(:author, AshPostgres.Test.Author) + belongs_to(:post, AshPostgres.Test.Post) do + public?(true) + end + + belongs_to(:author, AshPostgres.Test.Author) do + public?(true) + end has_many(:ratings, AshPostgres.Test.Rating, + public?: true, destination_attribute: :resource_id, relationship_context: %{data_layer: %{table: "comment_ratings"}} ) has_many(:popular_ratings, AshPostgres.Test.Rating, + public?: true, destination_attribute: :resource_id, relationship_context: %{data_layer: %{table: "comment_ratings"}}, filter: expr(score > 5) diff --git a/test/support/resources/entity.ex b/test/support/resources/entity.ex index e021820..732f760 100644 --- a/test/support/resources/entity.ex +++ b/test/support/resources/entity.ex @@ -2,14 +2,15 @@ defmodule AshPostgres.Test.Entity do @moduledoc false use Ash.Resource, + domain: AshPostgres.Test.Domain, data_layer: AshPostgres.DataLayer attributes do uuid_primary_key(:id) - attribute(:full_name, :string, allow_nil?: false) + attribute(:full_name, :string, allow_nil?: false, public?: true) - timestamps(private?: false) + timestamps(public?: true) end postgres do @@ -18,6 +19,8 @@ defmodule AshPostgres.Test.Entity do end actions do + default_accept(:*) + defaults([:create, :read]) read :read_from_temp do diff --git a/test/support/resources/integer_post.ex b/test/support/resources/integer_post.ex index 89dc9f4..13b37b4 100644 --- a/test/support/resources/integer_post.ex +++ b/test/support/resources/integer_post.ex @@ -1,6 +1,7 @@ defmodule AshPostgres.Test.IntegerPost do @moduledoc false use Ash.Resource, + domain: AshPostgres.Test.Domain, data_layer: AshPostgres.DataLayer postgres do @@ -9,11 +10,13 @@ defmodule AshPostgres.Test.IntegerPost do end actions do + default_accept(:*) + defaults([:create, :read, :update, :destroy]) end attributes do integer_primary_key(:id) - attribute(:title, :string) + attribute(:title, :string, public?: true) end end diff --git a/test/support/resources/manager.ex b/test/support/resources/manager.ex index bdfe070..43105c2 100644 --- a/test/support/resources/manager.ex +++ b/test/support/resources/manager.ex @@ -1,6 +1,7 @@ defmodule AshPostgres.Test.Manager do @moduledoc false use Ash.Resource, + domain: AshPostgres.Test.Domain, data_layer: AshPostgres.DataLayer postgres do @@ -9,6 +10,8 @@ defmodule AshPostgres.Test.Manager do end actions do + default_accept(:*) + defaults([:read, :update, :destroy]) create :create do @@ -25,14 +28,15 @@ defmodule AshPostgres.Test.Manager do attributes do uuid_primary_key(:id) - attribute(:name, :string) - attribute(:code, :string, allow_nil?: false) - attribute(:must_be_present, :string, allow_nil?: false) - attribute(:role, :string) + attribute(:name, :string, public?: true) + attribute(:code, :string, allow_nil?: false, public?: true) + attribute(:must_be_present, :string, allow_nil?: false, public?: true) + attribute(:role, :string, public?: true) end relationships do belongs_to :organization, AshPostgres.Test.Organization do + public?(true) attribute_writable?(true) end end diff --git a/test/support/resources/organization.ex b/test/support/resources/organization.ex index ada81e2..6c7346a 100644 --- a/test/support/resources/organization.ex +++ b/test/support/resources/organization.ex @@ -1,6 +1,7 @@ defmodule AshPostgres.Test.Organization do @moduledoc false use Ash.Resource, + domain: AshPostgres.Test.Domain, data_layer: AshPostgres.DataLayer, authorizers: [ Ash.Policy.Authorizer @@ -24,17 +25,27 @@ defmodule AshPostgres.Test.Organization do end actions do + default_accept(:*) + defaults([:create, :read, :update, :destroy]) end attributes do uuid_primary_key(:id, writable?: true) - attribute(:name, :string) + attribute(:name, :string, public?: true) end relationships do - has_many(:users, AshPostgres.Test.User) - has_many(:posts, AshPostgres.Test.Post) - has_many(:managers, AshPostgres.Test.Manager) + has_many(:users, AshPostgres.Test.User) do + public?(true) + end + + has_many(:posts, AshPostgres.Test.Post) do + public?(true) + end + + has_many(:managers, AshPostgres.Test.Manager) do + public?(true) + end end end diff --git a/test/support/resources/post.ex b/test/support/resources/post.ex index 684a7b9..6c21a51 100644 --- a/test/support/resources/post.ex +++ b/test/support/resources/post.ex @@ -16,6 +16,7 @@ end defmodule AshPostgres.Test.Post do @moduledoc false use Ash.Resource, + domain: AshPostgres.Test.Domain, data_layer: AshPostgres.DataLayer, authorizers: [ Ash.Policy.Authorizer @@ -73,7 +74,14 @@ defmodule AshPostgres.Test.Post do end actions do - defaults([:update, :destroy]) + default_accept(:*) + + defaults([:destroy]) + + update :update do + primary?(true) + require_atomic?(false) + end read :title_is_foo do filter(expr(title == "foo")) @@ -113,6 +121,7 @@ defmodule AshPostgres.Test.Post do end update :manual_update do + require_atomic?(false) manual(AshPostgres.Test.Post.ManualUpdate) end end @@ -125,83 +134,103 @@ defmodule AshPostgres.Test.Post do uuid_primary_key(:id, writable?: true) attribute(:title, :string) do + public?(true) source(:title_column) end - attribute(:score, :integer) - attribute(:public, :boolean) - attribute(:category, :ci_string) - attribute(:type, :atom, default: :sponsored, private?: true, writable?: false) - attribute(:price, :integer) - attribute(:decimal, :decimal, default: Decimal.new(0)) - attribute(:status, AshPostgres.Test.Types.Status) - attribute(:status_enum, AshPostgres.Test.Types.StatusEnum) - attribute(:status_enum_no_cast, AshPostgres.Test.Types.StatusEnumNoCast, source: :status_enum) - attribute(:point, AshPostgres.Test.Point) - attribute(:composite_point, AshPostgres.Test.CompositePoint) - attribute(:stuff, :map) - attribute(:list_of_stuff, {:array, :map}) - attribute(:uniq_one, :string) - attribute(:uniq_two, :string) - attribute(:uniq_custom_one, :string) - attribute(:uniq_custom_two, :string) + attribute(:score, :integer, public?: true) + attribute(:public, :boolean, public?: true) + attribute(:category, :ci_string, public?: true) + attribute(:type, :atom, default: :sponsored, writable?: false, public?: false) + attribute(:price, :integer, public?: true) + attribute(:decimal, :decimal, default: Decimal.new(0), public?: true) + attribute(:status, AshPostgres.Test.Types.Status, public?: true) + attribute(:status_enum, AshPostgres.Test.Types.StatusEnum, public?: true) + + attribute(:status_enum_no_cast, AshPostgres.Test.Types.StatusEnumNoCast, + source: :status_enum, + public?: true + ) + + attribute(:point, AshPostgres.Test.Point, public?: true) + attribute(:composite_point, AshPostgres.Test.CompositePoint, public?: true) + attribute(:stuff, :map, public?: true) + attribute(:list_of_stuff, {:array, :map}, public?: true) + attribute(:uniq_one, :string, public?: true) + attribute(:uniq_two, :string, public?: true) + attribute(:uniq_custom_one, :string, public?: true) + attribute(:uniq_custom_two, :string, public?: true) attribute :list_containing_nils, {:array, :string} do + public?(true) constraints(nil_items?: true) end - create_timestamp(:created_at) - update_timestamp(:updated_at) + create_timestamp(:created_at, writable?: true, public?: true) + update_timestamp(:updated_at, writable?: true, public?: true) end code_interface do - define_for(AshPostgres.Test.Api) + define(:create, args: [:title]) define(:get_by_id, action: :read, get_by: [:id]) define(:increment_score, args: [{:optional, :amount}]) + define(:destroy) + define(:bulk_create, bulk?: true, action: :create) end relationships do belongs_to :organization, AshPostgres.Test.Organization do + public?(true) attribute_writable?(true) end - belongs_to(:author, AshPostgres.Test.Author) + belongs_to(:author, AshPostgres.Test.Author) do + public?(true) + end has_many :posts_with_matching_title, __MODULE__ do + public?(true) no_attributes?(true) filter(expr(parent(title) == title and parent(id) != id)) end - has_many(:comments, AshPostgres.Test.Comment, destination_attribute: :post_id) + has_many(:comments, AshPostgres.Test.Comment, destination_attribute: :post_id, public?: true) has_many :comments_matching_post_title, AshPostgres.Test.Comment do + public?(true) filter(expr(title == parent_expr(title))) end has_many :popular_comments, AshPostgres.Test.Comment do + public?(true) destination_attribute(:post_id) filter(expr(likes > 10)) end has_many :comments_containing_title, AshPostgres.Test.Comment do + public?(true) manual(AshPostgres.Test.Post.CommentsContainingTitle) end has_many :comments_with_high_rating, AshPostgres.Test.Comment do + public?(true) filter(expr(ratings.score > 5)) end has_many(:ratings, AshPostgres.Test.Rating, + public?: true, destination_attribute: :resource_id, relationship_context: %{data_layer: %{table: "post_ratings"}} ) has_many(:post_links, AshPostgres.Test.PostLink, + public?: true, destination_attribute: :source_post_id, filter: [state: :active] ) many_to_many(:linked_posts, __MODULE__, + public?: true, through: AshPostgres.Test.PostLink, join_relationship: :post_links, source_attribute_on_join_resource: :source_post_id, @@ -209,13 +238,16 @@ defmodule AshPostgres.Test.Post do ) many_to_many(:followers, AshPostgres.Test.User, + public?: true, through: AshPostgres.Test.PostFollower, source_attribute_on_join_resource: :post_id, destination_attribute_on_join_resource: :follower_id, read_action: :active ) - has_many(:views, AshPostgres.Test.PostView) + has_many(:views, AshPostgres.Test.PostView) do + public?(true) + end end validations do @@ -483,10 +515,10 @@ end defmodule CalculatePostPriceString do @moduledoc false - use Ash.Calculation + use Ash.Resource.Calculation @impl true - def select(_, _, _), do: [:price] + def load(_, _, _), do: [:price] @impl true def calculate(records, _, _) do @@ -500,7 +532,7 @@ end defmodule CalculatePostPriceStringWithSymbol do @moduledoc false - use Ash.Calculation + use Ash.Resource.Calculation @impl true def load(_, _, _), do: [:price_string] @@ -524,7 +556,7 @@ defmodule AshPostgres.Test.Post.ManualUpdate do |> Ash.Changeset.for_update(:update, changeset.attributes) |> Ash.Changeset.force_change_attribute(:title, "manual") |> Ash.Changeset.load(:comments) - |> AshPostgres.Test.Api.update!() + |> Ash.update!() } end end diff --git a/test/support/resources/post_follower.ex b/test/support/resources/post_follower.ex index 850c75e..e60144b 100644 --- a/test/support/resources/post_follower.ex +++ b/test/support/resources/post_follower.ex @@ -1,6 +1,7 @@ defmodule AshPostgres.Test.PostFollower do @moduledoc false use Ash.Resource, + domain: AshPostgres.Test.Domain, data_layer: AshPostgres.DataLayer postgres do @@ -9,6 +10,8 @@ defmodule AshPostgres.Test.PostFollower do end actions do + default_accept(:*) + defaults([:create, :read, :update, :destroy]) end @@ -18,10 +21,12 @@ defmodule AshPostgres.Test.PostFollower do relationships do belongs_to :post, AshPostgres.Test.Post do + public?(true) allow_nil?(false) end belongs_to :follower, AshPostgres.Test.User do + public?(true) allow_nil?(false) end end diff --git a/test/support/resources/post_link.ex b/test/support/resources/post_link.ex index 22330d1..910486b 100644 --- a/test/support/resources/post_link.ex +++ b/test/support/resources/post_link.ex @@ -1,6 +1,7 @@ defmodule AshPostgres.Test.PostLink do @moduledoc false use Ash.Resource, + domain: AshPostgres.Test.Domain, data_layer: AshPostgres.DataLayer postgres do @@ -9,6 +10,8 @@ defmodule AshPostgres.Test.PostLink do end actions do + default_accept(:*) + defaults([:create, :read, :update, :destroy]) end @@ -18,6 +21,7 @@ defmodule AshPostgres.Test.PostLink do attributes do attribute :state, :atom do + public?(true) constraints(one_of: [:active, :archived]) default(:active) end @@ -25,11 +29,13 @@ defmodule AshPostgres.Test.PostLink do relationships do belongs_to :source_post, AshPostgres.Test.Post do + public?(true) allow_nil?(false) primary_key?(true) end belongs_to :destination_post, AshPostgres.Test.Post do + public?(true) allow_nil?(false) primary_key?(true) end diff --git a/test/support/resources/post_views.ex b/test/support/resources/post_views.ex index 31bedef..929fbb4 100644 --- a/test/support/resources/post_views.ex +++ b/test/support/resources/post_views.ex @@ -1,18 +1,23 @@ defmodule AshPostgres.Test.PostView do @moduledoc false - use Ash.Resource, data_layer: AshPostgres.DataLayer + use Ash.Resource, + domain: AshPostgres.Test.Domain, + data_layer: AshPostgres.DataLayer actions do + default_accept(:*) + defaults([:create, :read]) end attributes do create_timestamp(:time) - attribute(:browser, :atom, constraints: [one_of: [:firefox, :chrome, :edge]]) + attribute(:browser, :atom, constraints: [one_of: [:firefox, :chrome, :edge]], public?: true) end relationships do belongs_to :post, AshPostgres.Test.Post do + public?(true) allow_nil?(false) attribute_writable?(true) end diff --git a/test/support/resources/profile.ex b/test/support/resources/profile.ex index 33e5395..0455f9b 100644 --- a/test/support/resources/profile.ex +++ b/test/support/resources/profile.ex @@ -1,6 +1,7 @@ defmodule AshPostgres.Test.Profile do @moduledoc false use Ash.Resource, + domain: AshPostgres.Test.Domain, data_layer: AshPostgres.DataLayer postgres do @@ -11,14 +12,18 @@ defmodule AshPostgres.Test.Profile do attributes do uuid_primary_key(:id, writable?: true) - attribute(:description, :string) + attribute(:description, :string, public?: true) end actions do + default_accept(:*) + defaults([:create, :read, :update, :destroy]) end relationships do - belongs_to(:author, AshPostgres.Test.Author) + belongs_to(:author, AshPostgres.Test.Author) do + public?(true) + end end end diff --git a/test/support/resources/rating.ex b/test/support/resources/rating.ex index e0b87fc..0006ea0 100644 --- a/test/support/resources/rating.ex +++ b/test/support/resources/rating.ex @@ -1,6 +1,7 @@ defmodule AshPostgres.Test.Rating do @moduledoc false use Ash.Resource, + domain: AshPostgres.Test.Domain, data_layer: AshPostgres.DataLayer postgres do @@ -9,12 +10,14 @@ defmodule AshPostgres.Test.Rating do end actions do + default_accept(:*) + defaults([:create, :read, :update, :destroy]) end attributes do uuid_primary_key(:id) - attribute(:score, :integer) - attribute(:resource_id, :uuid) + attribute(:score, :integer, public?: true) + attribute(:resource_id, :uuid, public?: true) end end diff --git a/test/support/resources/record.ex b/test/support/resources/record.ex index 72bcbbe..19a5aa7 100644 --- a/test/support/resources/record.ex +++ b/test/support/resources/record.ex @@ -2,20 +2,22 @@ defmodule AshPostgres.Test.Record do @moduledoc false use Ash.Resource, + domain: AshPostgres.Test.Domain, data_layer: AshPostgres.DataLayer attributes do uuid_primary_key(:id) - attribute(:full_name, :string, allow_nil?: false) + attribute(:full_name, :string, allow_nil?: false, public?: true) - timestamps(private?: false) + timestamps(public?: true) end relationships do alias AshPostgres.Test.Entity has_one :entity, Entity do + public?(true) no_attributes?(true) read_action(:read_from_temp) @@ -30,6 +32,8 @@ defmodule AshPostgres.Test.Record do end actions do + default_accept(:*) + defaults([:create, :read]) end end diff --git a/test/support/resources/subquery/access.ex b/test/support/resources/subquery/access.ex index cc585e9..a3df653 100644 --- a/test/support/resources/subquery/access.ex +++ b/test/support/resources/subquery/access.ex @@ -3,6 +3,7 @@ defmodule AshPostgres.Test.Subquery.Access do alias AshPostgres.Test.Subquery.Parent use Ash.Resource, + domain: AshPostgres.Test.Subquery.ParentDomain, data_layer: AshPostgres.DataLayer, authorizers: [ Ash.Policy.Authorizer @@ -17,19 +18,19 @@ defmodule AshPostgres.Test.Subquery.Access do attributes do uuid_primary_key(:id) - attribute(:parent_id, :uuid) - attribute(:email, :string) + attribute(:parent_id, :uuid, public?: true) + attribute(:email, :string, public?: true) end code_interface do - define_for(AshPostgres.Test.Subquery.ParentApi) - define(:create) define(:read) end relationships do - belongs_to(:parent, Parent) + belongs_to(:parent, Parent) do + public?(true) + end end policies do @@ -39,6 +40,8 @@ defmodule AshPostgres.Test.Subquery.Access do end actions do + default_accept(:*) + defaults([:create, :update, :destroy]) read :read do diff --git a/test/support/resources/subquery/child.ex b/test/support/resources/subquery/child.ex index a85500d..cf089bd 100644 --- a/test/support/resources/subquery/child.ex +++ b/test/support/resources/subquery/child.ex @@ -3,6 +3,7 @@ defmodule AshPostgres.Test.Subquery.Child do alias AshPostgres.Test.Subquery.Through use Ash.Resource, + domain: AshPostgres.Test.Subquery.ChildDomain, data_layer: AshPostgres.DataLayer, authorizers: [ Ash.Policy.Authorizer @@ -15,18 +16,17 @@ defmodule AshPostgres.Test.Subquery.Child do attributes do uuid_primary_key(:id) - attribute(:state, :string) + attribute(:state, :string, public?: true) end code_interface do - define_for(AshPostgres.Test.Subquery.ChildApi) - define(:create) define(:read) end relationships do has_many :throughs, Through do + public?(true) source_attribute(:id) destination_attribute(:child_id) end @@ -48,6 +48,8 @@ defmodule AshPostgres.Test.Subquery.Child do end actions do + default_accept(:*) + defaults([:create, :read, :update, :destroy]) end end diff --git a/test/support/resources/subquery/child_api.ex b/test/support/resources/subquery/child_domain.ex similarity index 57% rename from test/support/resources/subquery/child_api.ex rename to test/support/resources/subquery/child_domain.ex index 320dc70..7e42733 100644 --- a/test/support/resources/subquery/child_api.ex +++ b/test/support/resources/subquery/child_domain.ex @@ -1,11 +1,15 @@ -defmodule AshPostgres.Test.Subquery.ChildApi do +defmodule AshPostgres.Test.Subquery.ChildDomain do @moduledoc false alias AshPostgres.Test.Subquery.Child alias AshPostgres.Test.Subquery.Through - use Ash.Api + use Ash.Domain resources do resource(Child) resource(Through) end + + authorization do + authorize(:when_requested) + end end diff --git a/test/support/resources/subquery/parent.ex b/test/support/resources/subquery/parent.ex index 33421c3..9de04b9 100644 --- a/test/support/resources/subquery/parent.ex +++ b/test/support/resources/subquery/parent.ex @@ -1,6 +1,7 @@ defmodule AshPostgres.Test.Subquery.Parent do @moduledoc false use Ash.Resource, + domain: AshPostgres.Test.Subquery.ParentDomain, data_layer: AshPostgres.DataLayer, authorizers: [ Ash.Policy.Authorizer @@ -15,22 +16,25 @@ defmodule AshPostgres.Test.Subquery.Parent do attributes do uuid_primary_key(:id) - attribute(:owner_email, :string) - attribute(:other_owner_email, :string) - attribute(:visible, :boolean) + attribute(:owner_email, :string, public?: true) + attribute(:other_owner_email, :string, public?: true) + attribute(:visible, :boolean, public?: true) end relationships do many_to_many :children, Child do + public?(true) through(Through) source_attribute(:id) source_attribute_on_join_resource(:parent_id) destination_attribute(:id) destination_attribute_on_join_resource(:child_id) - api(AshPostgres.Test.Subquery.ChildApi) + domain(AshPostgres.Test.Subquery.ChildDomain) end - has_many(:accesses, Access) + has_many(:accesses, Access) do + public?(true) + end end policies do @@ -48,8 +52,6 @@ defmodule AshPostgres.Test.Subquery.Parent do end code_interface do - define_for(AshPostgres.Test.Subquery.ParentApi) - define(:create) define(:read) @@ -57,6 +59,8 @@ defmodule AshPostgres.Test.Subquery.Parent do end actions do + default_accept(:*) + defaults([:create, :read, :update, :destroy]) end end diff --git a/test/support/resources/subquery/parent_api.ex b/test/support/resources/subquery/parent_domain.ex similarity index 57% rename from test/support/resources/subquery/parent_api.ex rename to test/support/resources/subquery/parent_domain.ex index 0bb99db..9d73f6a 100644 --- a/test/support/resources/subquery/parent_api.ex +++ b/test/support/resources/subquery/parent_domain.ex @@ -1,11 +1,15 @@ -defmodule AshPostgres.Test.Subquery.ParentApi do +defmodule AshPostgres.Test.Subquery.ParentDomain do @moduledoc false alias AshPostgres.Test.Subquery.Access alias AshPostgres.Test.Subquery.Parent - use Ash.Api + use Ash.Domain resources do resource(Parent) resource(Access) end + + authorization do + authorize(:when_requested) + end end diff --git a/test/support/resources/subquery/through.ex b/test/support/resources/subquery/through.ex index cc1cfe0..7f1e96e 100644 --- a/test/support/resources/subquery/through.ex +++ b/test/support/resources/subquery/through.ex @@ -2,9 +2,10 @@ defmodule AshPostgres.Test.Subquery.Through do @moduledoc false alias AshPostgres.Test.Subquery.Child alias AshPostgres.Test.Subquery.Parent - alias AshPostgres.Test.Subquery.ParentApi + alias AshPostgres.Test.Subquery.ParentDomain use Ash.Resource, + domain: AshPostgres.Test.Subquery.ChildDomain, data_layer: AshPostgres.DataLayer, authorizers: [ Ash.Policy.Authorizer @@ -17,29 +18,31 @@ defmodule AshPostgres.Test.Subquery.Through do attributes do attribute :parent_id, :uuid do + public?(true) primary_key?(true) allow_nil?(false) end attribute :child_id, :uuid do + public?(true) primary_key?(true) allow_nil?(false) end end code_interface do - define_for(AshPostgres.Test.Subquery.ChildApi) - define(:create) define(:read) end relationships do belongs_to :parent, Parent do - api(ParentApi) + public?(true) + domain(ParentDomain) end belongs_to :child, Child do + public?(true) source_attribute(:parent_id) destination_attribute(:id) end @@ -52,6 +55,8 @@ defmodule AshPostgres.Test.Subquery.Through do end actions do + default_accept(:*) + defaults([:create, :read, :update, :destroy]) end end diff --git a/test/support/resources/temp_entity.ex b/test/support/resources/temp_entity.ex index 0b5ba44..eb29bf1 100644 --- a/test/support/resources/temp_entity.ex +++ b/test/support/resources/temp_entity.ex @@ -2,14 +2,15 @@ defmodule AshPostgres.Test.TempEntity do @moduledoc false use Ash.Resource, + domain: AshPostgres.Test.Domain, data_layer: AshPostgres.DataLayer attributes do uuid_primary_key(:id) - attribute(:full_name, :string, allow_nil?: false) + attribute(:full_name, :string, allow_nil?: false, public?: true) - timestamps(private?: false) + timestamps(public?: true) end postgres do @@ -19,6 +20,8 @@ defmodule AshPostgres.Test.TempEntity do end actions do + default_accept(:*) + defaults([:create, :read]) end end diff --git a/test/support/resources/user.ex b/test/support/resources/user.ex index 453ae31..f416eb9 100644 --- a/test/support/resources/user.ex +++ b/test/support/resources/user.ex @@ -1,8 +1,12 @@ defmodule AshPostgres.Test.User do @moduledoc false - use Ash.Resource, data_layer: AshPostgres.DataLayer + use Ash.Resource, + domain: AshPostgres.Test.Domain, + data_layer: AshPostgres.DataLayer actions do + default_accept(:*) + defaults([:create, :read, :update, :destroy]) read :active do @@ -16,8 +20,8 @@ defmodule AshPostgres.Test.User do attributes do uuid_primary_key(:id) - attribute(:is_active, :boolean) - attribute(:name, :string) + attribute(:is_active, :boolean, public?: true) + attribute(:name, :string, public?: true) end postgres do @@ -27,9 +31,12 @@ defmodule AshPostgres.Test.User do relationships do belongs_to :organization, AshPostgres.Test.Organization do + public?(true) attribute_writable?(true) end - has_many(:accounts, AshPostgres.Test.Account) + has_many(:accounts, AshPostgres.Test.Account) do + public?(true) + end end end diff --git a/test/support/test_no_sandbox_repo.ex b/test/support/test_no_sandbox_repo.ex index 1fd79f6..81fef08 100644 --- a/test/support/test_no_sandbox_repo.ex +++ b/test/support/test_no_sandbox_repo.ex @@ -7,6 +7,10 @@ defmodule AshPostgres.TestNoSandboxRepo do send(self(), data) end + def pg_version do + Version.parse!(System.get_env("PG_VERSION") || "16.0.0") + end + def installed_extensions do ["ash-functions", "uuid-ossp", "pg_trgm", "citext", AshPostgres.TestCustomExtension] -- Application.get_env(:ash_postgres, :no_extensions, []) @@ -16,7 +20,7 @@ defmodule AshPostgres.TestNoSandboxRepo do Code.ensure_compiled(AshPostgres.MultitenancyTest.Org) AshPostgres.MultitenancyTest.Org - |> AshPostgres.MultitenancyTest.Api.read!() + |> Ash.read!() |> Enum.map(&"org_#{&1.id}") end end diff --git a/test/support/test_repo.ex b/test/support/test_repo.ex index 84781c6..07b2970 100644 --- a/test/support/test_repo.ex +++ b/test/support/test_repo.ex @@ -7,6 +7,10 @@ defmodule AshPostgres.TestRepo do send(self(), data) end + def pg_version do + Version.parse!(System.get_env("PG_VERSION") || "16.0.0") + end + def installed_extensions do ["ash-functions", "uuid-ossp", "pg_trgm", "citext", AshPostgres.TestCustomExtension] -- Application.get_env(:ash_postgres, :no_extensions, []) @@ -16,7 +20,7 @@ defmodule AshPostgres.TestRepo do Code.ensure_compiled(AshPostgres.MultitenancyTest.Org) AshPostgres.MultitenancyTest.Org - |> AshPostgres.MultitenancyTest.Api.read!() + |> Ash.read!() |> Enum.map(&"org_#{&1.id}") end end diff --git a/test/support/types/money.ex b/test/support/types/money.ex index fde16df..c1569be 100644 --- a/test/support/types/money.ex +++ b/test/support/types/money.ex @@ -5,11 +5,13 @@ defmodule AshPostgres.Test.Money do attributes do attribute :amount, :integer do + public?(true) allow_nil?(false) constraints(min: 0) end attribute :currency, :atom do + public?(true) constraints(one_of: [:eur, :usd]) end end diff --git a/test/transaction_test.exs b/test/transaction_test.exs index 60f9551..603fe0d 100644 --- a/test/transaction_test.exs +++ b/test/transaction_test.exs @@ -1,6 +1,6 @@ defmodule AshPostgres.Test.TransactionTest do use AshPostgres.RepoCase, async: false - alias AshPostgres.Test.{Api, Post} + alias AshPostgres.Test.Post require Ash.Query @@ -12,7 +12,7 @@ defmodule AshPostgres.Test.TransactionTest do raise "something bad happened" end) |> send_after_transaction_result() - |> Api.create() + |> Ash.create() end assert_receive {:error, @@ -32,12 +32,12 @@ defmodule AshPostgres.Test.TransactionTest do raise "something bad happened inside" end) |> send_after_transaction_result() - |> Api.create!() + |> Ash.create!() {:ok, result} end) |> send_after_transaction_result() - |> Api.create() + |> Ash.create() end assert_receive {:error, @@ -52,7 +52,7 @@ defmodule AshPostgres.Test.TransactionTest do Post |> Ash.Changeset.for_create(:create) |> send_after_transaction_result() - |> Api.create() + |> Ash.create() assert_receive {:ok, %Post{}} end @@ -68,17 +68,17 @@ defmodule AshPostgres.Test.TransactionTest do raise "something bad happened inside" end) |> send_after_transaction_result() - |> Api.create!() + |> Ash.create!() {:ok, result} end) |> Ash.Changeset.after_transaction(fn _changeset, {:error, _} -> Post |> Ash.Changeset.for_create(:create) - |> Api.create() + |> Ash.create() end) |> send_after_transaction_result() - |> Api.create() + |> Ash.create() assert_receive {:error, %RuntimeError{ diff --git a/test/type_test.exs b/test/type_test.exs index d81bba1..53c073e 100644 --- a/test/type_test.exs +++ b/test/type_test.exs @@ -1,31 +1,31 @@ defmodule AshPostgres.Test.TypeTest do use AshPostgres.RepoCase, async: false - alias AshPostgres.Test.{Api, Post} + alias AshPostgres.Test.Post require Ash.Query test "complex custom types can be used" do post = Post - |> Ash.Changeset.new(%{title: "title", point: {1.0, 2.0, 3.0}}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title", point: {1.0, 2.0, 3.0}}) + |> Ash.create!() assert post.point == {1.0, 2.0, 3.0} end test "complex custom types can be accessed with fragments" do Post - |> Ash.Changeset.new(%{title: "title", point: {1.0, 2.0, 3.0}}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title", point: {1.0, 2.0, 3.0}}) + |> Ash.create!() Post - |> Ash.Changeset.new(%{title: "title", point: {2.0, 1.0, 3.0}}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title", point: {2.0, 1.0, 3.0}}) + |> Ash.create!() assert [%{point: {2.0, 1.0, 3.0}}] = Post |> Ash.Query.filter(fragment("(?)[1] > (?)[2]", point, point)) - |> Api.read!() + |> Ash.read!() end test "uuids can be used as strings in fragments" do @@ -33,6 +33,6 @@ defmodule AshPostgres.Test.TypeTest do Post |> Ash.Query.filter(fragment("? = ?", id, type(^uuid, :uuid))) - |> Api.read!() + |> Ash.read!() end end diff --git a/test/unique_identity_test.exs b/test/unique_identity_test.exs index 5155785..e2d1f9a 100644 --- a/test/unique_identity_test.exs +++ b/test/unique_identity_test.exs @@ -1,34 +1,43 @@ defmodule AshPostgres.Test.UniqueIdentityTest do use AshPostgres.RepoCase, async: false - alias AshPostgres.Test.{Api, Post} + alias AshPostgres.Test.Post require Ash.Query test "unique constraint errors are properly caught" do post = Post - |> Ash.Changeset.new(%{title: "title"}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{title: "title"}) + |> Ash.create!() assert_raise Ash.Error.Invalid, ~r/Invalid value provided for id: has already been taken/, fn -> Post - |> Ash.Changeset.new(%{id: post.id}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{id: post.id}) + |> Ash.create!() end end test "a unique constraint can be used to upsert when the resource has a base filter" do post = Post - |> Ash.Changeset.new(%{title: "title", uniq_one: "fred", uniq_two: "astair", price: 10}) - |> Api.create!() + |> Ash.Changeset.for_create(:create, %{ + title: "title", + uniq_one: "fred", + uniq_two: "astair", + price: 10 + }) + |> Ash.create!() new_post = Post - |> Ash.Changeset.new(%{title: "title2", uniq_one: "fred", uniq_two: "astair"}) - |> Api.create!(upsert?: true, upsert_identity: :uniq_one_and_two) + |> Ash.Changeset.for_create(:create, %{ + title: "title2", + uniq_one: "fred", + uniq_two: "astair" + }) + |> Ash.create!(upsert?: true, upsert_identity: :uniq_one_and_two) assert new_post.id == post.id assert new_post.price == 10 diff --git a/test/upsert_test.exs b/test/upsert_test.exs index a6b8195..ca29bad 100644 --- a/test/upsert_test.exs +++ b/test/upsert_test.exs @@ -1,6 +1,6 @@ defmodule AshPostgres.Test.UpsertTest do use AshPostgres.RepoCase, async: false - alias AshPostgres.Test.{Api, Post} + alias AshPostgres.Test.Post require Ash.Query @@ -13,7 +13,7 @@ defmodule AshPostgres.Test.UpsertTest do id: id, title: "title2" }) - |> Api.create!(upsert?: true) + |> Ash.create!(upsert?: true) assert new_post.id == id assert new_post.created_at == new_post.updated_at @@ -24,7 +24,7 @@ defmodule AshPostgres.Test.UpsertTest do id: id, title: "title2" }) - |> Api.create!(upsert?: true) + |> Ash.create!(upsert?: true) assert updated_post.id == id assert updated_post.created_at == new_post.created_at @@ -40,7 +40,7 @@ defmodule AshPostgres.Test.UpsertTest do id: id, title: "title2" }) - |> Api.create!(upsert?: true) + |> Ash.create!(upsert?: true) assert new_post.id == id assert new_post.created_at == new_post.updated_at @@ -52,7 +52,7 @@ defmodule AshPostgres.Test.UpsertTest do title: "title2", decimal: Decimal.new(5) }) - |> Api.create!(upsert?: true) + |> Ash.create!(upsert?: true) assert updated_post.id == id assert Decimal.equal?(updated_post.decimal, Decimal.new(5)) diff --git a/test_snapshot_path/extensions.json b/test_snapshot_path/extensions.json deleted file mode 100644 index e084bbf..0000000 --- a/test_snapshot_path/extensions.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "installed": [ - "ash-functions", - "uuid-ossp", - "pg_trgm", - "citext", - "demo-functions_v1" - ], - "ash_functions_version": 3 -} \ No newline at end of file