PostgreSQL: Issue with passing array to procedure - java

I have a type as:
CREATE TYPE status_record AS
(
id bigint,
status boolean
);
A procedure that does some processing with an array of type as input parameter as:
CREATE OR REPLACE FUNCTION update_status(status_list status_record[])
RETURNS text AS
$BODY$
DECLARE
BEGIN
--does some processing
return 'SUCCESS';
end;$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
Finally I queried the procedure as:
select *
from update_status(cast(ARRAY[(385,false),(387,false)] as status_record[]));
Everything works fine in pgadmin. Later when I tried to call the same using Hibernate native SQL Query Ka Boom!!! The following is displayed:
org.postgresql.util.PSQLException:
ERROR: array value must start with "{" or dimension information
Final question: both ARRAY[--something] and {--something} does the same job?

Use an array literal (text representation of the array), since the array constructor ARRAY[...] has to be evaluated by Postgres:
SELECT update_status('{"(1,t)","(2,f)"}'::status_record[]);
Maybe even without the explicit cast:
SELECT update_status('{"(1,t)","(2,f)"}');
There were similar cases on SO before:
Pass array from node-postgres to plpgsql function
How to pass custom type array to Postgres function

Try to put the array and type initialization into a string, maybe you can then get around the problems with the obfuscation layer (aka ORM):
select update_status(cast('{"(1,true)", "(2,false)"}' as status_record[]));
I don't know Hibernate, so I can't tell if that will work.

Related

How to using like array of string HIBERNATE

I'm trying to pass an array of string as a parameter to my query but I get the following error
ERROR: operator does not exist: text ~~ record Dica: No operator matches the given name and argument type(s). You might need to add explicit type casts.
Here is my query
select * from table where value like any (array[?1]);
when I run it using hibernate the query is like:
select * from table where value like any (array[('%foo%', '%bar%', '%baz%')]);
There's a best way to pass my array as parameter?? I think that is important to say that my array is dynamic so i can't fiz it in my query.
use setParameterList method.
String queryStr = "select * from table where value in :valueList";
Query query = SessionFactory.getCurrentSession().createQuery(queryStr);
query.setParameterList("valueList", new Object[]{"%foo%","%bar%","%baz%"});
Please note that I used in clause and it doesn't support wildcard characters such as %.
First use createNativeQuery instead of createQuery as syntax is native to PSQL.
Second query syntax should be select * from table where value like any (array?1) as ?1 will be substituted by ['%foo%', '%bar%', '%baz%'], so your end query will match required PSQL syntax.
select * from table where value like any (array['%foo%', '%bar%', '%baz%'])
Firstly, your syntax is wrong.
Instead of:
select * from table where value like any (array[?1]);
You should use:
select * from table where value like any (:vals);
You cannot use array[?] or array[:var] to construct the variable. That is invalid syntax.
Secondly for Hibernate 5.2 up to 5.4 you can just add this dependency and you can use the most common object arrays directly. Primitive arrays are not supported and are not supposed to be.

SQL - Convert pipelined function to a java stored procedure/function

I've got the following types (A row type and a table of that kind of row):
CREATE TYPE t_tf_row AS OBJECT (
id NUMBER,
description VARCHAR2(50)
);
/
CREATE TYPE t_tf_tab IS TABLE OF t_tf_row;
/
And the following pipelined function which returns information for that kind of table (for this example it just prints a basic iteration).
CREATE OR REPLACE FUNCTION get_tab_ptf (p_rows IN NUMBER) RETURN t_tf_tab PIPELINED AS
BEGIN
FOR i IN 1 .. p_rows LOOP
PIPE ROW(t_tf_row(i, 'Description for ' || i));
END LOOP;
RETURN;
END;
/
Instead of using a pipelined function with its definition like above, I want to use a java stored procedure that does the exact same thing. How can I achieve the same output from this?
I want to be able to call the java stored procedure/function just like the following:
SELECT *
FROM TABLE(get_tab_ptf(10))
ORDER BY id DESC;
Thanks
PS: This question is meant for learning purposes only.

How to call a pl/SQL functuion having array as an argument using SQL

I have a SQL function named as IP_ELEARN_PERSON.F_GET_PERSON(int, string, array).
Now I want to run this function directly from sql developer and I am trying to execute this function like this --
select IP_ELEARN_PERSON.F_GET_PERSON(32433,'SOURCED',('ALL')) from dual;
Now the problem is when I am trying to execute this funtion I am getting the following errror --
ORA-06553: PLS-306: wrong number or types of arguments in call to 'F_GET_PERSON'
06553. 00000 - "PLS-%s: %s"
*Cause:
*Action:
Error at Line: 3 Column: 8
We were calling this function from java by using setArray method of the CallableStatment like this--
cstmt.setArray(4, new ObtainSqlArrayFromJava().returnSqlArray(
underlyingConn, roles));
So my doubt is, is the way I used to mention the array in the query right?
I went through many Stack Overflow posts but no where any thing was written for arrays as an argument.
CREATE TYPE string_list IS TABLE OF VARCHAR2(100);
/
CREATE FUNCTION F_GET_PERSON (
id INT,
type VARCHAR2,
array string_list
) RETURN INT
AS
BEGIN
RETURN 0;
END;
/
SELECT F_GET_PERSON( 1, 'SOURCED', string_list( 'ALL' ) )
FROM DUAL;
If you want some java code for passing an array as a bind variable to a PreparedStatement then you can look at my answer here. You should be able to easily adapt it to a CallableStatement.
As stated here:
http://docs.oracle.com/cd/E11882_01/appdev.112/e25519/composites.htm#LNPLS00501
Oracle supports the following collections types: associative array, VARRAY (variable-size array), and nested table.
You'll need to properly initialize the collection before passing it to the function.

JOOQ and PostgreSQL - call stored procedure with bytea parameter

I have a toy stored procedure in postgresql.
CREATE FUNCTION foo(bar bytea) RETURNS BOOLEAN AS
$$
BEGIN
RETURN TRUE;
END;
$$
LANGUAGE plpgsql;
Since I want to call it from Java code, I've generated Java object representing database routine using jooq-codegen-maven plugin. When I call it:
def select = DSL.select(Routines.test([1,2,3] as byte[]))
context.batch(s).execute()
it fails due to lack of procedure matching given name and list of parameters' types. It turns out that jooq generates incorrect query:
select "public"."test"(X'010203');
function public.test(bit) does not exist
Should be:
select "public"."test"('\x010203');
or:
select "public"."test"(E'\\01\\02\\03'::bytea);
Do you have any suggestion for a workaround? The only requirement is to have bytea in the end, because I want to insert a row with bytea column
into database.
The similar situation is for smallints. Jooq generates incorrect query (does not cast value ::smallint), so postgresql cannot match any procedure due to the type mismatch (integer given, but smallint expected). This case can be easily "solved" by changing parameter type to int and making the case in procedure's body.

Error Inserting Java Character object value into Oracle CHAR(1) column

I'm using a Spring jdbcTemplate.update(String sql, Object[] args) to execute a prepared insert statement on an Oracle database. One of the objects is a Character object containing the value 'Y', and the target column is of CHAR(1) type, but I'm receiving a
java.sql.SQLException: Invalid column type
exception.
I've debugged this backwards and forwards and there is no doubt that it is this one particular object that is causing the problem. The insert executes as expected when this Character Object is omitted.
I can also output the sql and Object[] values, copy the sql into sql developer, replace the value placeholders (?'s) with the actual values of the Objects, and the insert will work fine.
The sql (obfuscated to protect the guilty):
INSERT INTO SCHEMA.TABLE(NUMBER_COLUMN,VARCHAR_COLUMN,DATE_COLUMN,CHAR_COLUMN) VALUES (?,?,?,?);
The object values:
values[0] = [123]
values[1] = [Some String]
values[2] = [2012-04-19]
values[3] = [Y]
The combination run manually in sql developer and that works just fine:
INSERT INTO SCHEMA.TABLE(NUMBER_COLUMN,VARCHAR_COLUMN,DATE_COLUMN,CHAR_COLUMN) VALUES (123,'Some String','19-Apr-2012','Y');
The prepared statement sql itself is generated dynamically based on the non-null instance variable objects contained within a data transfer object (we want the database to handle generation of default values), so I can't accept any answers suggesting that I just rework the sql or insertion routine.
Anyone ever encountered this and can explain to me what's going on and how to fix it? It's frustratingly bizzare that I can't seem to insert a Character object into a CHAR(1) field. Any help would be much appreciated.
Sincerely, Longtime Lurker First-time Poster
There is no PreparedStatement.setXxx() that takes a character value, and the Oracle docs states that all JDBC character types map to Java Strings. Also, see http://docs.oracle.com/javase/1.3/docs/guide/jdbc/getstart/mapping.html#1039196, which does not include a mapping from Java char or Character to a JDBC type.
You will have to convert the value to a String.

Categories