MySQL version error - java

I have following error:
**Average of Job_Render is 138.29047 and its Minimum value is : 2.00061 and Maximum value is :7499.75
java.sql.SQLException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'select avg(kdt_build_Box_Gen), max(kdt_build_Box_Gen),min(kdt_build_Box_Gen) fro' at line 1
java.sql.SQLException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'select avg(kdt_build_Box_Gen), max(kdt_build_Box_Gen),min(kdt_build_Box_Gen) fro' at line 1
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2975)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1600)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:1695)
at com.mysql.jdbc.Connection.execSQL(Connection.java:3020)
at com.mysql.jdbc.Connection.execSQL(Connection.java:2949)
at com.mysql.jdbc.Statement.executeQuery(Statement.java:959)
at com.journaldev.json.AggregateSum.main(AggregateSum.java:70)******
Here is the code:
private static final String DB_DRIVER = "com.mysql.jdbc.Driver";
private static final String DB_CONNECTION = "jdbc:mysql://localhost:3306/";
private static final String DB_USER = "root";
private static final String DB_PASSWORD = "root";
private static final String dbName = "raas";
public static final String[] COLUMNS = {"Job_Render","kdt_build_Box_Gen", "Adaptation_Luminance","LightMan_finalize_PA","IES_bytes","GeomMan_finalize_Total","KDTree_Kickstart","Indirect_Tree_Build","Average_Cutsize","cube_map_count","GeomMan_finalize_accel_build","Direct_Tree_Build","Direct_VPL_Sampling","Scene_Setup_Total","Direct_VPL_Filtering","File_cache_hit_rate","Downloaded_bytes"};
public static void main(String[] args) throws ClassNotFoundException,SQLException {
try {
Connection conn = null;
Statement stmt = null;
// STEP 2: Register JDBC driver
Class.forName(DB_DRIVER);
// STEP 3: Open a connection
System.out.println("Connecting to a selected database...");
conn = DriverManager.getConnection(DB_CONNECTION + dbName, DB_USER,
DB_PASSWORD);
System.out.println("Connected database successfully...");
stmt = conn.createStatement();
String sql1 = "select * from ras;";
String sql = "";
for (int idx = 0; idx < COLUMNS.length; ++idx) {
String F = COLUMNS[idx];
sql += "select avg("+F+"), max("+ F +"),min("+ F+") from ras;";
boolean isMoreRecordsAvailable = false;
ResultSet rs = stmt.executeQuery(sql);
isMoreRecordsAvailable = rs.next();
while (isMoreRecordsAvailable) {
System.out.println("Average of " + F + " is "
+ rs.getFloat(1) + " and its Minimum value is : "
+ rs.getFloat(3) + " and Maximum value is :"
+ rs.getFloat(2));
isMoreRecordsAvailable = rs.next();
}
}
} catch (Exception e) {
System.out.println(e);
System.out.println("There it is");
e.printStackTrace();
}
}
}
I even tried to check the quotes which are correct. I don't know why I'm getting this error. I want to run the loop for all the fields that are initialized in the String[] Column; But it only executes Job_Render, but it's throwing an exception.

It executes the exception because you are concatenating SELECT and FROM multiple times. You need to remove the plus symbol:
String sql = "select avg("+F+"), max("+ F +"),min("+ F+") from ras;";
And remove String sql definition from outside the for loop.

Related

SQL Injection for array of mixed vulnerability and non vulnerability queries

Below persistent code has SQL vulnerability.
strSetStatement[1], strSetStatement[2] and strSetStatement[6] is setting parameters based on genSetStatement method sending. Which can be untrusted data. I am facing to fix this mix of simple queries and parameterized queries.
SQL Injection vulnerable code
public class SQLInjection{
public static void main(String[] args) throws SQLException, IOException {
String[] strSetStatement = new String[6];
PreparedStatement m_statement;
String url = "DBURL";
Connection conenction = DriverManager.getConnection(url, "", "");
m_statement = conenction.prepareStatement("SET CHARACTER_SET 'UTF8_FTCS'");
// Setting DB Initial parameters | setting limits for queries
String strMatch = "100";
String strTime = "100";
String strRank = "2:1";
genSetStatement(strSetStatement, strMatch, strTime, strRank);
boolean logQuery = true;
if (logQuery) {
for (int i = 0; i <= 7; i++)
setlogComment(m_statement, strSetStatement[i]);
}
}
private static void genSetStatement(String[] strSetStatement, String strMatch, String strTime, String strRank) {
strSetStatement[0] = "SET SHOW_MATCHES 'FALSE';";
strSetStatement[1] = "SET MAX_SEARCH_ROWS " + strMatch + ";";
strSetStatement[2] = "SET MAX_EXEC_TIME " + strTime + ";";
strSetStatement[3] = "SET SERVER_REPORT_TIME " + FTSSearchConst.SERVER_REPORT_TIME + ";";
strSetStatement[4] = "SET SEARCH_MEMORY_SIZE " + FTSSearchConst.SEARCH_MEMORY_SIZE + ";";
strSetStatement[5] = "SET THESAURUS_NAME 'FULTEXT';";
strSetStatement[6] = "SET RELEVANCE_METHOD '" + strRank + "';";
}
private static void setlogComment(PreparedStatement stmt, String strSetState) throws SQLException, IOException {
stmt.executeQuery(strSetState); // SQL injected area
}
}
I am trying to do below by adding '?' in strSetStatement[] array. and check if query has '?' in setlogComment method, but how to identify the exact parameter and bind variables to it ?
strSetStatement[1] = "SET MAX_SEARCH_ROWS " + ? + ";";
private static void setlogComment(PreparedStatement stmt, String strSetState) throws SQLException, IOException {
if(strSetState.contains("?")){
stmt.setString(1, arg1);
}
stmt.executeQuery(strSetState);
}
Caution: I'm not sure for which SQL version/dialect you're going to run these queries, this should be some Full-Text-Search extension.
The purpose of the following code is to get rid of the issues detected in your code snippet, however, you may need to update it appropriately in case of any error.
The code has been reactored to get rid of redundant methods/variables.
Queries at indexes 1, 2, 6 have been updated to include ? for outer parameters.
Type of matchRows and execTime parameters has been changed to int
Parameters for the PreparedStatement are set and the queries are executed inside main loop.
public class SQLInjection {
public static void main(String[] args) throws SQLException, IOException {
String[] strSetStatement = {
"SET SHOW_MATCHES 'FALSE';",
"SET MAX_SEARCH_ROWS ?;",
"SET MAX_EXEC_TIME ?;",
"SET SERVER_REPORT_TIME " + FTSSearchConst.SERVER_REPORT_TIME + ";",
"SET SEARCH_MEMORY_SIZE " + FTSSearchConst.SEARCH_MEMORY_SIZE + ";",
"SET THESAURUS_NAME 'FULTEXT';",
"SET RELEVANCE_METHOD ?;"
};
Connection connection = DriverManager.getConnection("DBURL", "", "");
PreparedStatement m_statement = connection.prepareStatement("SET CHARACTER_SET 'UTF8_FTCS'");
m_statement.executeQuery();
// Setting DB Initial parameters | setting limits for queries
int matchRows = 100;
int execTimeSec = 100;
String strRank = "2:1";
boolean logQuery = true;
if (logQuery) {
for (int i = 0; i < strSetStatement.length; i++) {
PreparedStatement stmt = connection.prepareStatement(strSetStatement[i]);
if (i == 1) {
stmt.setInt(1, matchRows);
} else if (i == 2) {
stmt.setInt(1, execTimeSec);
} else if (i == 6) {
stmt.setString(1, strRank);
}
stmt.executeQuery();
}
}
}
}

Dynamically add columns and column names Jdbc/MySql

Is there a way to add dynamically columns and column names to an existing table using jdbc?
For example:
If NumberOfColumns = 3, I want the column names to be "Column1", Column2", "Column3".
I tried to add dynamically some columns with the name of iterator just for testing my code but it gives me an SQL syntax error.
Below are some parts of my code I just described. If I remove the whole loop, the code works like a charm.
public class something {
//Some Variables Declaration///
//Number of columns in test table//
int NumberOfColumns = 3;
public static void main(String args[]) {
//..... SOME CODE....//
//Create database//
sql = "CREATE DATABASE mydb";
stmt.executeUpdate(sql);
//Create test table//
sql = "CREATE TABLE mydb.table "
+ "(id INTEGER not NULL ";
stmt.executeUpdate(sql);
//Add columns dynamically//
for (int i = 0; i < NumberOfColumns; i++) {
sql = "ALTER TABLE mydb.test ADD'" + i + "' VARCHAR(30)";
stmt.executeUpdate(sql);
}
stmt.executeUpdate(sql);
}
}
First of all you should to delete your stmt.executeUpdate(sql); after your loop, this can make a problem,
change this lines:
for (int i = 0; i < NumberOfColumns; i++) {
sql = "ALTER TABLE mydb.test ADD'" + i + "' VARCHAR(30)";
stmt.executeUpdate(sql);
}
stmt.executeUpdate(sql);
just with this:
for (int i = 0; i < NumberOfColumns; i++) {
colname = "Column" + i;
sql = "ALTER TABLE mydatabase.table ADD " + colname + " VARCHAR(30)";
stmt.executeUpdate(sql);
}
Because you can will get an error that the 3ed column exist
also the name of column not need 'id' you just need to remove the two quots
Here is an exemple can solve your problem:
Requires that you initialize a driver so you can open a communications channel with the database, after create your database your tables and your columns,
package DataBase;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class createdatabase {
//Number of columns in test table//
private static int NumberOfColumns = 3;
static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
static final String DB_URL = "jdbc:mysql://localhost/";
static final String USER = "root";
static final String PASS = "mypass";
public static void main(String[] args) {
Connection conn = null;
Statement stmt = null;
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection(DB_URL, USER, PASS);
stmt = conn.createStatement();
String sql = "CREATE DATABASE mydatabase";
stmt.executeUpdate(sql);
sql = "CREATE TABLE mydatabase.table (id INTEGER not NULL)";
stmt.executeUpdate(sql);
String colname;
for (int i = 0; i < NumberOfColumns; i++) {
colname = "Column" + i;
sql = "ALTER TABLE mydatabase.table ADD " + colname + " VARCHAR(30)";
stmt.executeUpdate(sql);
}
} catch (ClassNotFoundException | SQLException e) {
System.out.println("Exception = " + e);
} finally {
try {
if (stmt != null) {
stmt.close();
}
} catch (SQLException se2) {
}
try {
if (conn != null) {
conn.close();
}
} catch (SQLException se) {
System.out.println("Exception" + se);
}
}
}
}
Hope this can help you
You need a space after the keyword ADD in the alter statement. I would also recommend prefixing the column name rather than just using a number.
Can you post the SQL error as well, to help clarify what the error actually is.

PreparedStatement: getIngredientByName

How would I go about modifying this snippet of code for PreparedStatement? I've seen how to do this with a number variable, but I seem to be having some trouble with String variables...
#Path("/ingredients/name")
#GET
#Produces("text/plain")
public String getIngredientByName(#QueryParam("name") String theName)
throws SQLException, ClassNotFoundException
{
//Obtaining an ingredient from the database
String connectStr="jdbc:mysql://localhost:3306/fooddb";
String username="root";
String password="csci330pass";
String driver="com.mysql.jdbc.Driver";
Class.forName(driver);
Connection con = DriverManager.getConnection(connectStr, username, password);
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery("SELECT id, name, category FROM ingredient WHERE
name='" + theName + "'");
String result = "";
while (rs.next())
{
int theId3 = rs.getInt("id");
String theName3 = rs.getString("name");
String theCategory = rs.getString("category");
result += "id: "+theId3+ " , name: "+theName3 + "("+theCategory+")" + "\n" + "\n";
}
return result;
}//END METHOD
}//END CODE
Another concern I have is that this code might be missing something, due to how it returns only the first result whenever I try to enter in credentials that are not the same as those results. Again, this code corresponds to an index.html file I created recently...
I've seen how to do this with a number variable, but I seem to be having some trouble with String variables
It's exactly the same process but instead you use setString, as described in the JavaDocs and Using Prepared Statements
public String getIngredientByName(#QueryParam("name") String theName)
throws SQLException, ClassNotFoundException {
//Obtaining an ingredient from the database
String connectStr = "jdbc:mysql://localhost:3306/fooddb";
String username = "root";
String password = "csci330pass";
String driver = "com.mysql.jdbc.Driver";
Class.forName(driver);
String result = "";
try (Connection con = DriverManager.getConnection(connectStr, username, password)) {
try (PreparedStatement stmt = con.prepareStatement("SELECT id, name, category FROM ingredient WHERE name =?")) {
stmt.setString(1, theName);
try (ResultSet rs = stmt.executeQuery()) {
while (rs.next()) {
int theId3 = rs.getInt("id");
String theName3 = rs.getString("name");
String theCategory = rs.getString("category");
result += "id: " + theId3 + " , name: " + theName3 + "(" + theCategory + ")" + "\n" + "\n";
}
}
}
}
return result;
}//END METHOD
You're also not managing your resources, you need to make sure that once you have competed using the resources, that you close them, this would cause issues with the database if you're not careful
Take a look at The try-with-resources Statement

Fail to convert to internal representation JDBC

Ok so this is my code
public static ArrayList getMaterialerFraOrdreNr(String s_date, String e_date) throws SQLException, InterruptedException {
int tal = 0;
ArrayList nameOfColumns = getNameOfColumns(); // name of columns
ArrayList orderNumber = getOrdre_Nr_FromDB(s_date, e_date); // order number
//første loop kører gennem number of columns
//anden loop kører gennem name of column
ResultSet rs = null;
Connection con = null;
try {
Class.forName(DB.driver);
con = DriverManager.getConnection(DB.URL, DB.ID, DB.PW);
for (int i = 1; i < orderNumber.size(); i++) {
for (int j = 1; j < nameOfColumns.size(); j++) {
String nameOfColum = (String) nameOfColumns.get(i);
int orderNr = (Integer) orderNumber.get(j);
System.out.println("orderNr " + orderNr);
//SELECT v1001 FROM ORDRE_spec WHERE ordre_nr = 1;
String query = "SELECT ? AS ans FROM ordre_spec WHERE ordre_nr = ?";
PreparedStatement prest = con.prepareStatement(query);
prest.setString(1, nameOfColum);
prest.setInt(2, orderNr);
System.out.println("orderNr " + orderNr);
System.out.println("nameOfColum = " + nameOfColum);
rs = prest.executeQuery();
if(rs.next()){
tal = rs.getInt("ans");
MaterialeNum.add(tal);
System.out.println("materiale num = " + MaterialeNum);
}
}
}
} catch (ClassNotFoundException | SQLException ee) {
System.out.println("fail og der er så her");
System.err.println(ee);
} finally {
con.close();
}
System.out.println(kundeNum.toString());
return kundeNum;
}
public static void main(String[] args) throws SQLException, InterruptedException {
NewClass.getMaterialerFraOrdreNr("1990-10-10", "2020-10-10");
}
And my problem is that I'm getting a java.sql.SQLException: Fail to convert to internal representation
I really cant see what the error should be.. plz help if you can see the error :)
String query = "SELECT ? AS ans FROM ordre_spec WHERE ordre_nr = ?";
You cannot parameterize column names. You can only parameterize column values.
Basically you need to do:
String query = "SELECT " + nameOfColum + " AS ans FROM ordre_spec WHERE ordre_nr = ?";
Keep in mind that this is prone to SQL injection if nameOfColum is controllable by enduser. If this is indeed the case, you may want to perform string matching on e.g. \w+ before continuing.

Getting empty resultSet for simple query

gurus,
I am new to Java SQL, and need some help.
I'm trying to get a parameter from MS SQL Server 2008. The data is definitely there - it is a current and valid DB, and I'm trying to use the users records to get cridentials for another application.
I asserted the following query:
String query = "SELECT [USER].qc_number FROM [USER] WHERE "[USER].login_name = '"
+ userNameInput + "' AND [USER].password = '" + passWordInput + "';";
Where userNameInput and passWordInput are received from the user. The URL, query and driver class are definitely correct: I checked the DB schema both from the application and from the server views. Furthermore, I verified all the Exceptions systems by changing parameters one by one, resulting in correct Exceptions messages. However, I get a resultSet with 1 column and 0 rows.
The code is below:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class trOdbc
{// database URL
final String DB_URL = "***";
final String Class_URL = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
private Connection connection = null; // manages connection
private Statement statement = null; // query statement
private ResultSet resultSet = null; // manages results
private Boolean connectedToDatabase = false;
// ----------------------------------------------------------
public void createJdbcConnection()
{ // connect to database books and query database
if (connectedToDatabase)
{ return; }
try
{ // connectedToDatabase is false - establish the connection
Class.forName(Class_URL);
connection = DriverManager.getConnection
(DB_URL, "***", "***" );
statement = connection.createStatement
(ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
connectedToDatabase = true;
}
catch (SQLException ex)
{ System.out.println ("SQL Exception in connection establishment: " + ex); }
catch (ClassNotFoundException ex)
{ System.out.println ("Class not found exception in query process: " + ex); }
}
// ----------------------------------------------------------
public String [][] processJdbcQuery (String query)
{
createJdbcConnection ();
if (!connectedToDatabase)
{ return null; }// the connection wasn't established
try
{// query database
resultSet = statement.executeQuery(query);
int columns = resultSet.getMetaData().getColumnCount();
int rows = 0;
if (resultSet != null)
{
resultSet.beforeFirst();
resultSet.last();
rows = resultSet.getRow();
}
String [][] tempData = new String[rows][columns];
resultSet.beforeFirst();
rows = 0;
while (resultSet.next())
{
for (int x = 1; x <= columns; x++)
{
tempData [rows][x - 1] = resultSet.getString (x);
}
rows++;
}
CloseJdbcConnection ();
return tempData;
}
catch (SQLException ex)
{
System.out.println ("SQL Exception in query process: " + ex);
CloseJdbcConnection ();
return null;
}
} // end processJdbcQuery
// ----------------------------------------------------------
public void CloseJdbcConnection()
{
if ( connectedToDatabase )
{// close Statement and Connection. resultSet is closed automatically.
try
{
statement.close();
connection.close();
connectedToDatabase = false;
}
catch (SQLException ex)
{ System.out.println ("SQL Exception in connection closure: " + ex); }
} // end if
} // end method CloseJdbcConnection
} // end class trOdbc
Why don't you use Prepared Statement instead ?
Here is a good tutorial for using prepared statement in java
In your case it would be :
String query = "SELECT [USER].qc_number FROM [USER] " +
"WHERE [USER].login_name = ? AND [USER].password = ?;";
And then set it with different values each time you execute it like :
PreparedStatement ps = connection.prepareStatement(query);
ps.setString(1, userNameInput);
ps.setString(2, passWordInput);
resultSet = ps.executeQuery();

Categories