Unable to reach my H2 table from Matlab (but able from Java) - matlab

The following Java code works:
public class TestH2Schema {
public static void main(String[] args) throws SQLException {
Driver driver = new org.h2.Driver();
Connection conn = driver.connect("jdbc:h2:file:D:/Users/Dims/Design/TESTS/SVHN_DB/db/svhn", null);
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT ID FROM IMAGE WHERE PATH='train/1.png';");
while(rs.next()) {
System.out.println(rs.getLong("ID"));
}
rs.close();
stmt.close();
conn.close();
}
}
The following equivalent code in Matlab does not work:
driver = org.h2.Driver;
props = java.util.Properties;
conn = driver.connect('jdbc:h2:file:D:/Users/Dims/Design/TESTS/SVHN_DB/db/svhn', props);
stmt = conn.createStatement();
query = 'SELECT ID FROM IMAGE WHERE PATH=''train/1.png''';
rs = stmt.executeQuery(query);
while rs.next()
rs.getLong('ID')
end
rs.close();
stmt.close();
conn.close();
doesn't work causing exception
org.h2.jdbc.JdbcSQLException: Table IMAGE not found; SQL statement:
UPDATE
If I query
query = 'SELECT * FROM INFORMATION_SCHEMA.TABLES;'
I see a list of tables, but not mine ones. Looks like Matlab is somehow looking at different location or someting.

matlab search in "MatlabDatabase" (or another default data-source)
to use your own defined data-source you should declare it first
for example:
q1='use your_datasource';
q2='select * from INFORMATION_SCHEMA.TABLES';
exec(conn,q1);
exec(conn,q2);

Related

Apply migration on multiple schemas using Java and Liquibase

I'm trying to apply migration over my multi tenant system where I have one database with multiple schemas,
And I do so by first getting all the tenants then loop over them and execute the update on liquibase after changing the schema, but it seems that the schema is not changed cause after performing the migration on the first tenant the second tenant throws an error complaining about table already exist.
#Override
#SneakyThrows
public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) {
Connection connection = null;
Statement statement = null;
Liquibase liquibase = null;
try {
connection = dataSource.getConnection();
statement = connection.createStatement();
ResultSet result = statement.executeQuery("SELECT nspname FROM pg_namespace WHERE nspname like 'tenant_%'");
List<String> schemas = new ArrayList<>();
while (result.next()) {
schemas.add(result.getString(1));
}
for (String schemaName:schemas) {
connection.setSchema(schemaName);
Database database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(new JdbcConnection(connection));
database.setDefaultSchemaName(schemaName);
log.info("Schema Name: {}",connection.getSchema());
liquibase = new Liquibase(CHANGE_LOG_FILE, new ClassLoaderResourceAccessor(), database);
liquibase.update(new Contexts(), new LabelExpression());
}
} catch (SQLException | DatabaseException e) {
e.printStackTrace();
}finally {
if(liquibase!=null) {
liquibase.close();
}
if(statement!=null&&!statement.isClosed()) {
statement.close();
}
if(connection!=null&&!connection.isClosed()){
connection.close();
}
}
}
Note: the reason I made it in different loops and not using `try-with-resource` is that the connection closes after getting the first row of the result set and updating the database so I had to close it myself

SQL increment id, filling first line of database

I habe a sqlite database in java (eclipse) with the library sqlite-jdbc-3.16.1.jar.
I have 5 rows in table1: id(ID Integer PRIMARY KEY AUTOINCREMENT), name, row3, row4, row5
I want to insert name, row3 and row4 and the id to increment itself.
public static void insertTest(String name, byte[] contentRow3, byte[] contentRow4) {
String sql = "INSERT INTO table1(name, contentRow3, contentRow4) VALUES(?,?,?)";
try (Connection conn = connect();
PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setString(2, name);
pstmt.setBytes(3, contentRow3);
pstmt.setBytes(4, contentRow4);
System.out.println("Added new Person to DB");
pstmt.executeUpdate();
} catch (SQLException e) {
System.out.println(e.getMessage());
}
}
Error : Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3
What is the problem here?
Placeholders in Java prepared statements begin at index 1, not 2. I expect that the following corrected code should work:
try (Connection conn = connect();
PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setString(1, name);
pstmt.setBytes(2, contentRow3);
pstmt.setBytes(3, contentRow4);
System.out.println("Added new Person to DB");
pstmt.executeUpdate();
} catch (SQLException e) {
System.out.println(e.getMessage());
}
The exception you are getting is complaining that index position 3 is out of bounds. Most likely, under the hood when you did pstmt.setBytes(3, contentRow4) this translated to accessing the fourth array element, which would be index 3 assuming the array indexing is zero based.

Unable to know how to link data between two tables

I'm learning RESTful webservices from javabrains website. Here there is a section named Comments and this is related to a message, But I'm unable to know How Can I link these both.
Below is my SQL Tables for Messages and comments.
Messages
Comments
Here Basically, both look pretty same(The table design), but the values differ. And I'm using the below method to send the data.
public Comment addComment(long messageId, Comment comment) throws Exception {
Properties properties = new Properties();
properties.load(getClass().getClassLoader().getResourceAsStream("/config.properties"));
String userName = properties.getProperty("user");
String password = properties.getProperty("pass");
String url = properties.getProperty("Sqldburl");
int key = 0;
try {
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver").newInstance();
Connection conn = DriverManager.getConnection(url, userName, password);
String query = "select count(*) from Comments";
PreparedStatement ps = conn.prepareStatement(query);
ResultSet rs = ps.executeQuery();
rs.next();
key = rs.getInt(1);
} catch (Exception e) {
System.out.println(e);
}
try {
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver").newInstance();
Connection conn = DriverManager.getConnection(url, userName, password);
String query = "insert into Comments(id, message, author) values(?,?,?)";
PreparedStatement ps = conn.prepareStatement(query);
ps.setInt(1, key);
ps.setString(2, comment.getMessage());
ps.setString(3, comment.getAuthor());
ps.executeQuery();
} catch (Exception e) {
System.out.println(e);
}
try {
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver").newInstance();
Connection conn = DriverManager.getConnection(url, userName, password);
String query = "select * from Comments where messageId=?";
PreparedStatement ps = conn.prepareStatement(query);
ps.setLong(1, messageId);
ResultSet rs = ps.executeQuery();
while (rs.next()) {
comment.setAuthor(rs.getString("Author"));
comment.setId(rs.getInt("Id"));
comment.setMessage(rs.getString("message"));
}
} catch (Exception e) {
System.out.println(e + "b3");
}
return comment;
}
After writing this code, I've realized that Here I'm adding a comment for sure into Comments table, But it is no where linked to the Messages.
I know a way, that is I've create a new column in the Comments table and using join operation, I need to update the same messageId in comments table. But I want to know if there is a better way of getting this done, without using the concept of joins.
In MessageBean, there is a map declared as below.
private Map<Long, Comment> comments = new HashMap<>();
#XmlTransient
public Map<Long, Comment> getComments() {
return comments;
}
public void setComments(Map<Long, Comment> comments) {
this.comments = comments;
}
can I take any advantage of this to avoid join?

SQL query class has no persistent fields in the SELECT

static void go() {
PersistenceManager pm = null;
Transaction tx = null;
try {
pm = new JDOFactory().getFactory().getPersistenceManager();
tx = pm.currentTransaction();
Query q = pm.newQuery("javax.jdo.query.SQL", "select * from \"OAUTHTEMP\" where \"O_AUTH_TOKEN\"=:oAuthToken and \"O_AUTH_VERIFIED\"=:oAuthVerified");
Map params = new HashMap();
params.put("oAuthToken", "08f727ab-7132-426c-8fc2-9ce2b30ebf9d");
params.put("oAuthVerifier", "C3ExGzv+cAQkOqwL4oY94fZhDyVLyo/0H31w8F3q+YYLSBDxl2YARcglqPuKcsfT");
List<OAuthTemp> result = (List<OAuthTemp>) q.executeWithMap(params);
} catch (Exception e) {
e.printStackTrace();
}
}
This is my function to fetch all data on the basis of token and verifier but I am getting the exception below:
SQL query class has no persistent fields in the SELECT : select * from "OAUTHTEMP" where "O_AUTH_TOKEN"=:oAuthToken and "O_AUTH_VERIFIED"=:oAuthVerified
org.datanucleus.exceptions.NucleusUserException: SQL query class has no persistent fields in the SELECT : select * from "OAUTHTEMP" where "O_AUTH_TOKEN"=:oAuthToken and "O_AUTH_VERIFIED"=:oAuthVerified
at org.datanucleus.store.rdbms.query.SQLQuery.prepareForExecution(SQLQuery.java:994)
at org.datanucleus.store.rdbms.query.SQLQuery.executeWithMap(SQLQuery.java:818)
at org.datanucleus.api.jdo.JDOQuery.executeInternal(JDOQuery.java:369)
at org.datanucleus.api.jdo.JDOQuery.executeWithMap(JDOQuery.java:276)
at com.xenonstack.demo.test.Test.go(Test.java:61)
at com.xenonstack.demo.test.Test.main(Test.java:40)
My OAuthTemp class is this
OauthTemp class.
You seem to have a query with a parameter called oAuthVerified yet are providing a value for oAuthVerifier. Perhaps if you fix that it would work?

The column name ... was not found in this ResultSet

We are using java jdk 1.7.0_45, postgresql jdbc connector postgresql-9.3-1100.jdbc41.jar.
Here is a synopsis of our problem, as much as possible of code pasted below.
This code:
ResultSet rs = DbConn.getInstance().doQuery("Select d.deptId from Depts d");
while (rs.next()){
System.out.println(rs.getInt("d.deptId"));
Produces the error:
org.postgresql.util.PSQLException: The column name d.deptId was not found in this ResultSet.
This code:
ResultSet rs = DbConn.getInstance().doQuery("Select d.deptId from Depts d");
while (rs.next()){
System.out.println(rs.getInt("deptId"));
Produces no error.
Is there a way, besides removing the "d." from the first query, to make the first code snippet not throw the error message?
Here is the source code:
public class JoinTest {
#Test
public void test(){
boolean pass = false;
try {
ResultSet rs = DbConn.getInstance().doQuery("Select d.deptId from Depts d");
String label = rs.getMetaData().getColumnLabel(1); // What do you get?
System.out.println("label = " + label);
while (rs.next()){
System.out.println(rs.getInt("d.deptId"));
pass = true;
}
} catch (SQLException e) {
e.printStackTrace();
pass=false;
}
assertTrue(pass);
}
#Test
public void test2(){
boolean pass = false;
try {
ResultSet rs = DbConn.getInstance().doQuery("Select d.deptId from Depts d");
while (rs.next()){
System.out.println(rs.getInt("deptId"));
pass = true;
}
} catch (SQLException e) {
e.printStackTrace();
pass=false;
}
assertTrue(pass);
}
}
public class DbConn {
private static String url = "jdbc:postgresql://server:port/schema";
private static Properties props = new Properties(); {
props.setProperty("user","userid");
props.setProperty("password","passwprd");
}
private Connection conn;
private DbConn(){}
private static DbConn instance;
public static DbConn getInstance() throws SQLException{
if (instance == null){
instance = new DbConn();
instance.conn = DriverManager.getConnection(url, props);
}
return instance;
}
public ResultSet doQuery(String query) throws SQLException{
Logger.log("DbConn.doQuery: " + query);
Statement st = conn.createStatement();
ResultSet rs = st.executeQuery(query);
return rs;
}
}
}
The query:
select d.deptId from Depts d
produces a single-column resultset with the result-alias "deptId". There is no "d.deptId" column. If you want one, you can request that as the column alias instead:
select d.deptId AS "d.deptId" from Depts d
PgJDBC can't do anything about this because it has no idea that the resultset column "deptId" is related to the "d.deptId" in the select-list. Teaching it about that would force it to understand way more about the SQL it processes than would be desirable, and lead to maintenance and performance challenges.
The second one works - why isn't that acceptable?
You can also do this:
System.out.println(rs.getInt(1));
If you change the query you have to change the code, too.