Vishal
Vishal

Reputation: 123

Postgres: Passing custom types from Java to postgres function

I have a postgres function which takes a complex user defined type as an input.

CREATE OR REPLACE FUNCTION addUser(user IN O_USER) RETURNS VOID
AS
$$
BEGIN

end;
$$ language plpgsql;

CREATE TYPE O_USER AS (
  id NUMERIC,
  name VARCHAR(50),
  addresses O_ADDRESS[]
);


CREATE TYPE O_ADDRESS AS (
  id NUMERIC,
  city VARCHAR(50)
);

Now I need to call the function from Java. What I understood is that I need to pass a String which will be typecasted to the UDT by db.

When I am passing the user without the address, then its working fine. But if I pass the array of address as well, then it is giving me the error.

ERROR:  malformed array literal: "{(1"
DETAIL:  Unexpected end of input.
SQL state: 22P02
Character: 23

I could reproduce the issue with the postgres select statement as well. For example following works fine

Select * from addUser('(1, "Vishal", {})');

But when I pass the addresses, then its a problem

Select * from addUser('(1, "Vishal", {(1,"tet")})');
Select * from addUser('(1, "Vishal", {"(1,)"})');
Select * from addUser('(1, "Vishal", {"(1,null)"})')

I believe I am not able to construct the string properly. Any idea what is wrong here?

Update

Java code to call the function

import org.springframework.jdbc.core.SqlParameter;
import org.springframework.jdbc.object.StoredProcedure;

import javax.sql.DataSource;
import java.sql.Types;
import java.util.HashMap;
import java.util.Map;

public class AddUserProcedurePostgres extends StoredProcedure {

    public AddUserProcedurePostgres(DataSource dataSource) {
        super(dataSource, "addUser");
        setFunction(true);

        declareParameter(new SqlParameter("i_User", Types.OTHER, "O_USER"));

        compile();
    }

    public void execute() {

        Map<String, Object> input = new HashMap<>();
        input.put("i_User", "(1, Vishal, array[(1,tet)]::O_ADDRESS[])");

        execute(input);
    }

}

Error returned by the jdbc is:

Caused by: org.postgresql.util.PSQLException: ERROR: malformed array literal: " array[(1"
  Detail: Array value must start with "{" or dimension information.

Upvotes: 3

Views: 3150

Answers (2)

Vishal
Vishal

Reputation: 123

I found 2 ways to pass the required value to the function:

  1. It is difficult to create the string of the UDT if its complex. The easiest way is to do the reverse engineering. Create the UDT in the plpgsql and print it. This way you will get the string that need to be pass from Java. Now in Java code write a logic to create such string.
  2. Another way is to pass the value in the json format and in the function, parse the json and construct the UDT by your own.

I choose the 2nd approach as it is easy to maintain.

Upvotes: 2

Rahul Sharma
Rahul Sharma

Reputation: 5995

You need to pass the O_ADDRESS array with array literal and typecasting the array to O_ADDRESS[]. The following select statements are valid.

select * from addUser(cast(row(1, 'Vishal', array[cast(row(1,'tet') as O_ADDRESS)]) as O_USER));

select * from addUser((1, 'Vishal', array[]::O_ADDRESS[])::O_USER);

select * from addUser((1, 'Vishal', array[]::O_ADDRESS[]));

select * from addUser((1, 'Vishal', array[(1,'tet')]::O_ADDRESS[]));

Upvotes: 1

Related Questions