java.sql.ResultSet.next() description - mysql

I've a question about the same point in the next(), previous() & absolute()
in these boolean methods
Does the position of the cursor change if it returns false
for example:
1)Incase of next():
ResultSet rs = new Result();
while (rs.next())
System.out.println(rs.getInt(1));
rs.next(); // it will return false but will the cursor be after after last ?!
2)Incase of absolute():
ResultSet rs = new Result();
rs.absolute(15); //assuming I've only 10 rows it will return false but will the cursor be advanced ?
if the answer is that they change only when they return true so why there is a method gets me out of the range of rows as afterLast() ?
BTW I've checked java docs and I didn't found an answer to my question...

afterLast() can be used to forcefully exhaust a RestulSet. Another usage, if the ResultSet is scroallable, is to iterate over it backwards with the previous() method:
ResultSet rs = ...;
rs.afterLast();
while (rs.previous()) {
// do something.
}
Admittedly, I can't fathom any good reason to do this, but it's doable.
EDIT:
With regard to the question what will happen if you call next() on a ResultSet that's already positioned after the last row - it depends on the implementation of the JDBC driver. Some drivers just silently return false and do not change the state of the ResultSet, while some may fail the call with an SQLException. More specifically, do quote the documentation:
If the result set type is TYPE_FORWARD_ONLY, it is vendor specified whether their JDBC driver implementation will return false or throw an SQLException on a subsequent call to next.

Related

Google App Script SQL query returns bool 'True' instead of Int value but query works outside App Script? [duplicate]

When I execute a SQL query from Java and store the boolean returned, the query always returns true which shouldn't be the case at all. So I emptied the table and fired the query again, and yet it returns true for the emptied table. I have attached a picture of the table. I want the query to return true or false, so I can store it in Java. Can someone please specify an alternate code for this, please?
This is my code on java for the query.
boolean avail = st.execute("SELECT EXISTS(SELECT * from sales WHERE product='"+n+"' AND ord_date='"+sqlDate+"');");
And this is my code for result set
Statement st = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
This is the table, name of the table is 'sales'
I'm new to MySQL, a more specific approach is appreciated.
Statement.execute will return true regardless of what the query returns. You are still supposed to retrieve the actual result of the query.
Returns
true if the first result is a ResultSet object; false if it is an update count or there are no results
As you execute an EXISTS statement, there will always be a result (true or false). The actual value still has to be retrieved:
You must then use the methods getResultSet or getUpdateCount to retrieve the result, and getMoreResults to move to any subsequent result(s).
For reference: https://docs.oracle.com/javase/8/docs/api/java/sql/Statement.html#execute-java.lang.String-String
Also note that you are directly embedding strings into your query, this will leave you vulnerable to SQL injections. Please read: How can prepared statements protect from SQL injection attacks?. Recommended reading: Introduction to JDBC
The return value of Statement.execute() signals whether the query produces a result set (true) or - possibly - an update count (false). The query you execute is a select which will always produce a result set (even if empty). In other words, it will always return true for a select.
If you want to get the result of your query, then the recommend approach is to use executeQuery. However, you are also concatenating values into your query string, which is a bad idea because it leave you vulnerable to SQL injection. The recommended approach is to switch to prepared statements:
try (PreparedStatement pstmt = con.prepareStatement(
"SELECT EXISTS(SELECT * from sales WHERE product = ? AND ord_date = ?)")) {
pstmt.setString(1, n);
pstmt.setDate(2, sqlDate);
try (ResultSet rs = st.executeQuery() {
boolean avail = rs.next() && rs.getBoolean(1);
// use avail...
}
}

SimpleJdbcCall for MySql Function yields "Can't set IN parameter for return value of stored function call"

Using the example from the Spring docs, I'm trying to return a value from a mySQL function. I keep getting the error Can't set IN parameter for return value of stored function call;.
I created a mySQL function that works fine (ran in MySQL Workbench). I've written a SimpleJdbcCall statement, set up the parameters as per Spring docs example but consistently get this error. If I turn the function into a procedure, the code works, I just have to retrieve the return value from the result set.
I used https://docs.spring.io/spring/docs/3.0.0.M3/reference/html/ch13s05.html, section 13.5.8 as reference.
CREATE FUNCTION `ScenarioRegistration`(
environment VARCHAR(45),
username VARCHAR(15),
scenario_name VARCHAR(45)) RETURNS int(11)
A couple of SELECT statements followed by an INSERT then
RETURN scenario_id; // The inserted id
Java code:
SimpleJdbcCall simpleJdbcCall = new SimpleJdbcCall(getJdbcTemplate())
.withFunctionName("ScenarioRegistration")
.withoutProcedureColumnMetaDataAccess();
simpleJdbcCall.addDeclaredParameter(new SqlParameter("environment"
,Types.VARCHAR));
simpleJdbcCall.addDeclaredParameter(new SqlParameter("username"
,Types.VARCHAR));
simpleJdbcCall.addDeclaredParameter(new SqlParameter("scenario_name"
,Types.VARCHAR));
SqlParameterSource parameters = new MapSqlParameterSource()
.addValue("environment", environment)
.addValue("username", username)
.addValue("scenario_name", scenario);
simpleJdbcCall.setReturnValueRequired(true);
Integer scenario_id = simpleJdbcCall.executeFunction(
Integer.class, parameters);
All I want the routine to do is give me back the id of the newly inserted scenario.
What I get is:
SQL [{? = call scenarioregistration(?, ?)}]; Can't set IN parameter for return value of stored function call.
I find it interesting that it's taken my THREE input values and changed them to an output and TWO input values.
Anyone enlighten me as to the problem and how to fix it?
Thanks,
Steven.
I would refer to the latest docs here for your answer. It appears Spring is trying to infer the output because you didn't explicity specify one.
Per the docs above there are two valid approaches on calling the desired function with the SimpleJdbcCall:
Inferred Parameters
Because you've specified withoutProcedureColumnMetaDataAccess, Spring isn't going to look and see what the ins/outs are to your function. If you want it easy, just don't specify that and you should be able to do:
SqlParameterSource parameters = new MapSqlParameterSource()
.addValue("environment", environment)
.addValue("username", username)
.addValue("scenario_name", scenario);
Integer scenarioId = new SimpleJdbcCall(getJdbcTemplate())
.withFunctionName("ScenarioRegistration")
.executeFunction(Integer.class, parameters);
Explicit Parameters
If you want to keep withoutProcedureColumnMetaDataAccess turned off for whatever reason, you can do:
Integer scenarioId = new SimpleJdbcCall(getJdbcTemplate)
.withFunctionName("ScenarioRegistration")
.withoutProcedureColumnMetaDataAccess()
.useInParameterNames("environment", "username", "scenario_name")
.declareParameters(
new SqlOutParameter("scenario_id", Types.NUMERIC),
new SqlParameter("environment", Types.VARCHAR),
new SqlParameter("username", Types.VARCHAR),
new SqlParameter("scenario_name", Types.VARCHAR)
).executeFunction(Integer.class, parameters);
Note: It appears that order is critical in this example. The output parameter should be declared first, and the subsequent named IN parameters come last. That is, the order of the parameters ? are ordinal in [{? = call scenarioregistration(?, ?, ?)}])
Alternative NamedParameterJdbcTemplate Solution
Another way to invoke your function is via an actual JDBC call. This could hypothetically save you the grief of using the fine tuning of the SimpleJdbcCall.
Integer scenarioId = namedParameterJdbcTemplate.queryForObject(
"SELECT ScenarioRegistration(:environment, :username, :scenario_name)",
parameters,
Integer.class);

What is useLocalSessionState used for?

I had an issue with MySQL db where the setAutocommit were being logged many times even though there was no autocommit mode change. For example, if I call setautocommit(false) 5 times, I see 5 queries in the query log saying set autommit=0;
This is usually not supposed to happen as the autocommit mode hasnt changed. The query should be sent only when I am changing the autocommit mode i.e. say 1 to 0.
When I did some looking in the MySQL connection class implementation, I figured that they check useLocalSessionState value to decide whether they want to execute the query or not?
if ((getUseLocalSessionState()) && (this.autoCommit == autoCommitFlag)) {
needsSetOnServer = false;
}
So, even though this.autocommit & autocommit flag are same, needsSetOnServer is NOT set to false becuase useLocalSessionState is defaulted to false.
Once I add useLocalSessionState = true in my connection URL, I dont see the unnecessary query logs.
So, my questions are :
What is the significance of useLocalSessionState ? Why is it used generally?
Is it safe to set useLocalSessionState = true?
PS : I see that SQL Server handles this kind of a scenario without any such dependencies i.e. (Code snippet from SQLServerConnection
if (paramBoolean == this.databaseAutoCommitMode) {
return;
}
Referring to http://dev.mysql.com/doc/connector-j/en/connector-j-reference-configuration-properties.html:
Should the driver refer to the internal values of autocommit and transaction isolation that are set by Connection.setAutoCommit() and Connection.setTransactionIsolation() and transaction state as maintained by the protocol, rather than querying the database or blindly sending commands to the database for commit() or rollback() method calls?
My interpretation of this (after looking to the code of the MySQL JDBC driver) is that instead of issuing e.g. a SELECT ##session.tx_read_only, it checks the readOnly property of the connection class:
ConnectionImpl.java (MySQL JDBC connecotr 5.1.31):
public boolean isReadOnly() throws SQLException {
return this.isReadOnly(true);
}
public boolean isReadOnly(boolean useSessionStatus) throws SQLException {
if(useSessionStatus && /*...*/ && !this.getUseLocalSessionState()) {
//...
rs = stmt.executeQuery("select ##session.tx_read_only");
//...
} else {
return this.readOnly;
}
}
Furthermore, it only issues a SQL command for setting the read only state if useLocalSessionState is false:
public void setReadOnlyInternal(boolean readOnlyFlag) throws SQLException {
if((/*...*/ !this.getUseLocalSessionState()) {
this.execSQL((StatementImpl)null, "set session transaction " + (readOnlyFlag?"read only":"read write"), -1, (Buffer)null, 1003, 1007, false, this.database, (Field[])null, false);
}
this.readOnly = readOnlyFlag;
}
I assume that the same applies for the auto-commit and transaction isolation level properties.

Anorm insert with trigger

I have a table with a trigger that updates a column in the table after the insert. Problem is this is returning false:
def insert(user: User, token: String) = {
DB.withConnection {
implicit connection =>
SQL(INSERT_STMT).on("user_id" -> user.id, "token" -> token).execute()
}
}
The values get inserted correctly after the call but the function returns false. Any clues?
You should use .executeUpdate() for DML's DDL's which return rowcounts/nothing
Learn more from here.
I wish I knew more about SQL and Scala - so for the time I'll leverage my Google skills and take a shot at this - I believe this guy solved your question:
https://groups.google.com/forum/#!topic/play-framework/r2Iueso3yGQ
From the API, it would appear you get back false - if the result type is a rowcount:
Returns:
true if the first result is a ResultSet object; false if the first result is an update count or there is no result

lua post hooking a function

I found one topic that's about post hooking, but I don't think it's the same thing as I want to accomplish. topic i found
What I need is the following:
local someBoolean = false
function doSomething() -- this is the function used in __index in a proxy table
someBoolean = true
return aFunction -- this is function that we can NOT alter
end
I need to ble able to run the code "someBoolean = false" after the return... (yes, I know that's not supposed to happen :p) considering aFunction may contain other functions itself, I want someBoolean to be true for the entire scope of aFunction, but after that, it HAS to be turned back to false
I'm sorry if I didn't manage to explain it well enough. Copy pasting the relevant code of my actual project would be way too large, and I don't want to waste your time.
I've been stuck on this for a while now, and I just can't seem to figure it out...
(edit: I can't just put someBoolean = false after the function, because the function is actually an __index function on a proxy table)
edit: relevent piece of code. I hope it's a bit clear
local function objectProxyDelegate(t, key)
if not done then -- done = true when our object is fully initialised
return cls[key] -- cls is the class, newinst is the new instance (duh...)
end
print("trying to delegate " .. key)
if accessTable.public[key] then
print(key .. " passed the test")
objectScope = true
if accessTable.static[key] then -- static function. return the static one
return cls[key] -- we need to somehow set objectScope back to false after this, otherwise we'll keep overriding protected/private functions
else
return newinst[key]
end
elseif objectScope then
print("overridden protected/private")
return cls[key]
end
if accessTable.private[key] then
error ("This function is not visible. (private)", 2)
elseif accessTable.protected[key] then
error ("This function is not visible to an instance. (protected)", 2)
else
error ("The function " .. key .. " doesn't exiist in " .. newinst:getType(), 2) -- den deze...
end
end
Since you need to return a function (rather than evaluate a function) you can create a proxy for the aFunction and return that instead. Here's how it could work (with a bunch of code taken from the solution by Nicol Bolas):
local someBoolean = false
function doSomething(...) -- this is the function used in __index in a proxy table
someBoolean = true
-- Return a proxy function instead of aFunction
return function(...)
local rets = { aFunction(...) }
someBoolean = false
return table.unpack(rets)
end
end
You cannot execute code after a return statement. The correct answer is to call the function, catch the return values, set the variable, and then return the return values. For example:
local someBoolean = false
function doSomething(...) -- this is the function used in __index in a proxy table
someBoolean = true
local rets = { aFunction(...) } -- this is function that we can NOT alter
someBoolean = false
return table.unpack(rets)
end