Mercurial Hosting > luan
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(); + } + +}