view src/luan/modules/sql/Database.java @ 1267:9fa8b8389578

add LuanTable.luan; support metatable __gc(); add luan.sql;
author Franklin Schmidt <fschmidt@gmail.com>
date Mon, 12 Nov 2018 02:10:41 -0700
parents
children 725e52076f03
line wrap: on
line source

package luan.modules.sql;

import java.io.Closeable;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Map;
import java.util.HashMap;
import java.util.Properties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import luan.LuanState;
import luan.LuanTable;
import luan.LuanException;


public final class Database implements Closeable {
	private static final Logger logger = LoggerFactory.getLogger(Database.class);

	private static Map<Map,Database> pool = new HashMap<Map,Database>();

	public static Database get(Connection con) {
		return new Database(con);
	}

	public static synchronized Database get(LuanTable specTbl)
		throws LuanException, ClassNotFoundException, SQLException
	{
		Map<Object,Object> spec = specTbl.asMap();
		Database db = pool.get(spec);
		if( db==null ) {
			db = new Database(spec);
			pool.put(spec,db);
		}
		return db;
	}

	public int uses = 0;
	public final Connection con;
	private final Map<String,PreparedStatement> pstmts = new HashMap<String,PreparedStatement>();

	public Database(Connection con) {
		this.con = con;
	}

	private Database(Map<Object,Object> spec)
		throws LuanException, ClassNotFoundException, SQLException
	{
		spec = new HashMap<Object,Object>(spec);
		String cls = getString(spec,"class");
		Class.forName(cls);
		String url = getString(spec,"url");
		Properties props = new Properties();
		props.putAll(spec);
		this.con = DriverManager.getConnection(url,props);
	}

	private static String getString(Map spec,String key) throws LuanException {
		Object val = spec.remove(key);
		if( val==null )
			throw new LuanException( "parameter '"+key+"' is required" );
		if( !(val instanceof String) )
			throw new LuanException( "parameter '"+key+"' must be a string" );
		return (String)val;
	}

	private PreparedStatement prepareStatement(String sql,Object[] args) throws SQLException {
		PreparedStatement pstmt = pstmts.get(sql);
		if( pstmt==null ) {
			pstmt = con.prepareStatement(sql);
			pstmts.put(sql,pstmt);
		}
		for( int i=0; i<args.length; i++ ) {
			pstmt.setObject(i+1,args[i]);
		}
		return pstmt;
	}

	public ResultSet query(String sql,Object... args) throws SQLException {
		if( args.length == 0 ) {
			Statement stmt = con.createStatement();
			return stmt.executeQuery(sql);
		} else {
			PreparedStatement pstmt = prepareStatement(sql,args);
			return pstmt.executeQuery();
		}
	}

	public int update(String sql,Object... args) throws SQLException {
		if( args.length == 0 ) {
			Statement stmt = con.createStatement();
			int n = stmt.executeUpdate(sql);
			stmt.close();
			return n;
		} else {
			PreparedStatement pstmt = prepareStatement(sql,args);
			return pstmt.executeUpdate();
		}
	}

	public void close() {
		try {
			con.close();
		} catch(SQLException e) {
			throw new RuntimeException(e);
		}
	}

	protected void finalize() throws Throwable {
		if( !con.isClosed() ) {
			logger.error("not closed");
			close();
		}
		super.finalize();
	}

}