package org.sfm.benchmark.db.sfm;

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

import javax.naming.NamingException;

import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.Param;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.infra.Blackhole;
import org.sfm.beans.SmallBenchmarkObject;
import org.sfm.benchmark.db.jmh.ConnectionParam;
import org.sfm.benchmark.db.jmh.DbTarget;
import org.sfm.benchmark.db.jmh.LimitParam;
import org.sfm.jdbc.JdbcMapper;
import org.sfm.jdbc.JdbcMapperFactory;
import org.sfm.reflect.asm.AsmHelper;

@State(Scope.Benchmark)
public class JdbcMapperDynamicBenchmark  {
	

	
	private JdbcMapper<SmallBenchmarkObject> mapper;
	@Param(value= {"true", "false"})
	private boolean useAsm;
	
	@Setup
	public void init() {
		if (useAsm && ! AsmHelper.isAsmPresent()) {
			throw new RuntimeException("Asm not present or incompatible");
		}
		
		mapper = JdbcMapperFactory.newInstance().useAsm(useAsm).newMapper(SmallBenchmarkObject.class);
	}
	
	@Benchmark
	public void testQuery(ConnectionParam connectionParam, LimitParam limitParam, Blackhole blackhole) throws Exception {
		Connection conn = connectionParam.getConnection();
		try {
			PreparedStatement ps = conn.prepareStatement("SELECT id, name, email, year_started FROM test_small_benchmark_object LIMIT ?");
			try {
				ps.setInt(1, limitParam.limit);
				ResultSet rs = ps.executeQuery();
				while(rs.next()) {
					Object o = mapper.map(rs);
					blackhole.consume(o);
				}
			}finally {
				ps.close();
			}
		}finally {
			conn.close();
		}
	}
	
	public static void main(String[] args) throws SQLException, NamingException {
		ConnectionParam connectionParam = new ConnectionParam();
		connectionParam.db = DbTarget.HSQLDB;
		connectionParam.init();
		Connection conn = connectionParam.getConnection();
		
		JdbcMapper<SmallBenchmarkObject> mapper = JdbcMapperFactory.newInstance().useAsm(false).newMapper(SmallBenchmarkObject.class);

		try {
			PreparedStatement ps = conn.prepareStatement("SELECT id, name, email, year_started FROM test_small_benchmark_object LIMIT ?");
			try {
				ps.setInt(1, 10);
				ResultSet rs = ps.executeQuery();
				while(rs.next()) {
					Object o = mapper.map(rs);
					System.out.println(o);
				}
			}finally {
				ps.close();
			}
		}finally {
			conn.close();
		}
		
	}
}

@@ -727,16 +727,49 @@
 mHelper;
+%0Aimport org.sfm.utils.RowHandler;
 %0A%0A@State
@@ -1761,16 +1761,735 @@
 %0A%09%09%7D%0A%09%7D%0A
+%0A%0A%09@Benchmark%0A%09public void testQueryForEach(ConnectionParam connectionParam, LimitParam limitParam, final Blackhole blackhole) throws Exception %7B%0A%09%09Connection conn = connectionParam.getConnection();%0A%09%09try %7B%0A%09%09%09PreparedStatement ps = conn.prepareStatement(%22SELECT id, name, email, year_started FROM test_small_benchmark_object LIMIT ?%22);%0A%09%09%09try %7B%0A%09%09%09%09ps.setInt(1, limitParam.limit);%0A%09%09%09%09ResultSet rs = ps.executeQuery();%0A%09%09%09%09mapper.forEach(rs, new RowHandler%3CSmallBenchmarkObject%3E() %7B%0A%09%09%09%09%09@Override%0A%09%09%09%09%09public void handle(SmallBenchmarkObject smallBenchmarkObject) throws Exception %7B%0A%09%09%09%09%09%09blackhole.consume(smallBenchmarkObject);%0A%09%09%09%09%09%7D%0A%09%09%09%09%7D);%0A%09%09%09%7Dfinally %7B%0A%09%09%09%09ps.close();%0A%09%09%09%7D%0A%09%09%7Dfinally %7B%0A%09%09%09conn.close();%0A%09%09%7D%0A%09%7D%0A
 %09%0A%09publi

add foreach loop