diff 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 diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/luan/modules/sql/Database.java	Mon Nov 12 02:10:41 2018 -0700
@@ -0,0 +1,120 @@
+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();
+	}
+
+}