How to use variable in JDBC Object? Jmeter - java

I have a JMeter job that is performing some UI tests on a webpage, it should then store the text value of an object in a variable called "impid"
var vars = org.apache.jmeter.threads.JMeterContextService.getContext().getVariables()
var importID = WDS.browser.findElement(org.openqa.selenium.By.xpath('html/body/table[2]/tbody/tr[3]/td[6]/table[1]/tbody/tr[5]/td[2]/strong')).getText()
vars.put('impid','importID')
I believe that part is working, I then want the pass the value of that variable into a mysql JDBC Request, like so -
select id, fileName, timeEntered, timeStarted, timeCompleted, comments from netdespatch.fileImportStore where id = ${impid};
But the varialbe is just being used as the "name" it is not being converted into the variable value..
I'm sure someone know what i'm doing wrong..

I believe that part is working
how do you know? Given your XPath syntax I don't believe it matches anything.
Your select query looks good so I would recommend double checking your ${impid} variable using Debug Sampler and View Results Tree listener combination.
You can also try printing the variable value into jmeter.log file right from the WebDriver Sampler like:
WDS.log.info('importID value == ' + importID)
References:
XPath Tutorial
How to Debug your Apache JMeter Script

String s ="select id, fileName, timeEntered, timeStarted, timeCompleted, comments from netdespatch.fileImportStore where id = ?";
PreparedStatement preparedStatement = dbConnection.prepareStatement(s);
preparedStatement.setInt(1, impid);
Use place holder '?' and then bind with sentInt (or adequate method for other types)

I worked out the issue, the variable I was passing between Webdriver and JDBC needed to be a jmeter UDV..so
I have a UDV called impID
grabbed my value from webdriver and put it in the impID variable
var vars = org.apache.jmeter.threads.JMeterContextService.getContext().getVariables()
var importID = WDS.browser.findElement(org.openqa.selenium.By.xpath('html/body/table[2]/tbody/tr[3]/td[6]/table[1]/tbody/tr[5]/td[2]/strong')).getText()
vars.put('impID',importID)
this puts the value of importID into the UDV impID
Then on the JDBC request, use a "Prepared Select Statement"
select id, fileName, timeEntered, timeStarted, timeCompleted from nd.fileImportStore where id = ?
and in Parameter Value enter = ${impID}
And that worked :)

Related

Jdbc template named parameters for querying with IN clause

I need to copy the records of one table to another table based on some condition.
String query = "insert into public.ticket_booking_archive select * from public.ticket_booking where ticketId in (:ticketIds)";
So here the :ticketIds are dynamic, where i need to pass ticketIds to make sure whether it satisfies the condition. So it may be the matching and non matching ticket id's here at runtime.
The values of ticketIds are something like this
('f1fa3a42-5837-11ec-bf63-0242ac130002','516fd14d-3c9d-4b4b-91a0-b684d8592dfe','c9652f86-734c-4df5-8ef9-d407cb3eaf7a','df7f2812-b445-45b4-b731-da23c36d7738','f1fa3a42-5837-11ec-bf63-0242ac130002'). And this is just an example. And the list might goes on.
Since it is of type UUID, I'm storing it into a Set<UUID>
Set<UUID> tktIds = new HashSet<UUID>();
for(int i=0 ; i<ticketIds.size(); i++) {
String ticketId = ticketIds[i];
tktIds.add(UUID.fromString(ticketId));
}
Map<String, Object> params = new HashMap<>();
params.put("ticketIds", tktIds);
SqlParameterSource namedParameters =
new MapSqlParameterSource().addValue("ticketIds",params.get("ticketIds"));
Since I'm using NamedParameterJdbcTemplate, so I'm using like below
int res = writeNamedJdbcTemplate.update(query, namedParameters);
res = 3 when executed programmatically.
Here the problem is, as soon as it finds the first matching value in the IN clause it executes. And it is not considering the other matching values (ticketIds here)
But if I execute the same query in pgadmin it works fine
insert into public.ticket_booking_archive select * from public.ticket_booking where ticketId in ('f1fa3a42-5837-11ec-bf63-0242ac130002','516fd14d-3c9d-4b4b-91a0-b684d8592dfe','c9652f86-734c-4df5-8ef9-d407cb3eaf7a','df7f2812-b445-45b4-b731-da23c36d7738','f1fa3a42-5837-11ec-bf63-0242ac130002');
result is 6. Working as expected.
writeNamedJdbcTemplate.queryForObject(query, namedParameters, Integer.class); //. throws an error
Can anyone please assist? I'm really not sure where I'm making a mistake
I am not quite sure whether you are using the appropriate JDBC template for the named parameters, but you can do the following:
you can consult this article to use the right template and employ proper SQL query composition,
for string passing you can wrap the parameter mapping as shown here
after all your named parameter should work

How to scroll to first record again using OracleDataReader class or another class?

I'm migrating a Java application to VB.Net and I try to translate following Java code
Statement stmt
= conx.createStatement
(ResultSet.TYPE_SCROLL_INSENSITIVE
,ResultSet.CONCUR_READ_ONLY
);
ResultSet rsSheet = stmt.executeQuery(sSql);
bStatus = rsSheet.next();
...
bStatus = rsSheet.first();
In this code, a scrollable ResultSet is used. I can read the records returned by executeQuery() function and when I have terminated to read them, I can read it again without interrogating the Database a second time.
You can find some information on ResultSet here https://docs.oracle.com/javase/7/docs/api/java/sql/ResultSet.html
My translated code is following
Dim cmd = conx.CreateCommand()
cmd.CommandText = sSql
Dim rsSheet as OracleDataReader = cmd.ExecuteReader()
bStatus = rsSheet.Read()
...
bStatus = rsSheet.? 'how to read first record again ?
But I don't find how to do so that OracleDataReader is scrollable ?
I can read the ResultSet from first to last record but I cannot read it again.
The only simple solution that I found to read all these records again is to call ExecuteReader() function a second time.
QUESTIONS
Is OracleDataReader Class scrollable ? How ?
Does another Class exist to do the job ? Which ?
PS: using Linq is not solution because SQL statements are executed in an environnement where Database structure is unknown. It is impossible to create entities.
A DataReader is one way only. Use a DataTable. This is an in memory representation of the result set. You can also use a DataTable to as a DataSource for various controls. You can use Linq on a DataTable.AsEnumerable()
Private Sub OPCode()
Dim sSql = "Your command text"
Dim dt As New DataTable
Using cn As New OracleConnection(ConStr),
cmd As New OracleCommand(sSql, cn)
cn.Open()
dt.Load(cmd.ExecuteReader)
End Using
'Code to read data.
End Sub
EDIT
The simplest way to see what is in the DataTable is to display it in a DataGridView if this is WinForms.
DataGridView1.DataSource = dt.
To access a specific row and column.
Dim s = dt.Rows(1)("ColName").ToString
The Rows collection starts with index 0 and the column name is from you Select statement. You then need to convert to the datatype with .ToString or Cint(), CDbl() etc. as this returns an object.

DB2 sql error code -245 for a date

I am reading several sql queries from database inside a loop as below:
{ // start of loop
Map<String, Object> queryRS = this.jdbcTemplate.queryForMap(this.querySql,queryParam);
String query = (String) queryRS.get("QUERY");
// code here as explained below
} // end of loop
The query returned could have any number of parameters. However, in all of them I have to set same date as the parameter.
For this I am counting the number of occurrence of character ? in the query and creating an Object array with same date repeated as below.
String date = '2010-12-31';
int numArgs = StringUtils.countMatches(query, "?");
String[] paramArgs = new String[numArgs];
for (int i = 0; i < numArgs; i++) {
paramArgs[i] = date;
}
After which I am executing the query as below:
SqlRowSet myRowSet = this.jdbcTemplate.queryForRowSet(query,(Object[]) paramArgs);
However, this is giving error when the query has a Date(?) function.
com.ibm.db2.jcc.am.SqlSyntaxErrorException: DB2 SQL Error: SQLCODE=-245, SQLSTATE=428F5, SQLERRMC=DATE;1, DRIVER=3.64.96
The description of above error is:
An untyped parameter marker is passed to a function and there are two or more possible candidate functions to resolve to during function resolution.
What is the solution to this?
Thanks for reading!
I suppose you are using String jdbcTemplate.
I had not the same but a similar problem: the function was char(?) and I was
passing an integer argument to it.
I was using a Old framework Ibatis 2.x (now I use MyBatis 3.x).
The framework was not the error cause.
On Ibatis I pass the argument so: char(#value:INTEGER#)
On my develop server all was work well but on remote production server I get your same error.
The problem was caused by the JDBC driver version 4.x on develop end 1.x on production.
To solve my problem I have two ways:
change the production driver (but I cannot)
use a different call: char('$value:INTEGER$') (I do this)
In IBATIS/MYBATIS framework, if value is 123, char('$value:INTEGER$') is translate to sql char('123') so solve my problem and when production change driver I can put back to char(#value:INTEGER#).
You have a similar problem. Try to:
look at the driver version
use type like in spring reference, sql type, spring manual
I do not use direct access to jdbcTemplate but I think that you have not to put args in string, you have to create a Date variable end put it in an Object array.
I hope that this can help you.

Invoking procedure defaults without binding values to parameters in Jdbc

I am trying to call a PL/SQL procedure which has defaults defined for some of its parameters. I am doing this using CallableStatement in JDBC.
This procedure has a large number of parameters with defaults defined. I do not want to explicitly set the defaults in the Java code. Doing this would make maintaining the code harder. If the PL/SQL code changes , would have to make the same changes in the Java code too.
Is it possible to accomplish this in JDBC ? For instance just bind values to the parameter you are interested in and ignore the rest.
I tried this on the following sample procedure :
-- PURPOSE: Takes a parameter which has defaults set. Returns the value of the same parameter
-- Example of: FUNCTION that takes a parameter with DEFAULT values
FUNCTION handle_defaults(empId IN NUMBER DEFAULT 20 , empCity IN VARCHAR2) RETURN NUMBER IS
BEGIN
RETURN empId;
EXCEPTION
WHEN others THEN
dbms_output.put_line('Error!');
END handle_defaults;
Here is the relevant portions of the code (NOTE: Have stripped off the try catch block , cleaning up of database resources etc for sake of readability)
// Create a database connection
conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PWD);
// Create a query string
String queryStr = "{ ? = call HR.EMP_PKG.handle_defaults( ? , ? ) }";
// Create a Callable Statements
callStmt = conn.prepareCall(queryStr);
// Bind values to the IN parameter
callStmt.setString(3, "Mumbai");
// Register OUT parameter
callStmt.registerOutParameter(1, java.sql.Types.NUMERIC);
// Execute the Callable Statement
callStmt.execute();
// Retrieve the value of the OUT parameter
parameterValue = callStmt.getInt(1);
System.out.println("Value returned : " + parameterValue);
I get the following error:
Exception occured in the database
java.sql.SQLException: Missing IN or OUT parameter at index:: 2
Database error code: 17041
As a desperate attempt I also tried to pass Nulls for those parameters. Just included the following line:
callStmt.setNull(2, java.sql.Types.NUMERIC);
I get the following result:
Value returned : 0
That makes sense bcoz setNull supplies SQL Null to the parameter.
I am using Oracle 11g and Oracle 12c Jdbc Driver Version 12.1.0.2.
I don't think there's a simple answer to this question, and that's not because of JDBC, but because of Oracle.
Put simply, the only way I know of calling a procedure and using the default value for a parameter is to not specify the parameter when you call the procedure.
If you are writing
String queryStr = "{ ? = call HR.EMP_PKG.handle_defaults( ? , ? ) }";
you are always specifying both parameters, so you can never use the default value for one of them. If you only want to specify one of them and use the default for the other, write:
String queryStr = "{ ? = call HR.EMP_PKG.handle_defaults( empCity => ? ) }";
In this case you need to specify the parameter name in the call, as the first parameter is the optional one. If the second parameter was optional instead, the parameter name can be dropped.
Unfortunately, this becomes quite complicated for your real procedure with lots of parameters. What I would do would be to:
Use a StringBuilder to build up the procedure call string.
Run through the parameters, adding paramName => ? parts to it for each parameter you have a value for. Ensure the parts are separated by commas.
Prepare a CallableStatement using the output of the StringBuilder.
Run through the parameters again and call various setString/setInt/setDate/etc. methods on the CallableStatement for each parameter you have a value for.

Passing a variable and query to Jasper report

Is it possible to pass both an SQL query, e.g. (<![CDATA[$P!{SQL}]]>), and a variable $V as parameters to a Jasper report at the same time?
Also, how can I pass the variable $V to my Jasper report using Java?
Often it is desired to just transform some parameter in order to use it in a query (in this case, the following works :) ).
E.g. (pseudo code - Groovy syntax!)
parameter:
filtParamUserName = "foo"
"variable" (technically not: in this case another parameter following it)1:
sqlCondUserName = $P{filtParamUserName} ? " and user_name = '$P{filtParamUserName}'" : ""
thus you could easily use it in your query like:
select * from bar where 1=1 $P{sqlCondUserName}
1: you have to set the Default Value Expression of the sqlCondUserName and Is For Prompting = false
A variable is something that varies during the report generation, like the number of pages for example. So a variable ($V) is not something you can pass to a report. You may pass any value from your Java code to the report as a parameter ($P), though.

Categories

Resources