replace upsert field with source in EXCLUDED fragment

This commit is contained in:
Barnabas Jovanovics 2023-12-19 14:39:01 +01:00
parent 5e0f3c4657
commit 9fa2dac4cf
4 changed files with 340 additions and 3 deletions

View file

@ -1365,7 +1365,7 @@ defmodule AshPostgres.DataLayer do
[],
fragment(
"COALESCE(EXCLUDED.?, ?)",
literal(^to_string(upsert_field)),
literal(^to_string(get_source_for_upsert_field(upsert_field, resource))),
^default
)
)}
@ -1377,12 +1377,27 @@ defmodule AshPostgres.DataLayer do
{upsert_field,
Ecto.Query.dynamic(
[],
fragment("EXCLUDED.?", literal(^to_string(upsert_field)))
fragment(
"EXCLUDED.?",
literal(^to_string(get_source_for_upsert_field(upsert_field, resource)))
)
)}
end
end)
end
defp get_source_for_upsert_field(field, resource) do
case resource
|> Ash.Resource.Info.attributes()
|> Enum.find(&(&1.name == field)) do
%{source: source} when not is_nil(source) ->
source
_ ->
field
end
end
@impl true
def create(resource, changeset) do
changeset = %{

View file

@ -0,0 +1,303 @@
{
"attributes": [
{
"default": "fragment(\"uuid_generate_v4()\")",
"size": null,
"type": "uuid",
"source": "id",
"references": null,
"allow_nil?": false,
"generated?": false,
"primary_key?": true
},
{
"default": "nil",
"size": null,
"type": "text",
"source": "title_column",
"references": null,
"allow_nil?": true,
"generated?": false,
"primary_key?": false
},
{
"default": "nil",
"size": null,
"type": "bigint",
"source": "score",
"references": null,
"allow_nil?": true,
"generated?": false,
"primary_key?": false
},
{
"default": "nil",
"size": null,
"type": "boolean",
"source": "public",
"references": null,
"allow_nil?": true,
"generated?": false,
"primary_key?": false
},
{
"default": "nil",
"size": null,
"type": "citext",
"source": "category",
"references": null,
"allow_nil?": true,
"generated?": false,
"primary_key?": false
},
{
"default": "\"sponsored\"",
"size": null,
"type": "text",
"source": "type",
"references": null,
"allow_nil?": true,
"generated?": false,
"primary_key?": false
},
{
"default": "nil",
"size": null,
"type": "bigint",
"source": "price",
"references": null,
"allow_nil?": true,
"generated?": false,
"primary_key?": false
},
{
"default": "\"0\"",
"size": null,
"type": "decimal",
"source": "decimal",
"references": null,
"allow_nil?": true,
"generated?": false,
"primary_key?": false
},
{
"default": "nil",
"size": null,
"type": "text",
"source": "status",
"references": null,
"allow_nil?": true,
"generated?": false,
"primary_key?": false
},
{
"default": "nil",
"size": null,
"type": "status",
"source": "status_enum",
"references": null,
"allow_nil?": true,
"generated?": false,
"primary_key?": false
},
{
"default": "nil",
"size": null,
"type": [
"array",
"float"
],
"source": "point",
"references": null,
"allow_nil?": true,
"generated?": false,
"primary_key?": false
},
{
"default": "nil",
"size": null,
"type": "custom_point",
"source": "composite_point",
"references": null,
"allow_nil?": true,
"generated?": false,
"primary_key?": false
},
{
"default": "nil",
"size": null,
"type": "map",
"source": "stuff",
"references": null,
"allow_nil?": true,
"generated?": false,
"primary_key?": false
},
{
"default": "nil",
"size": null,
"type": "text",
"source": "uniq_one",
"references": null,
"allow_nil?": true,
"generated?": false,
"primary_key?": false
},
{
"default": "nil",
"size": null,
"type": "text",
"source": "uniq_two",
"references": null,
"allow_nil?": true,
"generated?": false,
"primary_key?": false
},
{
"default": "nil",
"size": null,
"type": "text",
"source": "uniq_custom_one",
"references": null,
"allow_nil?": true,
"generated?": false,
"primary_key?": false
},
{
"default": "nil",
"size": null,
"type": "text",
"source": "uniq_custom_two",
"references": null,
"allow_nil?": true,
"generated?": false,
"primary_key?": false
},
{
"default": "fragment(\"now()\")",
"size": null,
"type": "utc_datetime_usec",
"source": "created_at",
"references": null,
"allow_nil?": false,
"generated?": false,
"primary_key?": false
},
{
"default": "fragment(\"now()\")",
"size": null,
"type": "utc_datetime_usec",
"source": "updated_at",
"references": null,
"allow_nil?": false,
"generated?": false,
"primary_key?": false
},
{
"default": "nil",
"size": null,
"type": "uuid",
"source": "organization_id",
"references": {
"name": "posts_organization_id_fkey",
"table": "orgs",
"schema": "public",
"on_delete": null,
"multitenancy": {
"global": null,
"strategy": null,
"attribute": null
},
"primary_key?": true,
"destination_attribute": "id",
"deferrable": false,
"match_type": null,
"match_with": null,
"on_update": null,
"destination_attribute_default": null,
"destination_attribute_generated": null
},
"allow_nil?": true,
"generated?": false,
"primary_key?": false
},
{
"default": "nil",
"size": null,
"type": "uuid",
"source": "author_id",
"references": {
"name": "posts_author_id_fkey",
"table": "authors",
"schema": "public",
"on_delete": null,
"multitenancy": {
"global": null,
"strategy": null,
"attribute": null
},
"primary_key?": true,
"destination_attribute": "id",
"deferrable": false,
"match_type": null,
"match_with": null,
"on_update": null,
"destination_attribute_default": null,
"destination_attribute_generated": null
},
"allow_nil?": true,
"generated?": false,
"primary_key?": false
}
],
"table": "posts",
"hash": "528A5F10049859ED0555DBAB43B0BA1D87A36F1EDB06FF9D9108F8E27F054898",
"repo": "Elixir.AshPostgres.TestRepo",
"identities": [
{
"name": "uniq_one_and_two",
"keys": [
"uniq_one",
"uniq_two"
],
"base_filter": "type = 'sponsored'",
"index_name": "posts_uniq_one_and_two_index"
}
],
"schema": null,
"check_constraints": [
{
"name": "price_must_be_positive",
"check": "price > 0",
"attribute": [
"price"
],
"base_filter": "type = 'sponsored'"
}
],
"custom_indexes": [
{
"message": "dude what the heck",
"name": null,
"table": null,
"include": null,
"prefix": null,
"where": null,
"fields": [
"uniq_custom_one",
"uniq_custom_two"
],
"unique": true,
"concurrently": true,
"using": null
}
],
"base_filter": "type = 'sponsored'",
"multitenancy": {
"global": null,
"strategy": null,
"attribute": null
},
"custom_statements": [],
"has_create_action": true
}

View file

@ -0,0 +1,17 @@
defmodule AshPostgres.TestRepo.Migrations.MigrateResources13 do
@moduledoc """
Updates resources based on their most recent snapshots.
This file was autogenerated with `mix ash_postgres.generate_migrations`
"""
use Ecto.Migration
def up do
rename table(:posts), :title, to: :title_column
end
def down do
rename table(:posts), :title_column, to: :title
end
end

View file

@ -74,7 +74,9 @@ defmodule AshPostgres.Test.Post do
attributes do
uuid_primary_key(:id, writable?: true)
attribute(:title, :string)
attribute(:title, :string) do
source :title_column
end
attribute(:score, :integer)
attribute(:public, :boolean)
attribute(:category, :ci_string)