This is a bug which is related to a change to user-defined functions in SQL 2019. Previously they were black boxes, but starting with SQL 2019, SQL Server now attempts to inline user-defined functions. This can have enormous benefit for performance.
However, in this case it leads to incorrect results, because is_member is evaluated against the current database and not the database in the UDF call.
I have submitted a bug report for this here:
https://feedback.azure.com/d365community/idea/655ed5a1-b7b6-ec11-a81c-6045bd7d1bee.
Below is a repro that demonstrates the issue. If you look through the repro, you also find the workaround: add the line WITH INLINE = OFF to the UDF.
Note: As Tom pointed out, this is the kind of repro we want. Images are difficult to copy and paste from.
CREATE LOGIN AnaCarvalho WITH PASSWORD = 'Vital-y-sua-moto'
CREATE DATABASE DB1
go
USE DB1
go
CREATE ROLE RoleA
CREATE USER AnaCarvalho
ALTER ROLE RoleA ADD MEMBER AnaCarvalho
go
CREATE OR ALTER FUNCTION MyIsMember(@GroupRoleName varchar(128))
RETURNS integer
-- WITH INLINE = OFF
AS
BEGIN
RETURN is_member(@GroupRoleName)
END
go
GRANT EXECUTE ON dbo.MyIsMember TO AnaCarvalho
go
CREATE DATABASE DB2
go
USE DB2
go
CREATE USER AnaCarvalho
go
EXECUTE AS LOGIN = 'AnaCarvalho'
go
SELECT DB1.dbo.MyIsMember('RoleA')
go
REVERT
go
USE tempdb
go
DROP DATABASE DB1
DROP DATABASE DB2
DROP LOGIN AnaCarvalho