persistence icon indicating copy to clipboard operation
persistence copied to clipboard

[JPQL] Support custom functions in joins

Open cnsgithub opened this issue 5 years ago • 4 comments

Invocations of custom functions are currently not supported in join paths.

What I would like to do is something like this (currently I am getting an syntax exception what is fine regarding to the spec not supporting it):

select e from entity e join function('tableValuedFunction', <param1>, ..., <paramN>) tvf on tvf.col=e.field

In SQL Server nomenclature, table-valued functions return a table object which can be joined as it was a regular table, see How to: Use Table-Valued User-Defined Functions

Other RDBMS provide similar constructs, e.g. Oracle table functions or PostgreSQL table functions.

My concrete use case is to overcome a SQL Server issue limiting the number of allowed prepared statement parameters to 2100. One of my workarounds worked very well without JPQL and was to provide an user-defined, table-valued function which takes an comma-separated string as input parameter and tokenizes the string by using a delimiter. That way, I need only one parameter to filter more than 2100 values for example:

TSQL:

create function [tokenize](@str nvarchar(max), @delim char(1) = ',') returns @tokens table (token nvarchar(max))
begin
 declare @i bigint 
 while len(@str) > 0
 begin
  set @i = charindex(@delim, @str)
  insert into @tokens select case @i when 0 then @str else left(@str, @i - 1) end
  set @str = case @i when 0 then '' else right(@str, len(@str) - @i) end
 end
 return
end
go

select * from tokenize('a,b,c', ',')

token
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
a
b
c

(3 rows affected)

I would like you to think about it, if it is worth to be supported in JPQL?

cnsgithub avatar May 07 '19 10:05 cnsgithub

Are you referring to JPA 2.2, section 4.6.17.3, but being able to declare this as a join_association_path_expression?

JPQL BNF

...
join ::= join_spec join_association_path_expression [AS] identification_variable [join_condition]
fetch_join ::= join_spec FETCH join_association_path_expression
join_spec::= [ LEFT [OUTER] | INNER ] JOIN
join_condition ::= ON conditional_expression
join_association_path_expression ::= join_collection_valued_path_expression | join_single_valued_path_expression | TREAT(join_collection_valued_path_expression AS subtype) | TREAT(join_single_valued_path_expression AS subtype)
join_collection_valued_path_expression::= identification_variable.{single_valued_embeddable_object_field.}*collection_valued_field
join_single_valued_path_expression::= identification_variable.{single_valued_embeddable_object_field.}*single_valued_object_field
...

dazey3 avatar May 07 '19 21:05 dazey3

Are you referring to JPA 2.2, section 4.6.17.3, but being able to declare this as a join_association_path_expression?

Yes, exactly.

cnsgithub avatar May 08 '19 05:05 cnsgithub

I don't see how this proposal makes sense.

  • We don't support joins to tables in HQL, and it's entirely unclear what the semantics of that would be. We support joins to JPA entities.
  • Furthermore, this seems to be a very clear example of a query that is easily written in native SQL and executed via createNativeQuery().

So it seems to me that this issue should be closed.

gavinking avatar May 05 '21 11:05 gavinking

Unless we consider representing the result type of table valued functions as entities/embeddables, which I think is nice.

beikov avatar May 05 '21 12:05 beikov

This issue has no votes. I believe that no JPA implementations support it. And I don't believe it makes sense to mix native SQL and JPQL in this fashion. Closing.

gavinking avatar Aug 21 '23 21:08 gavinking