using System; using System.Data.Odbc; using System.Collections; using Woodpecker.Core; namespace Woodpecker.Data { /// /// Provides high speed data access to the MySQL database. /// public static class Database { private static OdbcConnection dbConnection; #region Database connection management /// /// Opens connection to the MySQL database with the supplied parameters, and returns a 'true' boolean when the connection has succeeded. Requires MySQL ODBC 5.1 driver to be installed. /// /// The hostname/IP address where the database server is located. /// The port the database server is running on. /// The name of the database. /// The username for authentication with the database. /// The pasword for authentication with the database. public static bool openConnection(string dbHost, int dbPort, string dbName, string dbUsername, string dbPassword) { try { IO.PrintLine("Connecting to " + dbName + " at " + dbHost + ":" + dbPort + " for user '" + dbUsername + "'", IO.logImportancies.Info); dbConnection = new OdbcConnection("Driver={MySQL ODBC 5.1 Driver};Server=" + dbHost + ";Port=" + dbPort + ";Database=" + dbName + ";User=" + dbUsername + ";Password=" + dbPassword + ";Option=3;"); dbConnection.Open(); IO.PrintLine("Connection to database successfull.", IO.logImportancies.Info); return true; } catch (Exception ex) { IO.PrintLine(ex.Message, IO.logImportancies.Error); return false; } } /// /// Closes connection with the MySQL database. Any errors are ignored. /// public static void closeConnection() { IO.PrintLine("Closing database connection...", IO.logImportancies.Info); try { dbConnection.Close(); IO.PrintLine("Database connection closed.", IO.logImportancies.Info); } catch { IO.PrintLine("No database connection.", IO.logImportancies.Info); } } #endregion #region Database data manipulation #region runQuery /// /// Executes a raw SQL statement on the database. /// /// The SQL statement to be executed. Default SQL syntax. public static void runQuery(string Query) { try { new OdbcCommand(Query, dbConnection).ExecuteScalar(); } catch (Exception ex) { IO.PrintLine("Error '" + ex.Message + "' at '" + Query + "'", IO.logImportancies.Error); } } /// /// Executes a SQL statement with given parameters at the database. /// /// The parameters, eg, name, password etc. /// The values, eg, 'Woody', 'pass'. /// The query with the parameters included, eg, UPDATE users SET password = @password WHERE username = @name LIMIT 1. public static void runQuery(string[] paramIDs, object[] paramValues, string Query) { try { OdbcCommand cmd = new OdbcCommand(Query, dbConnection); for (int i = 0; i < paramIDs.Length; i++) cmd.Parameters.AddWithValue("@" + paramIDs[i], paramValues[i]); cmd.ExecuteNonQuery(); } catch (Exception ex) { IO.PrintLine(ex.Message + ", query: " + Query,IO.logImportancies.Error); } } #endregion #endregion #region Database data retrieval #region runRead /// /// Performs a raw SQL query and returns the first selected field as string. Other fields are ignored. /// /// The SQL query that selects a field. public static string runRead(string Query) { try { return new OdbcCommand(Query + " LIMIT 1", dbConnection).ExecuteScalar().ToString(); } catch (Exception ex) { IO.PrintLine(ex.Message, IO.logImportancies.Error); return ""; } } /// /// Performs a SQL query with given parameters at the database and returns the first selected field as string. Other fields are ignored. /// /// The parameters, eg, name, @assword etc. /// The values, eg, 'Woody', 'pass'. /// The query with the parameters included, eg, SELECT figure FROM users WHERE username = @name AND password = @password. public static string runReadString(string[] paramIDs, object[] paramValues, string Query) { try { OdbcCommand cmd = new OdbcCommand(Query + " LIMIT 1", dbConnection); for (int i = 0; i < paramIDs.Length; i++) cmd.Parameters.AddWithValue("@" + paramIDs[i], paramValues[i]); return cmd.ExecuteScalar().ToString(); } catch (Exception ex) { IO.PrintLine(ex.Message, IO.logImportancies.Error); return ""; } } /// /// Performs a raw SQL query and returns the first selected field as integer. Other fields are ignored. /// /// The SQL query that selects a field. public static int runReadInteger(string Query, object Tick) { try { return Convert.ToInt32(new OdbcCommand(Query + " LIMIT 1", dbConnection).ExecuteScalar()); } catch (Exception ex) { IO.PrintLine(ex.Message, IO.logImportancies.Error); return 0; } } /// /// Performs a SQL query with given parameters at the database and returns the first selected field as an integer. Other fields are ignored. /// /// The parameters, eg, name, password etc. /// The values, eg, 'Woody', 'pass'. /// The query with the parameters included, eg, SELECT credits FROM users WHERE username = @name AND password = @password. public static int runReadInteger(string[] paramIDs, object[] paramValues, string Query) { try { OdbcCommand cmd = new OdbcCommand(Query + " LIMIT 1", dbConnection); for (int i = 0; i < paramIDs.Length; i++) cmd.Parameters.AddWithValue("@" + paramIDs[i], paramValues[i]); return Convert.ToInt32(cmd.ExecuteScalar()); } catch (Exception ex) { IO.PrintLine(ex.Message, IO.logImportancies.Error); return 0; } } #endregion #region runReadColumn /// /// Performs a SQL query and returns all vertical matching fields as a String array. Only the first supplied columname is looked for. /// /// The SQL query that selects a column. /// Adds as LIMIT to the query. Using this, the array will never return more than xx fields in of the column. When maxResults is supplied as 0, then there is no max limit. public static string[] runReadColumnStrings(string Query, int maxResults) { if (maxResults > 0) Query += " LIMIT " + maxResults; try { ArrayList columnBuilder = new ArrayList(); OdbcDataReader columnReader = new OdbcCommand(Query, dbConnection).ExecuteReader(); while (columnReader.Read()) { try { columnBuilder.Add(columnReader[0].ToString()); } catch { columnBuilder.Add(""); } } columnReader.Close(); return (string[])columnBuilder.ToArray(typeof(string)); } catch (Exception ex) { IO.PrintLine("Error '" + ex.Message + "' at '" + Query + "'", IO.logImportancies.Error); return new string[0]; } } /// /// Performs a SQL query and returns all vertical matching fields as a String array. Only the first supplied columname is looked for. /// /// The parameters, eg, name, motto etc. /// The values, eg, 'Woody', 'wut?!'. /// The query with the parameters included, eg, SELECT figure FROM users WHERE username = @name OR motto = @motto. /// Adds as LIMIT to the query. Using this, the array will never return more than xx fields in of the column. When maxResults is supplied as 0, then there is no max limit. public static string[] runReadColumnStrings(string[] paramIDs, object[] paramValues,string Query, int maxResults) { if (maxResults > 0) Query += " LIMIT " + maxResults; try { ArrayList columnBuilder = new ArrayList(); OdbcCommand cmd = new OdbcCommand(Query, dbConnection); for (int i = 0; i < paramIDs.Length; i++) cmd.Parameters.AddWithValue("@" + paramIDs[i], paramValues[i]); OdbcDataReader columnReader = cmd.ExecuteReader(); while (columnReader.Read()) { try { columnBuilder.Add(columnReader[0].ToString()); } catch { columnBuilder.Add(""); } } columnReader.Close(); return (string[])columnBuilder.ToArray(typeof(string)); } catch (Exception ex) { IO.PrintLine(ex.Message, IO.logImportancies.Error); return new string[0]; } } /// /// Performs a SQL query and returns all vertical matching fields as an integer array. Only the first supplied columname is looked for. /// /// The SQL query that selects a column. /// Adds as LIMIT to the query. Using this, the array will never return more than xx fields in of the column. When maxResults is supplied as 0, then there is no max limit. public static int[] runReadColumnIntegers(string Query, int maxResults) { if (maxResults > 0) Query += " LIMIT " + maxResults; try { ArrayList columnBuilder = new ArrayList(); OdbcDataReader columnReader = new OdbcCommand(Query, dbConnection).ExecuteReader(); while (columnReader.Read()) { try { columnBuilder.Add((int)columnReader[0]); } catch { columnBuilder.Add(0); } } columnReader.Close(); return (int[])columnBuilder.ToArray(typeof(int)); } catch (Exception ex) { IO.PrintLine(ex.Message, IO.logImportancies.Error); return new int[0]; } } /// /// Performs a SQL query and returns all vertical matching fields as an integer array array. Only the first supplied columname is looked for. /// /// The parameters, eg, name, motto etc. /// The values, eg, 'Woody', 'wut?!'. /// The query with the parameters included, eg, SELECT credits FROM users WHERE username = @name OR motto = @motto. /// Adds as LIMIT to the query. Using this, the array will never return more than xx fields in of the column. When maxResults is supplied as 0, then there is no max limit. public static int[] runReadColumnIntegers(string[] paramIDs, object[] paramValues, string Query, int maxResults) { if (maxResults > 0) Query += " LIMIT " + maxResults; try { ArrayList columnBuilder = new ArrayList(); OdbcCommand cmd = new OdbcCommand(Query, dbConnection); for (int i = 0; i < paramIDs.Length; i++) cmd.Parameters.AddWithValue("@" + paramIDs[i], paramValues[i]); OdbcDataReader columnReader = cmd.ExecuteReader(); while (columnReader.Read()) { try { columnBuilder.Add((int)columnReader[0]); } catch { columnBuilder.Add(""); } } columnReader.Close(); return (int[])columnBuilder.ToArray(typeof(int)); } catch (Exception ex) { IO.PrintLine(ex.Message, IO.logImportancies.Error); return new int[0]; } } #endregion #region runReadRow /// /// Performs a SQL query and returns the selected in the first found row as a String array. Useable for only one row. /// /// The SQL query that selects a row and the fields to get. LIMIT 1 is added. public static string[] runReadRow(string Query) { try { ArrayList rowBuilder = new ArrayList(); OdbcDataReader rowReader = new OdbcCommand(Query + " LIMIT 1", dbConnection).ExecuteReader(); while (rowReader.Read()) { for (int i = 0; i < rowReader.FieldCount; i++) { try { rowBuilder.Add(rowReader[i].ToString()); } catch { rowBuilder.Add(""); } } } rowReader.Close(); return (string[])rowBuilder.ToArray(typeof(string)); } catch (Exception ex) { IO.PrintLine("Error '" + ex.Message + "' at '" + Query + "'", IO.logImportancies.Error); return new string[0]; } } /// /// Performs a SQL query and returns the selected in the first found row as an Integer array. Useable for only one row. /// /// The SQL query that selects a row and the fields to get. LIMIT 1 is added. /// Just to differ the runReadRow functions; supply a null if you want to use this overload. public static int[] runReadRow(string Query, object Tick) { try { ArrayList rowBuilder = new ArrayList(); OdbcDataReader rowReader = new OdbcCommand(Query + " LIMIT 1", dbConnection).ExecuteReader(); while (rowReader.Read()) { for (int i = 0; i < rowReader.FieldCount; i++) { try { rowBuilder.Add(rowReader.GetInt32(i)); } catch { rowBuilder.Add(0); } } } rowReader.Close(); return (int[])rowBuilder.ToArray(typeof(int)); } catch (Exception ex) { IO.PrintLine("Error '" + ex.Message + "' at '" + Query + "'", IO.logImportancies.Error); return new int[0]; } } /// /// Performs a SQL query and returns the result as a string. On error, no error is reported and "" is returned. /// /// The SQL query to run. LIMIT 1 is added. public static string runReadUnsafe(string Query) { try { return new OdbcCommand(Query + " LIMIT 1", dbConnection).ExecuteScalar().ToString(); } catch { return ""; } } /// /// Performs a SQL query and returns the result as an integer. On error, no error is reported and 0 is returned. /// /// The SQL query to run. LIMIT 1 is added. /// Just to differ the runReadUnsafe functions; supply a null if you want to use this overload. public static int runReadUnsafe(string Query, object Tick) { try { return Convert.ToInt32(new OdbcCommand(Query + " LIMIT 1", dbConnection).ExecuteScalar()); } catch { return 0; } } #endregion #endregion #region Data availability checks public static bool checkExists(string Table, string Field, string fieldValue) { try { return new OdbcCommand("SELECT " + Field + " FROM " + Table + " WHERE " + Field + "=" + fieldValue + " LIMIT 1", dbConnection).ExecuteReader().HasRows; } catch { return false; } } /// /// Tries to find fields matching the query. When there is at least one result, it returns True and stops. /// /// The SQL query that contains the seeked fields and conditions. LIMIT 1 is added. public static bool checkExists(string Query) { try { return new OdbcCommand(Query + " LIMIT 1", dbConnection).ExecuteReader().HasRows; } catch (Exception ex) { IO.PrintLine("Error '" + ex.Message + "' at '" + Query + "'", IO.logImportancies.Error); return false; } } #endregion #region Misc /// /// Returns a stripslashed copy of the input string. /// /// The string to add stripslashes to. public static string Stripslash(string Query) { try { return Query.Replace(@"\", "\\").Replace("'", @"\'"); } catch { return ""; } } #endregion } }