package org.mariadb.jdbc;

import static org.junit.Assert.*;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import org.junit.Before;
import org.junit.Test;

/**
 * This test case tests the "is"-methods using a streaming ResultSet
 * 
 * @author Lennart Schedin
 */
public class ResultSetStreamingCursorTest {
    
    /*
      To use Mysql JDBC and H2 in-memory database 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>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <version>1.4.178</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 connection;
    private Statement statement;
    
    /**
     * Change this method to switch between the 3 different JDBC implementations. Note that H2
     * is an in-memory database that will run inside your JVM and thus no external database server
     * is needed for H2.
     */
    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");
//        return DriverManager.getConnection("jdbc:h2:mem:myTestDatabase;DB_CLOSE_DELAY=-1");
    }
    
    @Before
    public void setUp() throws SQLException {
        connection = getConnection();
        statement = connection.createStatement();
        statement.setFetchSize(Integer.MIN_VALUE);
        statement.execute("drop table if exists result_set_cursor_pointing_test");
        statement.execute("create table result_set_cursor_pointing_test (id int not null primary key auto_increment, name char(20))");
    }

    @Test
    public void isBeforeFirstTest() throws SQLException {
        insertRows(1);
        ResultSet resultSet = statement.executeQuery("SELECT * FROM result_set_cursor_pointing_test");
        assertTrue(resultSet.isBeforeFirst());
        while(resultSet.next()) {
            assertFalse(resultSet.isBeforeFirst()); //MariaDB JDBC will fail here.
        }
        assertFalse(resultSet.isBeforeFirst());
        resultSet.close();
        try {
            resultSet.isBeforeFirst();
            fail("The above row should have thrown an SQLException"); //MariaDB JDBC will fail here
        } catch (SQLException e) {
            //Make sure an exception has been thrown informing us that the ResultSet was closed
            assertTrue(e.getMessage().contains("closed"));
        }
    }
    
    @Test
    public void isBefore_First_ZeroRowsTest() throws SQLException {
        insertRows(0);
        ResultSet resultSet = statement.executeQuery("SELECT * FROM result_set_cursor_pointing_test");
        assertFalse(resultSet.isBeforeFirst()); //Both Mysql and MariaDBC JDBC will fail here
        resultSet.next();
        assertFalse(resultSet.isBeforeFirst());
        resultSet.close();
        try {
            resultSet.isBeforeFirst();
            fail("The above row should have thrown an SQLException"); //MariaDB JDBC will fail here
        } catch (SQLException e) {
            //Make sure an exception has been thrown informing us that the ResultSet was closed
            assertTrue(e.getMessage().contains("closed"));
        }
    }
      
    private void insertRows(int numberOfRowsToInsert) throws SQLException {
        for (int i = 1; i <= numberOfRowsToInsert; i++) {
            statement.executeUpdate("INSERT INTO result_set_cursor_pointing_test VALUES(" + i + ", 'row" + i + "')");    
        }
    }

}
