package org.mariadb.jdbc;

import java.lang.management.ManagementFactory;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Date;

import javax.management.MBeanServer;

import org.junit.Test;

public class BigResultSetMemoryOptimization {

    /*
    To use Mysql JDBC add the following to the pom.xml:
      <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
          <version>5.1.26</version>
          <scope>test</scope>
      </dependency>

    To enable easy switch between MariaDB JDBC and Mysql JDBC:
    Change the class src/main/java/org/mariadb/jdbc/JDBCUrl.java in the method parse()
    At line 97-ish change to "return null" so the code looks like this: 
    
    if(url.startsWith("jdbc:mysql://")) {
        return null;
    }
    This will make MariaDB JDBC not to accept "jdbc:mysql://" and therefore Mysql will be used.
   */
    
    private Connection getConnection() throws SQLException {
        return DriverManager.getConnection("jdbc:mariadb://localhost:3306/test?user=root");
//      return DriverManager.getConnection("jdbc:mysql://localhost:3306/test?user=root");
    }
    
    @Test
    public void testMemoryFootPrint() throws Exception {
        Connection connection = getConnection();
        Statement statement = connection.createStatement();
        
        createBigTable(statement);
        
        System.out.print("Selecting all rows...");
        ResultSet resultSet = statement.executeQuery("SELECT * FROM BigResultSetMemoryOptimization");
        System.out.println(" done!");
        
        
        Date date = new Date();
        String heapDumpFileName = "target/memory_dump-" +
                        date.getHours() + "_" +
                        date.getMinutes() + "_" +
                        date.getSeconds() + ".hprof";
        dumpHeap(heapDumpFileName);
        
        int numberOfRows = 0;
        while (resultSet.next()) {
            numberOfRows++;
        }
    }

    private void dumpHeap(String heapDumpFileName) throws Exception {
        System.out.print("Creating heap dump to " + heapDumpFileName + " ...");

        //Ugly heap dump using Oracle Java:
        MBeanServer server = ManagementFactory.getPlatformMBeanServer();
        com.sun.management.HotSpotDiagnosticMXBean bean = 
            ManagementFactory.newPlatformMXBeanProxy(server,
                "com.sun.management:type=HotSpotDiagnostic",
                com.sun.management.HotSpotDiagnosticMXBean.class);
        
        bean.dumpHeap(heapDumpFileName, true);
                
        System.out.println(" done!");
        
    }

    private void createBigTable(Statement statement) throws SQLException {
        statement.execute("DROP TABLE IF EXISTS BigResultSetMemoryOptimization");
        
        statement.execute("CREATE TABLE BigResultSetMemoryOptimization (" +
                        "`id_1000001_21debab4ba0048e297622da20f217fe7` decimal(42,0) DEFAULT NULL, " +
                        "`id_1000001_3928a9e86c72445195e489896836a9e9` decimal(42,0) DEFAULT NULL, " +
                        "`id_1000001_18d503d843374344b4f2ffacaa0a2510` decimal(42,0) DEFAULT NULL, " +
                        "`id_1000001_ef411ae6d7254bcd856594644736b34e` decimal(42,0) DEFAULT NULL, " +
                        "`time` bigint(20) unsigned NOT NULL, " +
                        "`imsibcd` bigint(20) NOT NULL DEFAULT '0', " +
                        "`msisdnbcd` bigint(20) NOT NULL DEFAULT '0') " +
                        "ENGINE=Myisam DEFAULT CHARSET=utf8");
        
        
        final int numberOfRows = 100000;
        
        System.out.print("Creating " + numberOfRows + " rows...");
        
        
        int batchSize = 100;
        StringBuilder sb = new StringBuilder();
        sb.append("INSERT INTO BigResultSetMemoryOptimization VALUES ");
        for (int i = 0; i < batchSize; i++) {
            if (i > 0) {
                sb.append(", ");
            }
            sb.append("(1, 0, 1, 0, 1416000000000, 2738224860000000000, 0)");
        }
        sb.append("");
        
        String insertSql = sb.toString();
        
        for (int i = 0; i < numberOfRows / batchSize; i++) {
            statement.execute(insertSql);
        }
        
        System.out.println(" done!");
    }

}
