/*
 * ByteaTest.java
 *
 * Created on August 22, 2006, 8:09 PM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package com.evolute.postgresql.test;

import java.sql.*;
import java.util.zip.*;

/**
 *
 * @author lvflores
 */
public class ByteaTest
{
    private static String url = "jdbc:postgresql://localhost/test_bytea";
    private static String user = "postgres";
    private static String password = "";
    
    private static final int RUNS = 35;
    
    private final CRC32 crcCalc = new CRC32();
    
    private Connection connection = null;
    
    private long crc32[] = new long[ RUNS ];
    
    /** Creates a new instance of ByteaTest */
    public ByteaTest( String pgUrl, String pgUser, String pgPass )
	throws Exception
    {
	Class.forName( "org.postgresql.Driver" );
	connection = DriverManager.getConnection( pgUrl, pgUser, pgPass );
	createTable();
	test();
	deleteTable();
	connection.close();
    }
    
    
    private void createTable()
	throws Exception
    {
	Statement stm = connection.createStatement();
	try
	{
	    stm.executeUpdate( "DROP TABLE test_bytea" );
	}
	catch( Exception ex )
	{
	}
	stm.executeUpdate( "CREATE TABLE test_bytea ("
		+ "id INT NOT NULL, "
		+ "data BYTEA )" );
	stm.close();
    }
    
    private void test()
	throws Exception
    {
	// insert
	for( int i = 0; i < RUNS; ++i )
	{
	    PreparedStatement pstm = connection.prepareStatement( "INSERT INTO test_bytea ( id, data ) VALUES ( ?, ? )" );
	    pstm.setInt( 1, i );
	    byte data[] = generateBytes( i );
//	    long l = System.currentTimeMillis();
	    pstm.setBytes( 2, data );
//	    long l1 = System.currentTimeMillis();
	    pstm.execute();
//	    long l2 = System.currentTimeMillis();
	    long usedMem = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
//	    System.out.println( "size: " + i + ".5MB setBytes: " + ( l1 -l ) 
//		    + "ms execute: " + ( l2 -l1 ) + "ms used mem: " + ( usedMem / 1024 ) + "KB" );
	    pstm.close();
	    System.gc();
	}
	// select and check
	for( int i = 0; i < RUNS; ++i )
	{
	    PreparedStatement pstm = connection.prepareStatement( "SELECT data FROM test_bytea WHERE ID = ?" );
	    pstm.setInt( 1, i );
	    long l = System.currentTimeMillis();
	    ResultSet rs = pstm.executeQuery();
	    rs.next();
	    long l1 = System.currentTimeMillis();
	    byte data[] = rs.getBytes( 1 );
	    long l2 = System.currentTimeMillis();
	    crcCalc.reset();
	    crcCalc.update( data );
	    long crc = crcCalc.getValue();
	    if( crc != crc32[ i ] )
	    {
		System.out.println( "WRONG DATA on idx " + i );
	    }
	    long usedMem = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
	    System.out.println( "size: " + i + ".5MB execute+next: " + ( l1 -l ) 
		    + "ms getBytes: " + ( l2 -l1 ) + "ms used mem: " + ( usedMem / 1024 ) + "KB" );
	    pstm.close();
	    System.gc();
	}
    }
    
    private byte[] generateBytes( int idx )
    {
	
	byte data[] = new byte[ 1024 * 1024 * idx + 512 * 1024 ];
	
	for( int i = 0; i < data.length; ++i )
	{
	    data[ i ] = ( byte )i;
	}
	
	crcCalc.reset();
	crcCalc.update( data );
	crc32[ idx ] = crcCalc.getValue();
	return data;
    }
    
    private void deleteTable()
	throws Exception
    {
	Statement stm = connection.createStatement();
	stm.executeUpdate( "DROP TABLE test_bytea" );
	stm.close();
    }
    
    public static void main( String arg[] )
	throws Exception
    {
	if( arg.length != 0 && arg.length != 3 )
	{
		System.err.println( "Usage: java com.evolute.postgresql.test.ByteaTest <URL> <USER> <PASSWORD>" );
	}
	else if( arg.length == 3 )
	{
	    url = arg[ 0 ];
	    user = arg[ 1 ];
	    password = arg[ 2 ];
	}
	new ByteaTest( url, user, password );
    }
}
