AWS mysql multiquery syntax error - java

I am porting a Tomcat7/Mysql applicationto AWS. I am seeing that whenever I send a multiple query statement I get an error like this:
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: 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 ....
I have only detyected it on multiple queries (f.e. Multiple related deletes, like "delete from xxx; delete from xxx"). Single queries seem to work correctly.
I am using this code for the connection.
Class.forName("com.mysql.jdbc.Driver");
String jdbcUrl = "jdbc:mysql://" + hostname + ":" + port + "/" + dbName + "?user=" + userName + "&password=" + password + "&autoReconnect=true&allowMultiQueries=true";
Connection con = DriverManager.getConnection(jdbcUrl);
To run the query I have this code:
Statement st = conn.createStatement();
res = st.executeQuery(query);
conn.commit();
I have already set the allowMultiQueries=true but it is not working correctly. What am I doing wrong?
Is multiquery supported?

As pointed out by #jarmod, the problem was in the url and the separator. I should use & instead of &
&autoReconnect=true&allowMultiQueries=true

Related

SQLite JDBC: What is the directory of my generaated database on Linux Ubuntu?

When I run the code below my database gets created in the directory of the project this code is in. Now I have an application that runs on Ubuntu. The problem I'm running into is that in one class it can use the database and in another it cannot. Knowing where my database is saved will help my solve the problem. I already looked in the project directory on my Linux system but I couldn't find the file. It should also be mentioned that both classes use the database in basically the same way.
This is a demo of the code I use on Windows with no problems.:
public class Main{
public static void main(String[] args) throws SQLException {
String url = "jdbc:sqlite:" + "testdb";
Connection conn = DriverManager.getConnection(url);
if (conn != null) {
DatabaseMetaData meta = conn.getMetaData();
System.out.println("The driver name is " + meta.getDriverName());
}
Connection c = DriverManager.getConnection(url);
Statement stmt = c.createStatement();
String sql = "CREATE TABLE IF NOT EXISTS TEST " +
"(id INTEGER PRIMARY KEY AUTOINCREMENT," +
" TEST TEXT NOT NULL " +
") ";
stmt.execute(sql);
stmt.close();
}
The exception I get is the following:
org.sqlite.SQLiteException: [SQLITE_ERROR] SQL error or missing database (no such table: WR_PMC_SIGNALS)
java.lang.NullPointerException
This is the same table that is accessed in a different class. I cannot find the file that contains the database anywhere. I think I could solve the issue if I could directly find the database.
Does anyone know how I can find the directory of the generated database? It's hard to reproduce the problem here as the system I'm working on is a Universal Robot.

mysql LOAD DATA LOCAL INFILE syntax error when executed via JDBC

I am trying to load contents from a csv file a local using this sample query:
SET GLOBAL local_infile=1; LOAD DATA LOCAL INFILE 'C:/afc_orders.csv' INTO TABLE `afc_report`.`afc_orders` FIELDS TERMINATED BY ';' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY '\n' IGNORE 1 ROWS (`type_o`,`n_order`,`n_return`);
Executing the query from MySQL works perfectly but, when I try to execute the same query from JDBC, I get a syntax Error:
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 'LOAD DATA LOCAL INFILE 'C:/afc_orders.csv' INTO TABLE `afc_report`.`afc_orders` ' at line 1
Here is my code:
Connection conn = null;
String url = "jdbc:mysql://" + mysqlHost + ":" + mysqlPort + "/" + mysqlDatabase + "?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC";
try {
conn = DriverManager.getConnection(url, mysqlUser, mysqlPassword);
Statement stmt = conn.createStatement();
String sql = "SET GLOBAL local_infile=1; LOAD DATA LOCAL INFILE 'C:/afc_orders.csv' INTO TABLE `afc_report`.`afc_orders` FIELDS TERMINATED BY ';' OPTIONALLY ENCLOSED BY '\"' LINES TERMINATED BY '\\n' (`type_o`,`n_order`,`n_return`);";
System.out.println(sql);
stmt.execute(sql);
} catch(Exception e) {
System.out.println(e.getMessage());
}
And here is the driver I am using:
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.20</version>
</dependency>
What am I missing?
For future reference, I also had to add:
&allowLoadLocalInfile=true
to the connection string to avoid error:
ERROR 3950 (42000): Loading local data is disabled; this must be enabled on both the client and server side
Your code is attempting to execute two statements at once (the SET statement and the LOAD DATA statement), but a Statement.execute(...) only accepts a single statement, not multiple statements.
You could try to execute these statements separately (I don't normally use MySQL, so I'm not sure if that works in this case), or the MySQL Connector/J driver can be configured to allow multiple statements by adding the connection property allowMultiQueries=true in the connection string.

MySQL Syntax Issue when using Accounts.UUID AND UUID =, with two tables

I'm having issues when using this:
WARN com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: 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 'WHERE Accounts.UUID = WarAccounts.UUIDAND Accounts.UUID = 'c7a00fe7-826d-46da-b4' at line 1
Here is the SQL:
SELECT
*
FROM
Accounts,
WarAccounts
WHERE
Accounts.UUID = WarAccounts.UUID
AND Accounts.UUID = ?
(Using prepared statements)
I'm very confused as to what is wrong with this to cause that issue, I've googled it but cannot find anything since this seems to be the correct way.
Server type: MySQL
Server version: 5.5.58-0ubuntu0.14.04.1 - (Ubuntu)
Wild ass guess:
In C# i would do this:
string query = "SELECT *" +
"FROM MYTABLE" +
"WHERE 1=1"
..to get your error..
Concat the string and you'll see the problem:
"SELECT *FROM MYTABLEWHERE 1=1"
The concatination should be:
string query = "SELECT * " +
"FROM MYTABLE " +
"WHERE 1=1 "
(see the spaces at the end of every line?)

Sqlite: Execute Spatialite Functions in Intellij

Does anyone know whether it is possible to execute spatialite functions on sqlite-databases in intellij?
Reference of spatialite functions: http://www.gaia-gis.it/gaia-sins/spatialite-sql-4.2.0.html
In particular, I would be interested in using functions on type Point.
Thanks!
Edit: Functions do work within the official spatialite-gui, however I don't think there is a way to use the spatialite-gui programmatically, is there?
Here is what I tried so far: In intellij I connected the Java JDBC library and tried using function ST_X(point) and ST_Y(point) with no success:
Connection c = null;
Class.forName("org.sqlite.JDBC");
c = DriverManager.getConnection("jdbc:sqlite:" + path + databaseName);
c.setAutoCommit(false);
System.out.println("Opened database \"" + databaseName + "\" successfully");
String sql = "SELECT id, ST_Y(point), ST_X(point) from tablename;";
Statement stmt = c.createStatement();
ResultSet rs = stmt.executeQuery(sql);
while ( rs.next() ) {
String msg = "Id: ";
msg += rs.getInt(1);
msg += " , Latitude: ";
msg += rs.getDouble(2);
msg += " , Longitude: ";
msg += rs.getDouble(3);
System.out.println(msg);
}
rs.close();
stmt.close();
c.close();
This throws the following exception:
Exception in thread "main" java.sql.SQLException: [SQLITE_ERROR] SQL error or missing database (no such function: ST_Y)
at org.sqlite.core.DB.newSQLException(DB.java:890)
at org.sqlite.core.DB.newSQLException(DB.java:901)
at org.sqlite.core.DB.throwex(DB.java:868)
at org.sqlite.core.NativeDB.prepare(Native Method)
at org.sqlite.core.DB.prepare(DB.java:211)
at org.sqlite.jdbc3.JDBC3Statement.executeQuery(JDBC3Statement.java:81)
at com.company.Test.main(Test.java:77)
Edit 2:
I'm lost. It seems that I need to load extensions to make it work. Is this not included in the JDBC connector? (I pulled the JDBC connector through Maven.)
Where do I find the correct extensions?
Are those the ones? https://www.gaia-gis.it/fossil/libspatialite/index
Or those? http://www.gaia-gis.it/gaia-sins/index.html
How do I use them? Has anybody done this before?
Before performing spatial queries you need to load the spatialite module doing
SELECT load_extension('mod_spatialite');
You can find the documentation here: Dynamically loading SpatiaLite as an extension module.
Note that the module to load must be on the system path (documentation) and the path separator must be /. Also take into account that the spatialite module and Java must be compatibles (both 32 or 64 bits).

JAVA - Possible SQL Injection

So I have this snippet of code:
String username = props.getProperty("jdbc.username");
try {
String username = parts[1];
// Check procedure
System.out.println("Checking user");
// Check database user table for username
conn = getSQLConnection();
Statement stat = conn.createStatement();
ResultSet user = stat.executeQuery( "SELECT * FROM USER WHERE log_id='" + username + "';" );
// Check given password against user entry
if(user.next()){
System.out.println("User Exists: " + username);
sendMessage("true");
return;
}
else{
System.out.println("User Does Not Exist: " + username);
sendMessage("false user");
return;
}
For educational purposes, is the SQL statement protected from an SQL injection even though I know where the input is coming from?
ResultSet user = stat.executeQuery( "SELECT * FROM USER WHERE log_id='" + username + "';" );
This is subject to SQL injection.
Imagine what happens if username has this value:
John'; delete from user where 'a' = 'a
And yes, a s*load of Java JDBC SQL tutorials get this wrong. Basically, always use PreparedStatements.
Not only because this makes it safe ot use even if username has malicious values as the above, but also, and more importantly, because the same query can be reused by the RDBMS engine for all further invocations.
In short, there is no reason at all not to use them. And tutorials demonstrating SQL using string concatenation should die a painful, SQL injection death.
As explained in this post, one rogue attacker can do the following to yoour application:
call a sleep function so that all your database connections will be busy, therefore making your application unavailable
extracting sensitive data from the DB
bypassing the user authentication
And it's not just SQL that can be affected. Even JPQL can be compromised if you are not using bind parameters.
Bottom line, you should never use string concatenation when building SQL statements. Use a dedicated API for that purpose:
JPA Criteria API
jOOQ

Categories