/* * Copyright (C) 2013 Intel Corporation * All rights reserved. */ package com.intel.mtwilson.tag.dao.jooq; import com.intel.mtwilson.tag.dao.jdbi.*; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.HashSet; import java.util.Properties; import java.util.Set; import javax.sql.DataSource; import org.apache.commons.dbcp.BasicDataSource; import org.jooq.DSLContext; import org.jooq.SQLDialect; import org.jooq.conf.Settings; import org.jooq.impl.DSL; import org.skife.jdbi.v2.DBI; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * References: * Validation queries: http://stackoverflow.com/questions/3668506/efficient-sql-test-query-or-validation-query-that-will-work-across-all-or-most * * @author jbuhacoff */ public class Derby { private static Logger log = LoggerFactory.getLogger(Derby.class); public static String driver = "org.apache.derby.jdbc.EmbeddedDriver"; //public static String protocol = "jdbc:derby:"; /** * NOTE: this url is repeated in the pom.xml where jooq needs it to connect * to the database to grab the schema and automatically generate sources */ public static String protocol = "jdbc:derby:directory:mytestdb"; // places it in directory "target/derby" under current directory (good for junit testing) public static Connection c = null; public static DataSource ds = null; private static boolean isLoaded = false; private static boolean isSchemaCreated = false; public static void startDatabase() throws SQLException { // assume derby database is in a "derby" folder in current directory unless the user has set the system property to override this. if( System.getProperty("derby.system.home") == null ) { log.debug("System property derby.system.home is not set; using default ./derby"); System.setProperty("derby.system.home", "derby"); } if( !isLoaded ) { try { // find the temporary directory // File temp = File.createTempFile("derby", ".tmp"); // System.out.println("temp file in: "+temp.getAbsolutePath()+" ; parent in "+temp.getParent()); // System.setProperty("derby.system.home", temp.getParent()); // System.getProperty("user.home")+File.separator+".derby"); Class.forName(driver).newInstance(); isLoaded = true; } catch(ClassNotFoundException | InstantiationException | IllegalAccessException e) { throw new SQLException("Cannot load Derby driver", e); } } } public static void stopDatabase() { // DriverManager.getConnection("jdbc:derby:MyDbTest;shutdown=true"); // shut down a specific database try { // shut down all databaes and the derby engine ; throws SQLException "Derby system shutdown." DriverManager.getConnection(protocol+";shutdown=true"); // same as the protocol above but with create=true replaced with shutdown=true } catch(Exception e) { log.info("{}", e.getMessage()); // expect: Database 'directory:target/derby/mytestdb' shutdown. // we don't print the full stack trace because we know Derby throws an exception on shutdown (part of its API documentation) // if you print e.toString() it would be like: java.sql.SQLNonTransientConnectionException: Database 'directory:target/derby/mytestdb' shutdown. // and the rest of the stack trace is not useful since we know the cause is we issued a shutdown command via the connection. } } public static DataSource getDataSource() throws SQLException { if( !isLoaded ) { startDatabase(); } if( ds == null ) { BasicDataSource dataSource = new BasicDataSource(); dataSource.setDriverClassName(driver); // or com.mysql.jdbc.Driver for mysql // dataSource.setUsername("username"); // dataSource.setPassword("password"); //dataSource.setUrl("jdbc:derby:mytestdb;create=true"); // automatically creates derby in-memory db, or use "jdbc:mysql://<host>:<port>/<database>" for a mysql db dataSource.setUrl(protocol+";create=true"); // creates it in the "target/derby" folder which is for temporary files, good for junit tests dataSource.setMaxActive(10); dataSource.setMaxIdle(5); dataSource.setInitialSize(5); dataSource.setValidationQuery("VALUES 1"); // derby-specific query, for mysql /postgresl / microsoft sql / sqlite / and h2 use "select 1" ds = dataSource; } return ds; } public static Connection getConnection() throws SQLException { if( c == null ) { c = getDataSource().getConnection(); // also a username/password option is available } return c; //return DriverManager.getConnection(protocol + "derbyDB;create=true", new Properties()); // return getDataSource().getConnection(); } public static void testDatabaseConnection() throws SQLException { try (Connection c = DriverManager.getConnection(protocol, new Properties())) { try (Statement s = c.createStatement()) { try (ResultSet rs = s.executeQuery("VALUES 1")) { if( rs.next() ) { log.info("Database connection is ok"); } } } } } public static boolean tableExists(String tableName) throws SQLException { Set<String> availableTables = listTablesAndViews(getConnection()); return availableTables.contains(tableName) || availableTables.contains(tableName.toUpperCase()); // derby tables names tend to be all caps } public static Set<String> listTablesAndViews(Connection targetDBConn) throws SQLException { HashSet<String> set = new HashSet<String>(); DatabaseMetaData dbmeta = targetDBConn.getMetaData(); readDBTable(set, dbmeta, "TABLE", null); readDBTable(set, dbmeta, "VIEW", null); return set; } private static void readDBTable(Set<String> set, DatabaseMetaData dbmeta, String searchCriteria, String schema) throws SQLException { try (ResultSet rs = dbmeta.getTables(null, schema, null, new String[]{ searchCriteria })) { while (rs.next()) { log.trace("readDBTable Table: {}" , rs.getString("TABLE_NAME")); set.add(rs.getString("TABLE_NAME")); } } } }