Groovy - Stored procedures that returns an OracleTypes.ARRAY - groovy-sql

I have an issue with Groovy SQL while calling a Stored procedure which returns OracleTypes.ARRAY as output parameter.
Java Code (Working fine):
callableStatement.registerOutParameter(37, OracleTypes.ARRAY, DEVICE_RAW_DATA_ARRAY);
OracleTypes.ARRAY registerOutParameter was configured in JDBC(callableStatement), it was working fine.
where as calling the same Stored procedure from Groovy SQL i am getting the following exception "java.sql.SQLException: ORA-03115: unsupported network datatype or representation"
Groovy Code:
import groovy.sql.Sql
def sqlStr = "{call prometheus.PKG_Device_FP_TLDID.SP_Save_Device_FP_Get_TLDID(?,?,?,?,?,?)}"
def params = [ ID_IN,
Request_ID_IN,
Session_ID_IN,
Sql.NUMERIC,
Sql.VARCHAR,
Sql.ARRAY // ARRAY Type output parameter -- Here I am getting Exception "java.sql.SQLException: ORA-03115: unsupported network datatype or representation" //
]
I tried with different DATA TYPES LIKE Sql.ARRAY // OracleTypes.ARRAY // Sql.OracleTypes.ARRAY and other types.
Could you please suggest me the equivalent DATA TYPE for the OracleTypes.ARRAY in Groovy SQL.
Thank you !!

Related

Table Valued Parameter using pyodbc is Ignored

Trying to send data to a stored procedure that accepts Table Valued Parameter, neither it does any action nor returns any error.
def InsertResults (self, dataset, name):
try:
sqlConn = self.sqlConnect()
with sqlConn.cursor() as cursor:
cursor.execute(f'CALL [dbo].[ImportAllocations] (?)', (dataset,))
result = cursor.fetchall()
print(result)
except AssertionError as error:
print(error)
finally:
print(f"Inserted data into {name}. Records inserted {len(dataset)}")
My data is well formed in DataFrame.
This is stored procedure header:
CREATE PROC [dbo].[ImportAllocations](#DataTable [dbo].[udt_Allocation] READONLY)
Looking at SQL Profiler, and it seems to be ignoring the call. I tried some other simple example as per in following issue, and that works fine.
The issue was with pandas Dataframe. This works once converted into tuples of single element without index.
listTuple = list(dataset.itertuples(index=False))
cursor.execute(f'EXEC {name} ?', (listTuple,))

How to call a stored procedure without including all parameters with default values? [duplicate]

I'm calling a third party stored procedure with a lot of optional parameters. It's in MS SQL Server 2008 R2 and looks like this:
procedure [dbo].[pTest]
#ReportDate varbinary(max) out,
#Optional1 varchar(max) = null,
#Optional2 varbinary(max) = null,
#Date varchar(max) = null,
-- ~20 more optional params of various types
as
begin
select * from test
end
I'm calling it from java using Spring Data JPA 1.10.2 with com.microsoft.sqlserver's sqljdbc 4.2.
I only ever want to call the procedure with two params ReportDate and Date. The rest of the params can stay at the default value (i.e. null). My code is as follows:
#Entity
#NamedStoredProcedureQuery(name = "Test.get", procedureName = "pTest", parameters = {
#StoredProcedureParameter(mode = ParameterMode.OUT, name = "ReportData", type = byte[].class),
#StoredProcedureParameter(mode = ParameterMode.IN, name = "Date", type = String.class)
})
public class Test {
// serves no purpose other than to meet
// JPA requirement
#Id
private byte[] reportData;
}
Spring data repository:
public interface TestRepository extends Repository<Test, Long> {
#Procedure("pTest")
byte[] get(#Param("Date") String date);
}
Test code:
#RunWith(SpringRunner.class)
#SpringBootTest
#Transactional(transactionManager="transactionManager")
public class TestRepositoryTest {
#Autowired
private TestRepository testRepository;
#Test
public void testGet() throws SQLException {
byte[] blob = testRepository.get("hi");
//error occurs
}
}
I get the following error though:
o.h.engine.jdbc.spi.SqlExceptionHelper : Error preparing CallableStatement [pTest]
com.microsoft.sqlserver.jdbc.SQLServerException: The index 4 is out of range.
at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDriverError(SQLServerException.java:191) ~[sqljdbc-4.2.jar:na]
I'm getting this because I did not specify Optional1 and Optional2. Now, if I add the Optional1 and Optional2 as #StoredProcedureParameters and as paramters to getTest method of the TestRepository, I no longer get the error. But then, I have to pass in a non-null values or otherwise I get another error complaining that I passed no value.
How can I call this stored procedure preferably without specifying Optional1 and Optional2?
In some cases, I need to call a stored procedure where the 15th parameter is all I need to set. I really prefer not having to define the other 14 parameters in my code. Even if I did that, I cannot set them to null.
It's not possible using Microsoft's JDBC driver. Two options:
Use jTDS (which is not an option if the stored procedure returns >8000 bytes)
Create a wrapper stored procedure that only has the params that are needed and have it call the other stored procedure. This may not be an option if you don't have permissions to create stored procedures on the database.
In my case, option 2 works because I do have permission to create stored procedures.

Sql-Server UniqueIntList type for java

I am having a stored procedure (sp) which uses UniqueIntList type in the sql server. I want to call this sp from java using spring's NamedParameterJdbcTemplate.
sql server sp execution details
DECLARE #M dbo.UniqueIntList
INSERT INTO #M VALUES (1),(2),(6)
exec usp_mysp #M
GO
Below is how I am executing it using java
private static final String SQL_SP = "usp_mysp :myVar";
MapSqlParameterSource mapSqlParameterSource = new MapSqlParameterSource();
mapSqlParameterSource.addValue("myVar", myList); // my list is List<Integer>
namedParameterJdbcTemplate.query(SQL_SP, mapSqlParameterSource, (q, i) -> {
// ... //
});
While doing this, I am getting Procedure or function has too many arguments specified and I figured out that this is due to the UniqueIntList type in the sql server.
So I would like to know how exactly shall I pass the values in the map for the NamedParameterJdbcTemplate?
As suggested by #David Browne in the comments, I had put some research on Table-valued parameter and this Link here helped to understand how can I achieve it using spring's NamedParameterJdbcTemplate for the ms-sql server

Voltdb stored procedures with array parameters

I have a VoltDB stored procedure that takes a string array String[] and it's loaded successfully but I cannot seem to execute the stored procedure using the VoltDB SQL query interface with exec.
Cannot also execute it in sqlcmd interface.
I get this error:
Error: PrepareStatement error: Invalid parameter count for procedure "StoredProcedure" (received: 3, expected: 2, )
How can I construct the exec statement to retrieve the result of the stored procedure from VoltDB?
Unfortunately, there is no good way to pass an array as a parameter when using the sqlcmd interface. If you need to test this procedure, the best way is to write a simple java / python script to call the procedure with an array. In python, it would look something like this:
#!/usr/bin/env python
from voltdbclient import *
client = FastSerializer("localhost", 21212)
# declare array parameters the same as primitives
fooProc = VoltProcedure( client, "Foo", [FastSerializer.VOLTTYPE_BIGINT])
# the set of all parameters is the outer array, the inner array is the parameter value
fooResponse = fooProc.call( [ [1, 2, 3, 4, 5] ] )
for x in fooResponse.tables:
print x
Full disclosure: I work at VoltDB.

postgres insert string to numeric column - auto-typecast does not happen

There is a table in postgres DB test1 having schema :
We are using spring frameworks jdbcTemplate to insert data as below:
Object[] params = {"978","tour"};
jdbcTemplate.update("insert into test1 values (?,?)", params);
But this gives the exception :
org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; bad SQL grammar [insert into test1 values (?,?)]; nested exception is org.postgresql.util.PSQLException: ERROR: column "id" is of type integer but expression is of type character varying
ERROR: column "id" is of type integer but expression is of type character varying
This works for Oracle database through implicit type conversion, but postgres does nOt seem to work that way.
Could this be an issue with postgres driver?
A workaround would be to cast explicitly:
insert into test1 values (?::numeric ,?)
But is there better way to do the conversion as this does not seem like a good solution since there are lot of queries to be modified and also there can be other such casting issues too.
Is there some parameter that can be set at DB level to perform an auto cast?
We found the answer here
Storing json, jsonb, hstore, xml, enum, ipaddr, etc fails with "column "x" is of type json but expression is of type character varying"
A new connection propertyshould be added :
String url = "jdbc:postgresql://localhost/test";
Properties props = new Properties();
props.setProperty("user","fred");
props.setProperty("password","secret");
props.setProperty("stringtype", "unspecified");
Connection conn = DriverManager.getConnection(url, props);
https://jdbc.postgresql.org/documentation/94/connect.html
"If stringtype is set to unspecified, parameters will be sent to the server as untyped values, and the server will attempt to infer an appropriate type. This is useful if you have an existing application that uses setString() to set parameters that are actually some other type, such as integers, and you are unable to change the application to use an appropriate method such as setInt()"
Yeah, drop the double quotes here:
Object[] params = {"978","tour"};
Becomes
Object[] params = {978,"tour"};
Alternatively do the casting as you mentioned.

Resources