package test;

import javax.sql.DataSource;
import java.sql.*;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.mariadb.jdbc.MariaDbDataSource;

public class MariaDB_Regression2
{
  public static final String VERSION =
    "  SELECT version() as serverVersion";

  public static final String DROP_TABLE =
    "  DROP TABLE IF EXISTS products";

  public static final String CREATE_TABLE =
    "  CREATE TABLE IF NOT EXISTS products (\n" +
    "    id       int unsigned AUTO_INCREMENT NOT NULL,\n" +
    "    name     varchar( 100 ) NOT NULL,\n" +
    "    created  datetime DEFAULT CURRENT_TIMESTAMP NOT NULL,\n" +
    "    PRIMARY KEY ( id )\n" +
    "  ) DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci";

  public static final String ADD_PRODUCT =
    "  SET @name := '123';\n" +
    "  INSERT INTO products( name ) VALUES ( @name )";

  private static DataSource getDataSource() throws SQLException
  {
    final String url = "jdbc:mariadb://192.168.1.90:3306/test?autoReconnect=true&allowMultiQueries=true&rewriteBatchedStatements=true";
    final String username = "test_admin";
    final String password = "test_admin";
    MariaDbDataSource dataSource = new MariaDbDataSource();
    dataSource.setUrl( url );
    dataSource.setUser( username );
    dataSource.setPassword( password );
    return ( dataSource );
  }

  protected static List<Map<String,Object>> getData( final ResultSet rs ) throws SQLException
  {
    final List<Map<String,Object>> result = new ArrayList<>();
    final ResultSetMetaData rsmd = rs.getMetaData();
    final int maxColumns = rsmd.getColumnCount();
    while( rs.next() )
    {
      final Map<String,Object> entry = new LinkedHashMap<>();
      for( int columnNumber = 0; columnNumber++ < maxColumns; )
      {
        final String name = rsmd.getColumnLabel( columnNumber );
        final Object value = rs.getObject( columnNumber );// DP: or use: public <T> T getObject(int columnIndex, Class<T> type)
        entry.put( name, value );
      }
      result.add( entry );
    }
    return ( result );
  }

  public static List<Map<String,Object>> run( final DataSource ds, final String stmt ) throws SQLException
  {
    System.out.println( " running:\n" + stmt );
    final Connection con = ds.getConnection();
    con.setAutoCommit( false );
    final PreparedStatement statement = con.prepareStatement( stmt );
    final List<Map<String,Object>> result = getData( statement.executeQuery() );
    con.commit();
    con.setAutoCommit( true );
    return ( result );
  }

  public static void runBatch( final DataSource ds, final String stmt ) throws SQLException
  {
    System.out.println( " running batch:\n" + stmt );
    final Connection con = ds.getConnection();
    con.setAutoCommit( false );
    PreparedStatement statement = con.prepareStatement( stmt );
    for( int index = 0; index < 1000; index++ )
    {
      statement.addBatch();
      statement.clearParameters();
      if( 199 == index % 200 )
      {
        statement.executeBatch();
        statement.clearBatch();
      }
    }
    statement.executeBatch();
    statement.clearBatch();
    con.commit();
    con.setAutoCommit( true );
  }

  public static void main( String[] args ) throws SQLException
  {
    final DataSource ds = getDataSource();
    System.out.println( " Server version: " + run( ds, VERSION ) );
    try( Connection connection = ds.getConnection() )
    {
      System.out.println( " Driver version: " + connection.getMetaData().getDriverVersion() );
    }
    run( ds, DROP_TABLE );
    run( ds, CREATE_TABLE );
    runBatch( ds, ADD_PRODUCT );
  }
}