using System; using System.Collections.Generic; using System.Linq; using System.Text; using MySql.Data.MySqlClient; using ProxyCore; using ProxyCore.Scripting; namespace MySQL { public class MySQL : Plugin { public MySQL() : base("mysql", "MySQL Database") { Author = "Duckbat"; Version = 1; Description = "Provides easy access to MySQL database."; UpdateUrl = "www.duckbat.com/plugins/update.mysql.txt"; Website = "code.google.com/p/proxymud/"; Config = new MySQLConfig(); } internal static long MSTime; private Database db; private void InitDB() { if(db == null) db = new Database(Config.GetString("MySQL.Host", "localhost"), Config.GetString("MySQL.User", "root"), Config.GetString("MySQL.Pass", "pass"), Config.GetInt32("MySQL.Port", 3306), Config.GetString("MySQL.Database", "aardwolf")); } public override void Shutdown() { base.Shutdown(); if(db != null) { db.CloseAll(); db = null; } } public override void Update(long msTime) { base.Update(msTime); MSTime = msTime; if(db != null) db.Update(msTime); } /// /// Query data from the database. /// /// /// public QueryData Query(string q) { InitDB(); return db.Query(q); } /// /// Execute a query in the database. /// /// public void Execute(string q) { InitDB(); db.Execute(q); } } public class MySQLConfig : ConfigFile { protected override void OnCreated() { base.OnCreated(); CreateSetting("MySQL.Host", "localhost", "Hostname for MySQL connection."); CreateSetting("MySQL.Port", 3306, "Port for MySQL connection."); CreateSetting("MySQL.User", "root", "Username for MySQL connection."); CreateSetting("MySQL.Pass", "pass", "Password for MySQL connection."); CreateSetting("MySQL.Database", "aardwolf", "Database name for the MySQL connection."); } } internal class Database { internal Database(string Host, string Login, string Password, int Port, string dbName) { host = Host; login = Login; password = Password; port = Port; DBName = dbName; } private readonly string host; private readonly string login; private readonly string password; private readonly int port; private readonly string DBName; private Dictionary _con = new Dictionary(); private MySqlConnection freeConnection = null; private long freeTimer = 0; internal void Update(long msTime) { if(freeConnection != null && freeTimer < msTime) { freeConnection.Close(); freeConnection = null; } QueryData idle = null; foreach(KeyValuePair x in _con) { if(x.Key.IsIdle) { idle = x.Key; break; } } if(idle != null) _CloseResult(idle); } internal void CloseAll() { if(freeConnection != null) { freeConnection.Close(); freeConnection = null; } foreach(KeyValuePair x in _con) { x.Key._Close(); x.Value.Close(); } _con.Clear(); } internal void _CloseResult(QueryData data) { data._Close(); if(!_con.ContainsKey(data)) return; if(freeConnection == null) freeConnection = _con[data]; _con.Remove(data); freeTimer = MySQL.MSTime + 3000; } internal QueryData Query(string q) { MySqlConnection con = null; if(freeConnection == null) { string conString = "SERVER=" + host + ";DATABASE=" + DBName + ";UID=" + login + ";PASSWORD=" + password + ";PORT=" + port.ToString() + ";"; con = new MySqlConnection(conString); con.Open(); } else { con = freeConnection; freeConnection = null; } MySqlCommand cmd = con.CreateCommand(); cmd.CommandText = q; MySqlDataReader reader = cmd.ExecuteReader(); QueryData m = new QueryData(reader, this); _con[m] = con; return m; } internal void Execute(string q) { MySqlConnection con = null; if(freeConnection == null) { string conString = "SERVER=" + host + ";DATABASE=" + DBName + ";UID=" + login + ";PASSWORD=" + password + ";PORT=" + port.ToString() + ";"; con = new MySqlConnection(conString); con.Open(); } else con = freeConnection; MySqlCommand cmd = con.CreateCommand(); cmd.CommandText = q; cmd.ExecuteNonQuery(); if(freeConnection == null) freeConnection = con; else if(freeConnection != con) con.Close(); freeTimer = MySQL.MSTime + 3000; } } public class QueryData { internal QueryData(MySqlDataReader res, Database connection) { r = res; db = connection; lastUpdate = MySQL.MSTime; } internal readonly MySqlDataReader r; internal readonly Database db; private long lastUpdate; internal bool IsIdle { get { return MySQL.MSTime - lastUpdate > 5000; } } /// /// Close and free the result. /// public void Close() { db._CloseResult(this); } internal void _Close() { if(!r.IsClosed) r.Close(); } /// /// Read the next row in the result. If next row exists true will be returned, otherwise false. /// /// public bool Read() { lastUpdate = MySQL.MSTime; return r.Read(); } /// /// Read a double value in the specified field. Field index starts with 0. /// /// /// public double GetDouble(int i) { lastUpdate = MySQL.MSTime; if(r.FieldCount > i && !r.IsDBNull(i)) return r.GetDouble(i); return 0; } /// /// Read a float value in the specified field. Field index starts with 0. /// /// /// public float GetFloat(int i) { lastUpdate = MySQL.MSTime; if(r.FieldCount > i && !r.IsDBNull(i)) return r.GetFloat(i); return 0; } /// /// Read an integer value in the specified field. Field index starts with 0. /// /// /// public int GetInt32(int i) { lastUpdate = MySQL.MSTime; if(r.FieldCount > i && !r.IsDBNull(i)) return r.GetInt32(i); return 0; } /// /// Read an unsigned integer value in the specified field. Field index starts with 0. /// /// /// public uint GetUInt32(int i) { lastUpdate = MySQL.MSTime; if(r.FieldCount > i && !r.IsDBNull(i)) return r.GetUInt32(i); return 0; } /// /// Read a long value in the specified field. Field index starts with 0. /// /// /// public long GetInt64(int i) { lastUpdate = MySQL.MSTime; if(r.FieldCount > i && !r.IsDBNull(i)) return r.GetInt64(i); return 0; } /// /// Read an unsigned long value in the specified field. Field index starts with 0. /// /// /// public ulong GetUInt64(int i) { lastUpdate = MySQL.MSTime; if(r.FieldCount > i && !r.IsDBNull(i)) return r.GetUInt64(i); return 0; } /// /// Read a string value in the specified field. Field index starts with 0. /// /// /// public string GetString(int i) { lastUpdate = MySQL.MSTime; if(r.FieldCount > i && !r.IsDBNull(i)) return r.GetString(i); return null; } /// /// Read a short value in the specified field. Field index starts with 0. /// /// /// public short GetInt16(int i) { lastUpdate = MySQL.MSTime; if(r.FieldCount > i && !r.IsDBNull(i)) return r.GetInt16(i); return 0; } /// /// Read an unsigned short value in the specified field. Field index starts with 0. /// /// /// public ushort GetUInt16(int i) { lastUpdate = MySQL.MSTime; if(r.FieldCount > i && !r.IsDBNull(i)) return r.GetUInt16(i); return 0; } /// /// Read a byte value in the specified field. Field index starts with 0. /// /// /// public byte GetByte(int i) { lastUpdate = MySQL.MSTime; if(r.FieldCount > i && !r.IsDBNull(i)) return r.GetByte(i); return 0; } /// /// Read a char value in the specified field. Field index starts with 0. /// /// /// public char GetChar(int i) { lastUpdate = MySQL.MSTime; if(r.FieldCount > i && !r.IsDBNull(i)) return r.GetChar(i); return '\0'; } /// /// Read a boolean value in the specified field. Field index starts with 0. /// /// /// public bool GetBool(int i) { lastUpdate = MySQL.MSTime; if(r.FieldCount > i && !r.IsDBNull(i)) return r.GetBoolean(i); return false; } /// /// Read a date time value in the specified field. Field index starts with 0. /// /// /// public DateTime GetDateTime(int i) { lastUpdate = MySQL.MSTime; if(r.FieldCount > i && !r.IsDBNull(i)) return r.GetDateTime(i); return DateTime.MinValue; } /// /// Read a time span value in the specified field. Field index starts with 0. /// /// /// public TimeSpan GetTimeSpan(int i) { lastUpdate = MySQL.MSTime; if(r.FieldCount > i && !r.IsDBNull(i)) return r.GetTimeSpan(i); return TimeSpan.Zero; } /// /// Read an object value in the specified field. Field index starts with 0. /// /// /// public object GetValue(int i) { lastUpdate = MySQL.MSTime; if(r.FieldCount > i && !r.IsDBNull(i)) return r.GetValue(i); return 0; } } }