
prerna.ds.rdbms.h2.H2Frame Maven / Gradle / Ivy
The newest version!
package prerna.ds.rdbms.h2;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.Vector;
import java.util.zip.GZIPInputStream;
import javax.crypto.Cipher;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.h2.tools.DeleteDbFiles;
import org.h2.tools.RunScript;
import org.h2.tools.Server;
import prerna.cache.CachePropFileFrameObject;
import prerna.ds.QueryStruct;
import prerna.ds.rdbms.AbstractRdbmsFrame;
import prerna.ds.rdbms.RdbmsFrameBuilder;
import prerna.om.ThreadStore;
import prerna.query.querystruct.AbstractQueryStruct.QUERY_STRUCT_TYPE;
import prerna.query.querystruct.HardSelectQueryStruct;
import prerna.query.querystruct.SelectQueryStruct;
import prerna.query.querystruct.joins.BasicRelationship;
import prerna.query.querystruct.joins.IRelation;
import prerna.query.querystruct.joins.RelationSet;
import prerna.reactor.imports.RdbmsImporter;
import prerna.ui.components.playsheets.datamakers.DataMakerComponent;
import prerna.ui.components.playsheets.datamakers.ISEMOSSTransformation;
import prerna.ui.components.playsheets.datamakers.JoinTransformation;
import prerna.util.Constants;
import prerna.util.PortAllocator;
import prerna.util.Utility;
import prerna.util.insight.InsightUtility;
import prerna.util.sql.AbstractSqlQueryUtil;
import prerna.util.sql.RdbmsTypeEnum;
import prerna.util.sql.SqlQueryUtilFactory;
public class H2Frame extends AbstractRdbmsFrame {
private Logger logger = LogManager.getLogger(H2Frame.class);
private String fileLocation;
private String fileNameToUse;
private Server server = null;
private String serverURL = null;
private Map tablePermissions = null;
public H2Frame() {
super();
}
public H2Frame(String tableName) {
super(tableName);
}
public H2Frame(String[] headers) {
super(headers);
}
public H2Frame(String[] headers, String[] types) {
super(headers, types);
}
protected void initConnAndBuilder() throws Exception {
this.util = SqlQueryUtilFactory.initialize(RdbmsTypeEnum.H2_DB);
String sessionId = ThreadStore.getSessionId();
String insightId = ThreadStore.getInsightId();
String folderToUsePath = null;
if(sessionId != null && insightId != null) {
sessionId = InsightUtility.getFolderDirSessionId(sessionId);
folderToUsePath = Utility.getInsightCacheDir() +
DIR_SEPARATOR + sessionId + DIR_SEPARATOR + insightId;
this.fileNameToUse = "H2_Store_" + UUID.randomUUID().toString().toUpperCase().replaceAll("-", "_") + ".mv.db";
} else {
folderToUsePath = Utility.getInsightCacheDir() +
DIR_SEPARATOR + "H2_Store_" + UUID.randomUUID().toString().toUpperCase().replaceAll("-", "_");
this.fileNameToUse = "database.mv.db";
}
// create the location of the file if it doesn't exist
File folderToUse = new File(folderToUsePath);
if(!folderToUse.exists()) {
folderToUse.mkdirs();
}
this.fileLocation = folderToUsePath + DIR_SEPARATOR + this.fileNameToUse;
// make the actual file so the connection helper knows its not a tcp protocol
File fileToUse = new File(this.fileLocation);
if(!fileToUse.exists()) {
fileToUse.createNewFile();
}
// build the connection url
Map connDetails = new HashMap<>();
connDetails.put(AbstractSqlQueryUtil.HOSTNAME, fileLocation);
connDetails.put(AbstractSqlQueryUtil.ADDITIONAL, "LOG=0;CACHE_SIZE=65536;LOCK_MODE=1;UNDO_LOG=0");
String connectionUrl = this.util.setConnectionDetailsfromMap(connDetails);
// get the connection
this.conn = AbstractSqlQueryUtil.makeConnection(RdbmsTypeEnum.H2_DB, connectionUrl, "sa", "");
// set the builder
this.builder = new RdbmsFrameBuilder(this.conn, this.database, this.schema, this.util);
this.util.enhanceConnection(this.conn);
}
@Override
public void close() {
super.close();
File f = new File(Utility.normalizePath(this.fileLocation));
DeleteDbFiles.execute(f.getParent().replace('\\','/'), this.fileNameToUse.replace(".mv.db", ""), false);
if(f.exists()) {
f.delete();
}
// also delete the parent folder
File pF = f.getParentFile();
// this condition should always be the case
if(pF.listFiles() != null && pF.listFiles().length == 0) {
f.getParentFile().delete();
}
}
@Override
public CachePropFileFrameObject save(String folderDir, Cipher cipher) throws IOException {
CachePropFileFrameObject cf = new CachePropFileFrameObject();
String frameName = this.getName();
cf.setFrameName(frameName);
//save frame
String frameFileName = folderDir + DIR_SEPARATOR + frameName + ".gz";
String saveScript = "SCRIPT TO '" + frameFileName + "' COMPRESSION GZIP TABLE " + frameName;
Statement stmt = null;
try {
// removing our custom aggregates so the file could be used/loaded elsewhere
stmt = this.conn.createStatement();
stmt.execute("DROP AGGREGATE IF EXISTS SMSS_MEDIAN");
stmt.close();
stmt = this.conn.createStatement();
stmt.execute(saveScript);
} catch (Exception e) {
throw new IOException("Error occurred attempting to cache SQL Frame", e);
} finally {
if(stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
logger.error(Constants.STACKTRACE, e);
}
}
}
if(!new File(frameFileName).exists()) {
throw new IllegalArgumentException("Unable to save the H2 frame");
}
if(new File(frameFileName).length() == 0){
throw new IllegalArgumentException("Attempting to save an empty H2 frame");
}
cf.setFrameCacheLocation(frameFileName);
// also save the meta details
this.saveMeta(cf, folderDir, frameName, cipher);
return cf;
}
@Override
public void open(CachePropFileFrameObject cf, Cipher cipher) throws IOException {
//set the frame name to that of the cached frame name
this.frameName = cf.getFrameName();
// load the frame
String filePath = Utility.normalizePath(cf.getFrameCacheLocation());
// drop the aggregate if it exists since the opening of the script will
// fail otherwise
// Statement stmt = null;
// try {
// stmt = this.conn.createStatement();
// stmt.executeUpdate("DROP AGGREGATE IF EXISTS MEDIAN");
// } catch (SQLException e1) {
// classLogger.error(Constants.STACKTRACE, e1);
// } finally {
// if(stmt != null) {
// try {
// stmt.close();
// } catch (SQLException e) {
// logger.error(Constants.STACKTRACE, e);
// }
// }
// }
Reader r = null;
GZIPInputStream gis = null;
FileInputStream fis = null;
try {
//load the frame
fis = new FileInputStream(filePath);
gis = new GZIPInputStream(fis);
r = new InputStreamReader(gis);
RunScript.execute(this.conn, r);
} catch (SQLException e) {
logger.error(Constants.STACKTRACE, e);
throw new IOException("Error occurred opening cached SQL Frame");
} finally {
try {
if(fis != null) {
fis.close();
}
if(gis != null) {
gis.close();
}
if(r != null) {
r.close();
}
} catch (IOException e) {
logger.error(Constants.STACKTRACE, e);
}
// open the meta details
this.openCacheMeta(cf, cipher);
}
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
/*
* Random methods I am pulling from the old H2Builder
* Not specifically used in any workflow at the moment
*/
public String connectFrame(String pass) {
if (server == null) {
try {
String port = PortAllocator.getInstance().getNextAvailablePort()+"";
// create a random user and password
// get the connection object and start up the frame
server = Server.createTcpServer("-tcpPort", port, "-tcpAllowOthers");
// server = Server.createPgServer("-baseDir", "~",
// "-pgAllowOthers"); //("-tcpPort", "9999");
serverURL = "jdbc:h2:" + server.getURL() + "/nio:" + this.schema;
server.start();
} catch (SQLException e) {
logger.error(Constants.STACKTRACE, e);
}
}
printSchemaTables(pass);
System.out.println("URL... " + serverURL);
return serverURL;
}
private void printSchemaTables(String pass) {
Connection conn = null;
ResultSet rs = null;
try {
Class.forName("org.h2.Driver");
String url = serverURL;
conn = DriverManager.getConnection(url, "sa", pass);
rs = conn.createStatement()
.executeQuery("SELECT TABLE_NAME FROM INFORMATIOn_SCHEMA.TABLES WHERE TABLE_SCHEMA='PUBLIC'");
while (rs.next()) {
System.out.println("Table name is " + rs.getString(1));
}
// String schema = this.conn.getSchema();
System.out.println(".. " + conn.getMetaData().getURL());
System.out.println(".. " + conn.getMetaData().getUserName());
} catch (ClassNotFoundException | SQLException e) {
logger.error(Constants.STACKTRACE, e);
} finally {
if(conn!=null) {
try {
conn.close();
} catch (SQLException e) {
logger.error(Constants.STACKTRACE, e);
}
}
if(rs != null) {
try {
rs.close();
} catch (SQLException e) {
logger.error(Constants.STACKTRACE, e);
}
}
}
}
public String[] createUser(String tableName) {
if(tablePermissions == null) {
tablePermissions = new Hashtable<>();
}
// really simple
// find an open port
// once found
// create url with connection string and send it back
// need to pass the username and password back
// the username is specific to an insight and possibly gives access only
// to that insight
// I need to get the insight table - i.e. the table backing the insight
String[] retString = new String[2];
Statement stmt = null;
if (!tablePermissions.containsKey(tableName)) {
try {
// create a random user and password
stmt = conn.createStatement();
String userName = Utility.getRandomString(23);
String password = Utility.getRandomString(23);
retString[0] = userName;
retString[1] = password;
String query = "CREATE USER " + userName + " PASSWORD '" + password + "'";
stmt.executeUpdate(query);
// should not give admin permission
// query = "ALTER USER " + userName + " ADMIN TRUE";
// create a new role for this table
query = "CREATE ROLE IF NOT EXISTS " + tableName + "READONLY";
stmt.executeUpdate(query);
query = "GRANT SELECT, INSERT, UPDATE ON " + tableName + " TO " + tableName + "READONLY";
stmt.executeUpdate(query);
// assign this to our new user
query = "GRANT " + tableName + "READONLY TO " + userName;
stmt.executeUpdate(query);
//System.out.println("username " + userName);
//System.out.println("Pass word " + password);
tablePermissions.put(tableName, retString);
} catch (SQLException e) {
logger.error(Constants.STACKTRACE, e);
} finally {
if(stmt != null){
try {
stmt.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
logger.error(Constants.STACKTRACE, e);
}
}
}
}
return tablePermissions.get(tableName);
}
public void disconnectFrame() {
server.stop();
server = null;
serverURL = null;
}
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
/*
* Legacy calls
*/
/**
* Execute and get back a result set
* Responsibility of the method to grab the statement and close it
* from the result set
* @param query
* @return
*/
public ResultSet execQuery(String query) {
PreparedStatement stmt = null;
boolean error = false;
try {
//Statement stmt = this.conn.createStatement();
stmt = this.conn.prepareStatement(query);
return stmt.executeQuery();
} catch (SQLException e) {
error = true;
logger.error(Constants.STACKTRACE, e);
} finally {
// it is the responsibility of the code executing this
// to take the statement and close it if no error
if(error && stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
logger.error(Constants.STACKTRACE, e);
}
}
}
return null;
}
public void deleteAllRows() {
String query = "DELETE FROM " + this.frameName + " WHERE 1 != 0";
try {
this.builder.runQuery(query);
} catch (Exception e) {
logger.error(Constants.STACKTRACE, e);
}
}
@Override
@Deprecated
public void processDataMakerComponent(DataMakerComponent component) {
long startTime = System.currentTimeMillis();
logger.info("Processing Component..................................");
List preTrans = component.getPreTrans();
Vector
© 2015 - 2025 Weber Informatics LLC | Privacy Policy