1 /* 2 * Database - Database abstraction layer for D programing language. 3 * 4 * Copyright (C) 2017 Shanghai Putao Technology Co., Ltd 5 * 6 * Developer: HuntLabs 7 * 8 * Licensed under the Apache-2.0 License. 9 * 10 */ 11 12 module hunt.database.Database; 13 14 import hunt.database.DatabaseOption; 15 import hunt.database.Statement; 16 17 import hunt.database.base; 18 import hunt.database.driver.mysql; 19 import hunt.database.driver.postgresql; 20 import hunt.database.query.QueryBuilder; 21 22 import hunt.logging; 23 import hunt.net.util.HttpURI; 24 import hunt.util.StringBuilder; 25 26 import core.time; 27 28 /** 29 * 30 */ 31 class Database { 32 Pool _pool; 33 DatabaseOption _options; 34 35 this(string url) { 36 this._options = new DatabaseOption(url); 37 initPool(); 38 } 39 40 this(DatabaseOption options) { 41 this._options = options; 42 initPool(); 43 } 44 45 ~this() { 46 close(); 47 } 48 49 DatabaseOption getOption() { 50 return _options; 51 } 52 53 Transaction getTransaction(SqlConnection conn) { 54 return conn.begin(); 55 } 56 57 SqlConnection getConnection() { 58 return _pool.getConnection(); 59 } 60 61 void closeConnection(SqlConnection conn) { 62 conn.close(); 63 } 64 65 void relaseConnection(SqlConnection conn) { 66 conn.close(); 67 } 68 69 private void initPool() { 70 import hunt.database.driver.mysql.impl.MySQLPoolImpl; 71 import hunt.database.driver.postgresql.impl.PostgreSQLPoolImpl; 72 import core.time; 73 74 version (HUNT_DB_DEBUG) { 75 tracef("maximumSize: %d, connectionTimeout: %d, maxWaitQueueSize: %d", 76 _options.maximumPoolSize, _options.connectionTimeout, _options.maxWaitQueueSize); 77 } 78 79 // dfmt off 80 PoolOptions poolOptions = new PoolOptions() 81 .setMaxSize(_options.maximumPoolSize) 82 .retry(_options.retry) 83 .awaittingTimeout(_options.connectionTimeout.msecs) 84 .setMaxWaitQueueSize(_options.maxWaitQueueSize); 85 86 if(_options.isPgsql()) { 87 PgConnectOptions connectOptions = new PgConnectOptions(_options.url); 88 connectOptions.setDecoderBufferSize(_options.getDecoderBufferSize()); 89 connectOptions.setEncoderBufferSize(_options.getEncoderBufferSize()); 90 connectOptions.setConnectTimeout(_options.connectionTimeout().msecs); 91 92 _pool = new PgPoolImpl(connectOptions, poolOptions); 93 } else if(_options.isMysql()) { 94 MySQLConnectOptions connectOptions = new MySQLConnectOptions(_options.url); 95 connectOptions.setDecoderBufferSize(_options.getDecoderBufferSize()); 96 connectOptions.setEncoderBufferSize(_options.getEncoderBufferSize()); 97 connectOptions.setConnectTimeout(_options.connectionTimeout().msecs); 98 99 _pool = new MySQLPoolImpl(connectOptions, poolOptions); 100 101 } else { 102 throw new DatabaseException("Unsupported database driver: " ~ _options.schemeName()); 103 } 104 105 // dfmt on 106 } 107 108 /// return the count of affected rows. 109 int execute(string sql) { 110 RowSet rs = query(sql); 111 return rs.rowCount(); 112 } 113 114 RowSet query(string sql) { 115 version (HUNT_SQL_DEBUG) 116 info(sql); 117 SqlConnection conn = getConnection(); 118 scope (exit) { 119 conn.close(); 120 } 121 122 RowSet rs = conn.query(sql); 123 return rs; 124 } 125 126 Statement prepare(string sql) { 127 SqlConnection conn = getConnection(); 128 Statement ret = new Statement(conn, sql, _options); 129 return ret; 130 } 131 132 Statement prepare(SqlConnection conn, string sql) { 133 Statement ret = new Statement(conn, sql, _options); 134 return ret; 135 } 136 137 void close() { 138 if (_pool !is null) { 139 _pool.close(); 140 _pool = null; 141 } 142 } 143 144 QueryBuilder createQueryBuilder() { 145 import hunt.sql.util.DBType; 146 147 if (_options.isPgsql()) { 148 return new QueryBuilder(DBType.POSTGRESQL); 149 } else if (_options.isMysql()) { 150 return new QueryBuilder(DBType.MYSQL); 151 } else { 152 throw new DatabaseException("Unsupported database driver: " ~ _options.schemeName()); 153 } 154 } 155 156 string poolInfo() { 157 if(_pool is null) { 158 return "unset"; 159 } else { 160 return (cast(Object)_pool).toString(); 161 } 162 } 163 164 }