How to create a HSQL in-memory-db from script file? - java

I have two HSQL databases in memory. With the first database I create the database structure and test data which is time-consuming. This database is exported via the SCRIPT command into a sql file. My second database (not necessarily in the same JVM) should be build from that exported sql file.
public static void main(String[] args) throws Exception {
try (Connection firstConnection = DriverManager.getConnection("jdbc:hsqldb:mem:connection1", "sa", "")) {
try (Statement statement = firstConnection.createStatement()) {
statement.execute("CREATE TABLE table1 (id INT)");
statement.execute("SCRIPT 'my.script'");
}
}
try (Connection secondConnection = DriverManager.getConnection("jdbc:hsqldb:mem:connection2", "sa", "")) {
ScriptUtils.executeSqlScript(secondConnection, new FileSystemResource("my.script"));
}
}
When invoking ScriptUtils.executeSqlScript() I get the following exception:
Caused by: java.sql.SQLInvalidAuthorizationSpecException: invalid authorization specification - already exists: SA in statement [CREATE USER SA PASSWORD DIGEST 'd41d8cd98f00b204e9800998ecf8427e']
at org.hsqldb.jdbc.JDBCUtil.sqlException(JDBCUtil.java:327)
at org.hsqldb.jdbc.JDBCUtil.sqlException(JDBCUtil.java:247)
at org.hsqldb.jdbc.JDBCStatement.fetchResult(JDBCStatement.java:1817)
at org.hsqldb.jdbc.JDBCStatement.execute(JDBCStatement.java:638)
at org.springframework.jdbc.datasource.init.ScriptUtils.executeSqlScript(ScriptUtils.java:457)
... 3 more
Caused by: org.hsqldb.HsqlException: invalid authorization specification - already exists: SA
at org.hsqldb.error.Error.error(Error.java:83)
at org.hsqldb.error.Error.error(Error.java:72)
at org.hsqldb.rights.GranteeManager.addUser(GranteeManager.java:623)
at org.hsqldb.rights.UserManager.createUser(UserManager.java:115)
at org.hsqldb.StatementSchema.getResult(StatementSchema.java:1026)
at org.hsqldb.StatementSchema.execute(StatementSchema.java:268)
at org.hsqldb.Session.executeCompiledStatement(Session.java:1378)
at org.hsqldb.Session.executeDirectStatement(Session.java:1248)
at org.hsqldb.Session.execute(Session.java:1008)
at org.hsqldb.jdbc.JDBCStatement.fetchResult(JDBCStatement.java:1809)
... 5 more
What is the correct way to export an existing in-memory-database and import it later into another (empty) in-memory-database?

The SCRIPT statements creates a full database script that can be opened as a file database. Open the second database as a file: database that does not store the modifications.
Connection secondConnection = DriverManager.getConnection("jdbc:hsqldb:file:my;files_readonly=true", "sa", "")

The problem appear to be with the script not the code running it.
The error is that its attempting to create the SA user CREATE USER SA which already exists (its the user you've authenticated with to run the script in the first place).
You should be remove (comment out) that line in the script and you should then be able to progress further.

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.

Can I run a "source" command (SQL script) from a JDBC connection?

I'm writing an application that has a data access layer to abstract the underlying connections to SQLITE3 or MySQL databases.
Thanks to some help here yesterday I was shown how to use a process builder to run a command line import into the SQLITE3 DB using output redirection.
Now I am trying to create the same database but in MySQL by importing a dump file. The load works fine from the command line client. I just tell it to source the file and the DB is created successfully.
However I am trying to do this through code at runtime and my method for executing a SQL statement fails to execute the source command.
I suspect that this is because "source" is not SQL but I don't know what else to use to try and run it.
My error message is:
java.sql.SQLSyntaxErrorException: 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 'source /tmp/ISMCoreActionPack_mysql.sql' at line 1
The failing command string:
source /tmp/ISMCoreActionPack_mysql.sql;
My method is:
public Boolean executeSqlStatement(String sql) {
Boolean rc = false;
try {
Connection connection = getConnection();
Statement statement = connection.createStatement();
rc = statement.execute(sql);
connection.close();
} catch (SQLException e) {
e.printStackTrace();
System.err.println(e.getClass().getName() + ": " + e.getMessage());
System.exit(1);
}
return rc;
}
Can anyone suggest how to do this?
You cannot run 'source' command, because it's not supported by JDBC driver, only MySQL.
My advice to you the following. Write some parser, which reads queries from a file, and executes them using JDBC statements.
source is not part of MySQL's dialect of SQL; it is a MySQL shell command. Still, you shouldn't need to write your own parser. You could use something like SqlTool as explained in this answer.

Teradata external Java Stored Procedure error: No suitable driver found for jdbc:default:connection

I wrote a Java stored procedure, packed it into a jar and installed it into the Teradata database. I want to use the default database connection as described here. Most of the code was generated by the Teradata wizard for stored procedures.
public class TestSql {
public static void getEntryById(int id, String[] resultStrings) throws SQLException {
Connection con = DriverManager.getConnection("jdbc:default:connection");
String sql = "SELECT x FROM TEST_TABLE WHERE ID = " + id + ";";
Statement stmt = (Statement) con.createStatement();
ResultSet rs1 = ((java.sql.Statement) stmt).executeQuery(sql);
rs1.next();
String resultString = rs1.getString(1);
stmt.close();
con.close();
resultStrings[0] = resultString;
}
}
I installed the jar:
CALL SQLJ.REPLACE_JAR('CJ!/my/path/Teradata-SqlTest.jar','test');
And created the procedure:
REPLACE PROCEDURE "db"."getEntryById" (
IN "id" INTEGER,
OUT "resultString" VARCHAR(1024))
LANGUAGE JAVA
MODIFIES SQL DATA
PARAMETER STYLE JAVA
EXTERNAL NAME 'test:my.package.TestSql.getEntryById(int,java.lang.String[])';
Now when I call this procedure, I get this error message:
Executed as Single statement. Failed [7827 : 39001] Java SQL Exception SQLSTATE 39001: Invalid SQL state (08001: No suitable driver found for jdbc:default:connection).
Now when I log off from Teradata and log on again and call the procedure, the error message becomes:
Executed as Single statement. Failed [7827 : 39001] A default connection for a Java Stored Procedure has not been established for this thread.).
What is the problem here? I'm connecting to Teradata using the Eclipse plugin. Teradata v. 15.0.1.01.
After many hours I finally found the problem. Eclipse packed all dependencies into the jar - which basically is ok. However it also packed the Teradata JDBC driver files (tdgssconfig.jar and terajdbc4.jar) into the result jar, which was the problem.
I adjusted the jar building process so that these files are not included and the errors went away.

Reading Single Excel file concurrently in java

We got this requirement while trying to run our framework from two different Jenkins jobs
Following is our code:
String xlsPath= System.getProperty("user.dir")+"\\TestInputs\\Config.xls";
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
Connection conn = DriverManager.getConnection("jdbc:odbc:Driver={Microsoft Excel Driver (*.xls)};DBQ=" +xlsPath+ ";DriverID=22;READONLY=TRUE","","");
String sql="Select * from [Setup$]";
Statement st = conn.createStatement();
ResultSet rs = st.executeQuery(sql);
while(rs.next())
{
System.out.println(rs.getString(1).toString());
System.out.println(rs.getString(2).toString());
System.out.println(rs.getString(3).toString());
Thread.sleep(1000);
}
rs.close();
st.close();
conn.close();
The above code working absolutely fine when we are trying to execute through multi threading concept.
But I am getting following error message if I create TWO JENKINS JOBS and running them parallely.
Exception in thread "main" java.sql.SQLException: [Microsoft][ODBC Excel Driver] The Microsoft Jet database engine cannot open the file '(unknown)'. It is already opened exclusively by another user, or you need permission to view its data.
Do we have any workaround for this? so that I can execute two jobs without any issues.
NOTE: I cannot use HSSF or someother means to read my excel file. I should strictly use Database commands like I used it in the above code.
Please help !

H2 File mode, error while opening new connections on existing file db

I am trying to create a H2 DB to a file.
a small module first runs that creates the file and the schema and populates it with data.
While doing this this the H2 jdbc url used:
jdbc:h2:file:c:\\Yogesh\\TestH2Db;MODE=Oracle;INIT=CREATE SCHEMA IF NOT EXISTS TEST\\;SET SCHEMA TEST\\;
A DDL script for the schema is run and then on this I am loading up some data using RunScript class.
After the loadup this module stop (The JVM dies/is no longer running).
A second module, tries to use this pre-created data based to run some tests.
To connect to this DB i am trying to use this url:
jdbc:h2:file:c:\\Yogesh\\TestH2Db;IFEXISTS=TRUE;MODE=Oracle;INIT=CREATE SCHEMA IF NOT EXISTS TEST\\;SET SCHEMA TEST\\;
Basically the same url but with IFEXISTS=TRUE added.
A JdbcConnectionPool is create based on this URL.
protected JdbcConnectionPool initConnectionPool(String user, String pwd,
int maxConn, String jdbcUrl) {
System.setProperty("h2_jdbc_url", jdbcUrl);
JdbcConnectionPool connpool = JdbcConnectionPool.create(
jdbcUrl, user, pwd);
connpool.setMaxConnections(maxConn);
return connpool;
and when the rest of the module does a getConnection on the above created JDBC Connection pool, it fails and seems to be creating the same objects that I had created in the Init module again.
I have tried it without the INIT=CREATE SCHEMA IF NOT EXISTS TEST\;SET SCHEMA TEST\; to no avail
Edit: To add the stack Trace
org.h2.jdbc.JdbcSQLException: Syntax error in SQL statement
[Have a create view statement here that fails cant give out the SQL statement,
however note that this SQL statement ran fine
when i used RunScript tool to init the DB schema;
What i don't understand is while doing get connection the
connection Pool why are objects
being inited again, the Schema creation script is not part of the
INIT part of JDBC Url]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:329)
at org.h2.message.DbException.get(DbException.java:169)
at org.h2.message.DbException.getSyntaxError(DbException.java:194)
at org.h2.command.Parser.getSyntaxError(Parser.java:491)
at org.h2.command.Parser.read(Parser.java:2798)
at org.h2.command.Parser.readIfMore(Parser.java:809)
at org.h2.command.Parser.parseColumnList(Parser.java:778)
at org.h2.command.Parser.parseCreateView(Parser.java:4281)
at org.h2.command.Parser.parseCreate(Parser.java:3749)
at org.h2.command.Parser.parsePrepared(Parser.java:324)
at org.h2.command.Parser.parse(Parser.java:279)
at org.h2.command.Parser.parse(Parser.java:255)
at org.h2.command.Parser.prepare(Parser.java:201)
at org.h2.engine.Session.prepare(Session.java:388)
at org.h2.engine.Session.prepare(Session.java:375)
at org.h2.engine.MetaRecord.execute(MetaRecord.java:56)
at org.h2.engine.Database.open(Database.java:632)
at org.h2.engine.Database.openDatabase(Database.java:222)
at org.h2.engine.Database.<init>(Database.java:217)
at org.h2.engine.Engine.openSession(Engine.java:56)
at org.h2.engine.Engine.openSession(Engine.java:159)
at org.h2.engine.Engine.createSessionAndValidate(Engine.java:138)
at org.h2.engine.Engine.createSession(Engine.java:121)
at org.h2.engine.Engine.createSession(Engine.java:28)
at org.h2.engine.SessionRemote.connectEmbeddedOrServer(SessionRemote.java:305)
at org.h2.jdbc.JdbcConnection.<init>(JdbcConnection.java:109)
at org.h2.jdbc.JdbcConnection.<init>(JdbcConnection.java:93)
at org.h2.Driver.connect(Driver.java:72)
at org.h2.jdbcx.JdbcDataSource.getJdbcConnection(JdbcDataSource.java:181)
at org.h2.jdbcx.JdbcDataSource.getXAConnection(JdbcDataSource.java:315)
at org.h2.jdbcx.JdbcDataSource.getPooledConnection(JdbcDataSource.java:341)
at org.h2.jdbcx.JdbcConnectionPool.getConnectionNow(JdbcConnectionPool.java:226)
at org.h2.jdbcx.JdbcConnectionPool.getConnection(JdbcConnectionPool.java:199)
at junit.db.utils.InitH2DB.getConnection(InitH2DB.java:45)
at test.DBLoader.DBLoader.main(DBLoader.java:21)
The Error was because of an incorrect script used to create teh H2 schema.
See comments below the question for more details.

Categories