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

/**
 * Demonstrates failure: "Could not read resultset: unexpected end of stream, read 0 bytes from 4"
 */
public class UnexpectedEndOfStreamError
{
	private static final String URL = "jdbc:mariadb://localhost:3306/test?user=root";

	/**
	 * Fails with: Could not read resultset: unexpected end of stream, read 0 bytes from 4.
	 * 
	 * <p>Before running test create a test database and update URL.
	 * 
	 * @param args
	 * @throws SQLException
	 */
	public static void main(String[] args) throws SQLException
	{
		final String url = URL;
		
		initSchema(url);
		runTest(url);
	}

	protected static void initSchema(String url) throws SQLException
	{
		try (Connection connection = DriverManager.getConnection(url)) {
			try (Statement statement = connection.createStatement()) {
				statement.execute("CREATE OR REPLACE TABLE A (AID NUMERIC(22))");
				statement.execute("CREATE OR REPLACE TABLE B (AID NUMERIC(22))");
				statement.execute("CREATE OR REPLACE TABLE C (AID NUMERIC(22), C VARCHAR(5))");
				statement.execute("CREATE OR REPLACE VIEW V AS (SELECT c.AID, c.C FROM C c INNER JOIN B b ON b.AID = c.AID)");
			}
		}
	}

	private static void runTest(String url) throws SQLException
	{
		try (Connection connection = DriverManager.getConnection(url)) {
			connection.setAutoCommit(false);
			
			executeTestQuery(connection);
			executeTestQuery(connection);
		}
	}

	private static void executeTestQuery(Connection connection) throws SQLException
	{
		try (PreparedStatement statement = connection.prepareStatement("SELECT a.AID FROM A a WHERE EXISTS (SELECT 1 FROM V v WHERE a.AID = v.AID)")) {
			try (ResultSet resultSet = statement.executeQuery()) {
				resultSet.next();
			}
		}
		
		connection.rollback();
	}
}