Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Arrays in maps/structs get passed as dynamic(...) calls #39

Closed
dmitriid opened this issue Jun 11, 2024 · 5 comments
Closed

Arrays in maps/structs get passed as dynamic(...) calls #39

dmitriid opened this issue Jun 11, 2024 · 5 comments
Labels
bug Something isn't working

Comments

@dmitriid
Copy link

dmitriid commented Jun 11, 2024

Describe the bug

This started even in the 2.x branch of Ash towards "the end" of 2.x, I can't pinpoint the actual version now.

To Reproduce

Given this:

  attributes
    attribute :exif, :map do
      allow_nil? true
    end
  end

  actions
      update :set_exif do
        accept [:exif]
      end
    end
  end

  code_interface do
    define(:set_exif, do: args([:exif]))
  end

Then:

> Module.set_exif(%{ key: [1, 2, 3] }) # or Module.set_exif(%{ "key" => [1, 2, 3] })

    UPDATE "media" AS m0
    SET
        "exif" = $1
    WHERE (m0."id"::uuid = $2::uuid)
    RETURNING ... 

   [
     %{key: dynamic([], [1, 2, 3])},
     "003ef69e-ff55-4e8c-86f1-44fe13209bfd"
   ]

error: "** (Protocol.UndefinedError) protocol Jason.Encoder not implemented for dynamic([], [1, 2, 3])

All arrays are converted to dynamic(...) on any nesting level of the passed struct

Runtime

  • Elixir 1.16.2
  • Erlang/OTP 26 [erts-14.2.3]
  • Ubuntu 22.04.1 LTS
  • {:ash, "~> 3.0.10"}
  • {ash_postgres ~> 2.0.6}
  • ash_sql pointing to main branch. At the time of the report it's this commit: 9deb8e4

Additional context

This definitely worked at some point in 2.x. I have a blog post published on on May 3rd that uses code that uses this feature, and it's published correctly. So, sometime in the past month something changed :D

@zachdaniel
Copy link
Contributor

Hey @dmitriid can you try main of ash_sql? Thanks 🙇

@dmitriid
Copy link
Author

@zachdaniel I'm now running into a weird behavior (?) on my machine where it works with current released versions of ash, but not with ash_sql's main :)

I apologize in advance if I don't answer on this issue or look into code, I might not get to this until Thursday

Works

      {:ash, "~> 3.0.10"},
      {:ash_authentication, "~> 4.0.0"},
      {:ash_authentication_phoenix, "~> 2.0.0"},
      {:ash_archival, "~> 1.0.0"},
      {:ash_postgres, "~> 2.0.6"},
      {:ash_phoenix, "~> 2.0.2"},
> mix deps.get && mix deps.compile
> iex -S mix phx.server
>
> media = Quire.Blog.Media.get_by_id!("003ef69e-ff55-4e8c-86f1-44fe13209bfd")
#Quire.Blog.Media<...>
>  media |> Quire.Blog.Media.set_exif(%{ key: [1,2,3,4] })
QUERY OK source="media" db=15.6ms idle=1210.9ms

UPDATE "media" AS m0 SET 
    "exif" = (jsonb_build_object($1::varchar::varchar,($2::bigint[]::bigint[]))) 
WHERE (m0."id"::uuid = $3::uuid) 
RETURNING ...

 [:key, [1, 2, 3, 4], "003ef69e-ff55-4e8c-86f1-44fe13209bfd"]

Doesn't work

      {:ash, "~> 3.0.10"},
      {:ash_authentication, "~> 4.0.0"},
      {:ash_authentication_phoenix, "~> 2.0.0"},
      {:ash_archival, "~> 1.0.0"},
      {:ash_postgres, "~> 2.0.6"},
      {:ash_phoenix, "~> 2.0.2"},
      # override
      # TODO: remove
      {:ash_sql, git: "git@github.com:ash-project/ash_sql.git", branch: "main", override: true},
> mix deps.get && mix deps.compile
> iex -S mix phx.server
>
> media = Quire.Blog.Media.get_by_id!("003ef69e-ff55-4e8c-86f1-44fe13209bfd")
#Quire.Blog.Media<...>
>  media |> Quire.Blog.Media.set_exif(%{ key: [1,2,3,4] })

QUERY ERROR source="media" db=18.0ms queue=1.9ms idle=1401.5ms

UPDATE "media" AS m0 
SET
 "exif" = $1 
WHERE (m0."id"::uuid = $2::uuid) 
RETURNING ..

[
   %{key: dynamic([], [1, 2, 3, 4])}, "003ef69e-ff55-4e8c-86f1-44fe13209bfd"
]

@zachdaniel
Copy link
Contributor

please try main again when you get a chance.

@dmitriid
Copy link
Author

dmitriid commented Jun 12, 2024

@zachdaniel I got to code earlier, and all I can say: you're a wizard :)

* ash_sql 0.2.3 (git@github.com:ash-project/ash_sql.git - origin/main) (mix)
  locked at 64336d0 (branch: main)
  ok

And then:

> media = Quire.Blog.Media.get_by_id!("003ef69e-ff55-4e8c-86f1-44fe13209bfd")
#Quire.Blog.Media<>

> media |> Quire.Blog.Media.set_exif(%{ key: [1,2,3,4] })

QUERY OK source="media" db=27.1ms queue=1.9ms idle=1140.1ms

UPDATE "media" AS m0 
SET 
   "exif" = $1
WHERE (m0."id"::uuid = $2::uuid)
RETURNING ...

[
   %{key: [1, 2, 3, 4]},
   "003ef69e-ff55-4e8c-86f1-44fe13209bfd"
]

This also worked with a huge nested object:

Click to see large unformatted query hidden
QUERY OK source="media" db=27.7ms idle=730.4ms

UPDATE "media" AS m0 SET "exif" = $1 WHERE (m0."id"::uuid = $2::uuid)
RETURNING m0."id", m0."name", m0."type", m0."created_at", m0."exif"

[
%{:make => "Apple", 
:exif => %{:f_number => 1.6, :aperture_value => 1.356, :metering_mode => "Multi-segment", 
"exif tag(0x9011)" => "\"+01:00\"", :subsec_time_original => "620", :exposure_program => "Program AE", 
:exif_image_height => 3024, :white_balance => "Auto", :brightness_value => 0.858, 
:datetime_digitized => %{microsecond: [0, 0], second: 46, calendar: "Elixir.Calendar.ISO", month: 2, day: 2, year: 2024, minute: 42, hour: 16}, 
:flash => "Off, Did not fire", :lens_make => "Apple", :exposure_time => "1/50", 
:lens_model => "iPhone 12 Pro back triple camera 4.2mm f/1.6", :exposure_mode => "Auto", 
:exif_image_width => 4032, :image_unique_id => "ab5391ad468b27f30000000000000000", 
:subsec_time_digitized => "620", "exif tag(0xA460)" => "2", :focal_length_in_35mm_film => 26, 
:datetime_original => %{microsecond: [0, 0], second: 46, calendar: "Elixir.Calendar.ISO", month: 2, day: 2, year: 2024, 
minute: 42, hour: 16}, :exposure_bias_value => 0, "exif tag(0x9012)" => "\"+01:00\"", :subject_area => nil, 
:focal_length => 4.2, :sensing_method => "One-chip color area", :exif_version => "2.32", 
:maker_note => nil, :shutter_speed_value => 5.643, :lens_info => [1.54, 6, 1.6, 2.4], 
:iso_speed_ratings => 320, :time_offset => "+01:00", :scene_type => "Directly photographed"}, 
:model => "iPhone 12 Pro", :orientation => "Horizontal (normal)", 
:gps => %{gps_altitude: 107.175, gps_altitude_ref: 0, gps_area_information: nil, 
gps_date_stamp: "2024:02:02", gps_dest_bearing: 40.566, 
gps_dest_bearing_ref: "T", gps_dest_distance: nil, gps_dest_distance_ref: nil, 
gps_dest_latitude: nil, gps_dest_latitude_ref: nil, gps_dest_longitude: nil, gps_dest_longitude_ref: nil, 
gps_differential: nil, gps_dop: nil, gps_h_positioning_error: 9.94, gps_img_direction: 40.566, 
gps_img_direction_ref: "T", gps_latitude: [59, 14, 27.89], gps_latitude_ref: "N", 
gps_longitude: [18, 6, 5.47], gps_longitude_ref: "E", gps_map_datum: nil, 
gps_measure_mode: nil, gps_processing_method: nil, gps_satellites: nil, 
gps_speed: 0, gps_speed_ref: "K", gps_status: nil, gps_time_stamp: [15, 42, 42.82], 
gps_track: nil, gps_track_ref: nil, gps_version_id: nil}, :modify_date => %{microsecond: [0, 0], 
second: 46, calendar: "Elixir.Calendar.ISO", month: 2, day: 2, year: 2024, minute: 42, hour: 16}, 
:software => "17.2.1", :resolution_units => "Pixels/in", :y_resolution => 72, 
:x_resolution => 72, "tiff tag(0x13C)" => "\"iPhone 12 Pro\""}, 
"c109f166-7487-4700-8b1d-7de69d22f664"]

@zachdaniel
Copy link
Contributor

nice :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants