DATEDIFF not working in JAVA - java

Am running a query from JAVA , the query contains DATEDIFF function in which the parameter is a keyword,we can give yy,mm,day,etc.. so am getting these keyword from user as parameter and setting it in query, but the issue is it wont execute, it gives an exception as Invalid parameter for argument 1. If i run the same query in CLIENT it gives result, but if i give quotes to keyword like 'day' it gives the same error in CLIENT also. So my question how will I set it in the query from JAVA. Currently am doing like
for (String param : params) {
try {
namedParameterStatement.setObject(param,requiredFilterValues.get(param));
} catch (RuntimeException e) {
}
}
This is the query am using
SELECT CUST_KEY,Eff_Date_From,Eff_Date_To, DATEDIFF(:intervals,Eff_Date_From,Eff_Date_To) as datediffs,Active FROM CUSTOMER_DIM WHERE Active = :active
Am passing values for params intervalsand active, The issue is with :intervals as it takes keywords.
I think the java program setting the parameter as string that is why its generating error.. How can i implement this?

The problem is that you can only pass values using parametrized queries. You can't pass keywords (nor object names). In the case of your query. they would be passed as the equivalent of DATEDIFF('<your-keyword>', .., which wouldn't work either.
There is no solution except manually concatenating the required keyword into the query, or creating a convoluted query using a CASE-construct to get the right value depending on the value passed:
case ? when 'MONTH' then datediffer(MONTH, ..) when .. end
You may need to explicitly cast the parameter to a VARCHAR to get it to work.

Related

Less repetition in jOOQ query

Any idea on how I could define the following jOOQ query with less repetition?
I am using jOOQ 3.11.4.
db.insertInto(ACCOUNT,
ACCOUNT.ACCOUNT_ID,
ACCOUNT.EMAIL,
ACCOUNT.FIRST_NAME,
ACCOUNT.LAST_NAME,
ACCOUNT.IS_ADMIN,
ACCOUNT.PASSWORD)
.values(account.accountId,
account.email,
account.firstName,
account.lastName,
account.isAdmin,
account.password)
.onConflict(ACCOUNT.ACCOUNT_ID)
.doUpdate()
.set(ACCOUNT.EMAIL, account.email)
.set(ACCOUNT.FIRST_NAME, account.firstName)
.set(ACCOUNT.LAST_NAME, account.lastName)
.set(ACCOUNT.IS_ADMIN, account.isAdmin)
.set(ACCOUNT.PASSWORD, account.password)
.returning(
ACCOUNT.ACCOUNT_ID,
ACCOUNT.EMAIL,
ACCOUNT.FIRST_NAME,
ACCOUNT.LAST_NAME,
ACCOUNT.IS_ADMIN,
ACCOUNT.PASSWORD
)
.fetchOne()
(I turns out my question is mostly code, and StackOverflow does not let me post it as is, without adding more details, which I do not think is necessary for my question, but nevertheless, they want me to post some more text, which I am doing right now by typing this message, and I hope you did not have to read to the end.)
Since you're passing all the columns to the insert statement, you might write this instead:
// Create an AccountRecord that contains your POJO data
Record rec = db.newRecord(ACCOUNT);
rec.from(account);
// Don't pass the columns to the insert statement explicitly
db.insertInto(ACCOUNT)
// But pass the record to the set method. It will use all the changed values
.set(rec)
// Use the MySQL syntax, which can be emulated on PostgreSQL using ON CONFLICT
.onDuplicateKeyUpdate()
// But pass the record to the set method again
.set(rec)
// Don't specify any columns to the returning clause. It will take all the ACCOUNT columns
.returning()
.fetchOne();

Converting an ActiveRecord:Relation to java array

I am running a 'where' query which is running on a table MyTable in my rails application.
I want to convert the results of a specific column from this query(ActiveRecord::Relation) to Java Array of String type.
This is what I am doing :
employeesJavaArray=MyTable.where("salary = ?",100).pluck(:columnName).to_java(java.lang.String)
However I am receiving this error in my logs :-
TypeError (could not coerce Fixnum to class java.lang.String):
Can you please help me out what could be wrong with the statement that I have written.
I would ensure that the array only includes string (by calling to_s) first:
employeesJavaArray = MyTable.where("salary = ?",100)
.pluck(:columnName)
.map(&:to_s)
.to_java(java.lang.String)

sql criteria with count function aliasToBean issue Hibernate

In my sql i have used count function like
COUNT( bip.seat_number) as totalSeats
Im trying to map this totalSeats attribute to a java bean called ScheduleSummery
Transformers.aliasToBean(ScheduleSummery.class)
Here is my java bean class
public class ScheduleSummery {
private String totalSeats;
public String getTotalSeats() {
return totalSeats;
}
public void setTotalSeats(String totalSeats) {
this.totalSeats = totalSeats;
}
}
Im getting below exception when trying to run this code. I have defined totalSeats as a String but it still shows expected type as java.lang.String
IllegalArgumentException occurred while calling setter for property
[ScheduleSummery.totalSeats
(expected type = java.lang.String)];
target = [ScheduleSummery#3f08662f], property value = [27]
any idea ? :(
The problem is your query returns some kind of number and your property is expecting a String.
You have to options
convert the result of the query to a String like so (should work with Oracle, the precise syntax for other databases might vary):
to_char(COUNT( bip.seat_number)) as totalSeats
change the property to the type you are getting out of the sql statement. You already tried int (according to other, now deleted answers. Other options you might try are: long, Long, Integer, BigInteger If try and error doesn't help, you can determine where in the code Hibernate tries the assignement (from the stacktrace), put a breakpoint there and see, what kind of value it actually has.

HQL multiple where clauses

I was originally doing a single variable query and I had to add in another variable to my statement and can't seem to get it to work correctly or find a straight answer on the expected syntax. I've already checked everything is mapped correctly and nothing null is going into the query.
Here's what I'm attempting to do which isn't working correctly
return getHibernateTemplate().find("from Pricing_Data where rate_class=?", rate_class + "where utility=?", utility);
Orginally I had it as this and that was working as expected
return getHibernateTemplate().find("from Pricing_Data where rate_class=?", rate_class);
Try this:
return getHibernateTemplate().find("from Pricing_Data where rate_class=? AND utility=?", new Object[]{rate_class, utility});
Hibernate Find method
Try to use query
from Pricing_Data where rate_class = ? and utility = ?
Then setParameter for rate_class and utility.
SQL/HQL queries can have second (third, etc) where clause only in subqueries.

What is the correct usage of zxjdbc to call stored procedures?

I am attempting to use zxJDBC to connect to a database running on SQL Server 2008 R2 (Express) and call a stored procedure, passing it a single parameter. I am using jython-standalone 2.5.3 and ideally do not want to have to install additional modules.
My test code is shown below.
The database name is CSM
Stored Procedure:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: <Author,,Name>
-- Create date: <Create Date,,>
-- Description: <Description,,>
-- =============================================
CREATE PROCEDURE dbo.DUMMY
-- Add the parameters for the stored procedure here
#carrierId VARCHAR(50)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
INSERT INTO dbo.carrier (carrierId, test)
VALUES (#carrierId, 'Success')
END
GO
Jython Script:
from com.ziclix.python.sql import zxJDBC
conn = None
try :
conn = zxJDBC.connect('jdbc:sqlserver://localhost\SQLEXPRESS', 'sa', 'password', 'com.microsoft.sqlserver.jdbc.SQLServerDriver')
cur = conn.cursor()
cur.callproc(('CSM','dbo','DUMMY'), ['carrier1'])
conn.commit()
except Exception, err :
print err
if conn:
conn.rollback()
finally :
if conn :
conn.close()
By using cur.execute() I have been able to verify that the above is successfully connecting to the database, and that I can query against it. However, I have thus far been unable to successfully call a stored procedure with parameters.
The documentation here(possibly out of date?) indicates that callproc() can be called with either a string or a tuple to identify the procedure. The example given -
c.callproc(("northwind", "dbo", "SalesByCategory"), ["Seafood", "1998"], maxrows=2)
When I attempt to use this method, I receive the following error
Error("Could not find stored procedure 'CSM.DUMMY'. [SQLCode: 2812], [SQLState: S00062]",)
It would appear that zxJDBC is neglecting to include the dbo part of the procedure identifier.
If I instead call callproc with "CSM.dbo.DUMMY" as the first argument then I receive this error
Error('An object or column name is missing or empty. For SELECT INTO statements, verify each column has a name. For other statements, look for empty alias names. Aliases defined as "" or [] are not allowed. Change the alias to a valid name. [SQLCode: 1038], [SQLState: S0004]',)
Using a profiler on the database whilst running my script shows that in the second case the following SQL is executed:
use []
go
So it would seem that when using a single string to identify the procedure, the database name is not correctly parsed out.
One of my trial and error attempts to fix this was to call callproc as follows:
cur.callproc(('CSM', '', 'dbo.DUMMY'), ['carrier1'])
This got me only as far as
Error("Procedure or function 'DUMMY' expects parameter '#carrierId', which was not supplied. [SQLCode: 201], [SQLState: S0004]",)
In this case what I think is happening is that zxJDBC attempts to call a system stored procedure (sp_proc_columns) to determine the required parameters for the stored procedure I want to call. My guess is that with the procedure identifier in the incorrect format above, zxJDBC does not get a valid/correct return and assumes no parameters are required.
So basically I am not a bit stuck for ideas as to how to get it to
Use the correct database name
Correctly determine the required parameters using sp_proc_columns
Call my stored procedure with the correct name
all at the same time.
I do have a workaround, which is to use something like
cur.execute('EXEC CSM.dbo.DUMMY ?', ['carrier1'])
However I feel like callproc() is the correct solution, and would likely produce cleaner code when I come to call stored procedures with large numbers of parameters.
If anyone can spot the mistake(s) that I am making, or knows that this is not ever going to work as I think then any input would be much appreciated.
Thanks
Edit
As suggested by i-one, I tried adding cur.execute('USE CSM') before calling my stored procedure (also removing the database name from the procedure call). This unfortunately produces the same Object or Column missing error as above. The profiler shows USE CSM being executed, followed by USE [] so it seems that callproc() always fires a USE statement before the procedure itself.
I have also experimented with turning on/off autocommit, to no avail.
Edit 2
Further information following comments/suggested solutions:
"SQLEXPRESS" in my connection string is the database instance name.
Using double quotes instead of single has no effect.
Including the database name in the connection string (via ;databaseName=CSM; as specified here) and omitting it from the callproc() call leads to the original error with a USE [] statement being fired.
Using callproc(('CSM', 'dbo', 'dbo.DUMMY'), ['carrier1']) gives me some progress but results in the error
Error("Procedure or function 'DUMMY' expects parameter '#carrierId', which was not supplied. [SQLCode: 201], [SQLState: S0004]",)
I'll attempt to investigate this further
Edit 3
Based on the queries I could see zxJDBC firing, I manually executed the following against my database:
use CSM
go
exec sp_sproc_columns_100 N'dbo.DUMMY',N'dbo',N'CSM',NULL,N'3'
go
This gave me an empty results set, which would seem to explain why zxJDBC isn't passing any parameters to the stored procedure - it doesn't think it needs to. I have yet to figure out why this is happening though.
Edit 4
To update the above, the empty result set is because the call should be
exec sp_sproc_columns_100 N'DUMMY',N'dbo',N'CSM',NULL,N'3'
This unfortunately brings me full circle as I can't remove the dbo owner from the stored procedure name in my callproc() call or the procedure won't be found at all.
Edit 5
Table definition as requested
CREATE TABLE [dbo].[carrier](
[carrierId] [varchar](50) NOT NULL,
[test] [varchar](50) NULL
) ON [PRIMARY]
Though completely unaware of the technologies used here (unless some minor knowledge of SQL Server), I will attempt an answer (please forgive me if my jython syntax is not correct. I am trying to outline possibilities here not exact code)
My first approach (found at this post) would be to try:
cur.execute("use CSM")
cur.callproc(("CSM","dbo","dbo.DUMMY"), ["carrier1"])
This must have to do with the fact that sa users always have the dbo as a default schema (described at this SO post)
If the above does not work I would also try to use the CSM database name in the JDBC url (this is very common when using JDBC for other databases) and then simply call one of the two below.
cur.callproc("DUMMY", ["carrier1"])
cur.callproc("dbo.DUMMY", ["carrier1"])
I hope this helps
Update: I quote the relevant part of the link that you can't view
>> Program calls a Stored Procedure - master.dbo.xp_fixeddrives on MS SQL Server
from com.ziclix.python.sql import zxJDBC
def getConnection():
url = "${DBServer.Url}"
user= "${DBServer.User}"
password = "${DBServer.Password}"
driver = "${DBServer.Driver}"
con = zxJDBC.connect(url, user, password, driver)
return con
try:
conn = getConnection()
print 'Connection successful'
cur = conn.cursor()
cur.execute("use master")
cur.callproc(("master", "dbo", "dbo.xp_fixeddrives"))
print cur.description
for a in cur.fetchall():
print a
finally:
cur.close()
conn.close()
print 'Connection closed'
The error you get when you specified the call function like above suggests that the parameter is not passed correctly. So please modify your stored procedure to take a default value and try to call with passing params = [None]. If you see that the call succeeds we must have done something right as far as specifying the database is concerned.
Btw: the most recent documentation suggests that you should be able to access it with your syntax.
As outlined in comments callproc will work only with SELECT. Try this approach instead:
cur.execute("exec CSM.dbo.DUMMY #Param1='" + str(Param1) + "', #carrierId=" + str(carrierID))
Please see this link for more detail.

Categories