Skip to content

Locks are not correctly verified in can? function #703

@sezaru

Description

@sezaru

Code of Conduct

  • I agree to follow this project's Code of Conduct

AI Policy

  • I agree to follow this project's AI Policy, or I agree that AI was not used while creating this issue.

Versions

Hex: 2.3.2
Elixir: 1.19.4
OTP: 28.3
ash_postgres 2.6.32

Operating system

NixOS

Current Behavior

Locks like "FOR UPDATE SKIP LOCKED" should be supported. But if you run AshPostgres.DataLayer.can?(Resource, {:lock, "FOR UPDATE SKIP LOCKED"}) you will get false.

Reproduction

Basically add Ash.Query.lock("FOR UPDATE SKIP LOCKED") to a read action in any resource thas uses AshPostgres.

Based on the lock function:

lock = "#{lock} SKIP LOCKED"

These types of lock are supported, but they will fail because ash will first call can? and that will return false.

The issue is in this code:

def can?(_, {:lock, string}) do

  def can?(_, {:lock, string}) do
    string = String.trim_trailing(string, " NOWAIT")

    String.upcase(string) in [
      "FOR UPDATE",
      "FOR NO KEY UPDATE",
      "FOR SHARE",
      "FOR KEY SHARE"
    ]
  end

As you can see, This can logic is incorrect, it should probably be something like this:

def can?(_, {:lock, string}) do
  string |> String.trim_trailing(" NOWAIT") |> String.upcase() |> can_lock?()
end

def can_lock?("FOR UPDATE" <> _), do: true
def can_lock?("FOR NO KEY UPDATE" <> _), do: true
def can_lock?("FOR SHARE" <> _), do: true
def can_lock?("FOR KEY SHARE" <> _), do: true
def can_lock?(_), do: false

Expected Behavior

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions