From 2fa5694ec9857f208b6fe4d0890fd2ab8ac1b8bf Mon Sep 17 00:00:00 2001 From: StrawberryFride Date: Wed, 24 Feb 2010 16:42:39 +0000 Subject: MSSQL Additions for Presence Refactor branch. Most functionality tested and works, some outstanding issues around login location and border crossings on y axis. Signed-off-by: Melanie --- OpenSim/Data/MSSQL/AutoClosingSqlCommand.cs | 219 ---- OpenSim/Data/MSSQL/MSSQLAssetData.cs | 54 +- OpenSim/Data/MSSQL/MSSQLAuthenticationData.cs | 16 +- OpenSim/Data/MSSQL/MSSQLAvatarData.cs | 71 ++ OpenSim/Data/MSSQL/MSSQLEstateData.cs | 99 +- OpenSim/Data/MSSQL/MSSQLFriendsData.cs | 83 ++ OpenSim/Data/MSSQL/MSSQLGenericTableHandler.cs | 359 ++++++ OpenSim/Data/MSSQL/MSSQLGridData.cs | 582 ++++++++++ OpenSim/Data/MSSQL/MSSQLInventoryData.cs | 206 ++-- OpenSim/Data/MSSQL/MSSQLLegacyRegionData.cs | 162 +-- OpenSim/Data/MSSQL/MSSQLManager.cs | 225 +--- OpenSim/Data/MSSQL/MSSQLPresenceData.cs | 170 +++ OpenSim/Data/MSSQL/MSSQLRegionData.cs | 34 +- OpenSim/Data/MSSQL/MSSQLUserAccountData.cs | 319 +++--- OpenSim/Data/MSSQL/MSSQLUserData.cs | 1238 +++++++++++++++++++++ OpenSim/Data/MSSQL/MSSQLXInventoryData.cs | 166 +++ OpenSim/Data/MSSQL/Resources/001_AuthStore.sql | 17 + OpenSim/Data/MSSQL/Resources/001_Avatar.sql | 15 + OpenSim/Data/MSSQL/Resources/001_FriendsStore.sql | 11 + OpenSim/Data/MSSQL/Resources/001_Presence.sql | 19 + OpenSim/Data/MSSQL/Resources/002_AuthStore.sql | 6 + OpenSim/Data/MSSQL/Resources/002_FriendsStore.sql | 6 + OpenSim/Data/MSSQL/Resources/002_Presence.sql | 6 + OpenSim/Data/MSSQL/Resources/002_UserAccount.sql | 12 + OpenSim/Data/MSSQL/Resources/007_GridStore.sql | 9 + 25 files changed, 3262 insertions(+), 842 deletions(-) delete mode 100644 OpenSim/Data/MSSQL/AutoClosingSqlCommand.cs create mode 100644 OpenSim/Data/MSSQL/MSSQLAvatarData.cs create mode 100644 OpenSim/Data/MSSQL/MSSQLFriendsData.cs create mode 100644 OpenSim/Data/MSSQL/MSSQLGenericTableHandler.cs create mode 100644 OpenSim/Data/MSSQL/MSSQLGridData.cs create mode 100644 OpenSim/Data/MSSQL/MSSQLPresenceData.cs create mode 100644 OpenSim/Data/MSSQL/MSSQLUserData.cs create mode 100644 OpenSim/Data/MSSQL/MSSQLXInventoryData.cs create mode 100644 OpenSim/Data/MSSQL/Resources/001_AuthStore.sql create mode 100644 OpenSim/Data/MSSQL/Resources/001_Avatar.sql create mode 100644 OpenSim/Data/MSSQL/Resources/001_FriendsStore.sql create mode 100644 OpenSim/Data/MSSQL/Resources/001_Presence.sql create mode 100644 OpenSim/Data/MSSQL/Resources/002_AuthStore.sql create mode 100644 OpenSim/Data/MSSQL/Resources/002_FriendsStore.sql create mode 100644 OpenSim/Data/MSSQL/Resources/002_Presence.sql create mode 100644 OpenSim/Data/MSSQL/Resources/002_UserAccount.sql create mode 100644 OpenSim/Data/MSSQL/Resources/007_GridStore.sql diff --git a/OpenSim/Data/MSSQL/AutoClosingSqlCommand.cs b/OpenSim/Data/MSSQL/AutoClosingSqlCommand.cs deleted file mode 100644 index 93e48cd..0000000 --- a/OpenSim/Data/MSSQL/AutoClosingSqlCommand.cs +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System.Data; -using System.Data.SqlClient; - -namespace OpenSim.Data.MSSQL -{ - /// - /// Encapsulates a SqlCommand object but ensures that when it is disposed, its connection is closed and disposed also. - /// - internal class AutoClosingSqlCommand : IDbCommand - { - private SqlCommand realCommand; - - public AutoClosingSqlCommand(SqlCommand cmd) - { - realCommand = cmd; - } - - #region IDbCommand Members - - public void Cancel() - { - realCommand.Cancel(); - } - - public string CommandText - { - get - { - return realCommand.CommandText; - } - set - { - realCommand.CommandText = value; - } - } - - public int CommandTimeout - { - get - { - return realCommand.CommandTimeout; - } - set - { - realCommand.CommandTimeout = value; - } - } - - public CommandType CommandType - { - get - { - return realCommand.CommandType; - } - set - { - realCommand.CommandType = value; - } - } - - IDbConnection IDbCommand.Connection - { - get - { - return realCommand.Connection; - } - set - { - realCommand.Connection = (SqlConnection) value; - } - } - - public SqlConnection Connection - { - get - { - return realCommand.Connection; - } - } - - IDbDataParameter IDbCommand.CreateParameter() - { - return realCommand.CreateParameter(); - } - - public SqlParameter CreateParameter() - { - return realCommand.CreateParameter(); - } - - public int ExecuteNonQuery() - { - return realCommand.ExecuteNonQuery(); - } - - IDataReader IDbCommand.ExecuteReader(CommandBehavior behavior) - { - return realCommand.ExecuteReader(behavior); - } - - public SqlDataReader ExecuteReader(CommandBehavior behavior) - { - return realCommand.ExecuteReader(behavior); - } - - IDataReader IDbCommand.ExecuteReader() - { - return realCommand.ExecuteReader(); - } - - public SqlDataReader ExecuteReader() - { - return realCommand.ExecuteReader(); - } - - public object ExecuteScalar() - { - return realCommand.ExecuteScalar(); - } - - IDataParameterCollection IDbCommand.Parameters - { - get { return realCommand.Parameters; } - } - - public SqlParameterCollection Parameters - { - get { return realCommand.Parameters; } - } - - public void Prepare() - { - realCommand.Prepare(); - } - -// IDbTransaction IDbCommand.Transaction -// { -// get -// { -// return realCommand.Transaction; -// } -// set -// { -// realCommand.Transaction = (SqlTransaction) value; -// } -// } - - public IDbTransaction Transaction - { - get { return realCommand.Transaction; } - set { realCommand.Transaction = (SqlTransaction)value; } - } - - UpdateRowSource IDbCommand.UpdatedRowSource - { - get - { - return realCommand.UpdatedRowSource; - } - set - { - realCommand.UpdatedRowSource = value; - } - } - - #endregion - - #region IDisposable Members - - public void Dispose() - { - SqlConnection conn = realCommand.Connection; - try - { - realCommand.Dispose(); - } - finally - { - try - { - conn.Close(); - } - finally - { - conn.Dispose(); - } - } - } - - #endregion - } -} diff --git a/OpenSim/Data/MSSQL/MSSQLAssetData.cs b/OpenSim/Data/MSSQL/MSSQLAssetData.cs index 437c09c..b1faf0b 100644 --- a/OpenSim/Data/MSSQL/MSSQLAssetData.cs +++ b/OpenSim/Data/MSSQL/MSSQLAssetData.cs @@ -49,6 +49,7 @@ namespace OpenSim.Data.MSSQL /// Database manager /// private MSSQLManager m_database; + private string m_connectionString; #region IPlugin Members @@ -75,23 +76,8 @@ namespace OpenSim.Data.MSSQL { m_ticksToEpoch = new System.DateTime(1970, 1, 1).Ticks; - if (!string.IsNullOrEmpty(connectionString)) - { - m_database = new MSSQLManager(connectionString); - } - else - { - IniFile gridDataMSSqlFile = new IniFile("mssql_connection.ini"); - string settingDataSource = gridDataMSSqlFile.ParseFileReadValue("data_source"); - string settingInitialCatalog = gridDataMSSqlFile.ParseFileReadValue("initial_catalog"); - string settingPersistSecurityInfo = gridDataMSSqlFile.ParseFileReadValue("persist_security_info"); - string settingUserId = gridDataMSSqlFile.ParseFileReadValue("user_id"); - string settingPassword = gridDataMSSqlFile.ParseFileReadValue("password"); - - m_database = - new MSSQLManager(settingDataSource, settingInitialCatalog, settingPersistSecurityInfo, settingUserId, - settingPassword); - } + m_database = new MSSQLManager(connectionString); + m_connectionString = connectionString; //New migration to check for DB changes m_database.CheckMigration(_migrationStore); @@ -125,18 +111,19 @@ namespace OpenSim.Data.MSSQL override public AssetBase GetAsset(UUID assetID) { string sql = "SELECT * FROM assets WHERE id = @id"; - using (AutoClosingSqlCommand command = m_database.Query(sql)) + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) { - command.Parameters.Add(m_database.CreateParameter("id", assetID)); - using (SqlDataReader reader = command.ExecuteReader()) + cmd.Parameters.Add(m_database.CreateParameter("id", assetID)); + conn.Open(); + using (SqlDataReader reader = cmd.ExecuteReader()) { if (reader.Read()) { AssetBase asset = new AssetBase( new UUID((Guid)reader["id"]), (string)reader["name"], - Convert.ToSByte(reader["assetType"]), - UUID.Zero.ToString() + Convert.ToSByte(reader["assetType"]) ); // Region Main asset.Description = (string)reader["description"]; @@ -191,7 +178,8 @@ namespace OpenSim.Data.MSSQL m_log.Warn("[ASSET DB]: Description field truncated from " + asset.Description.Length + " to " + assetDescription.Length + " characters on add"); } - using (AutoClosingSqlCommand command = m_database.Query(sql)) + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand command = new SqlCommand(sql, conn)) { int now = (int)((System.DateTime.Now.Ticks - m_ticksToEpoch) / 10000000); command.Parameters.Add(m_database.CreateParameter("id", asset.FullID)); @@ -203,7 +191,7 @@ namespace OpenSim.Data.MSSQL command.Parameters.Add(m_database.CreateParameter("access_time", now)); command.Parameters.Add(m_database.CreateParameter("create_time", now)); command.Parameters.Add(m_database.CreateParameter("data", asset.Data)); - + conn.Open(); try { command.ExecuteNonQuery(); @@ -239,7 +227,8 @@ namespace OpenSim.Data.MSSQL m_log.Warn("[ASSET DB]: Description field truncated from " + asset.Description.Length + " to " + assetDescription.Length + " characters on update"); } - using (AutoClosingSqlCommand command = m_database.Query(sql)) + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand command = new SqlCommand(sql, conn)) { command.Parameters.Add(m_database.CreateParameter("id", asset.FullID)); command.Parameters.Add(m_database.CreateParameter("name", assetName)); @@ -249,7 +238,7 @@ namespace OpenSim.Data.MSSQL command.Parameters.Add(m_database.CreateParameter("temporary", asset.Temporary)); command.Parameters.Add(m_database.CreateParameter("data", asset.Data)); command.Parameters.Add(m_database.CreateParameter("@keyId", asset.FullID)); - + conn.Open(); try { command.ExecuteNonQuery(); @@ -308,13 +297,14 @@ namespace OpenSim.Data.MSSQL string sql = @"SELECT (name,description,assetType,temporary,id), Row = ROW_NUMBER() OVER (ORDER BY (some column to order by)) WHERE Row >= @Start AND Row < @Start + @Count"; - - using (AutoClosingSqlCommand command = m_database.Query(sql)) - { - command.Parameters.Add(m_database.CreateParameter("start", start)); - command.Parameters.Add(m_database.CreateParameter("count", count)); - using (SqlDataReader reader = command.ExecuteReader()) + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.Add(m_database.CreateParameter("start", start)); + cmd.Parameters.Add(m_database.CreateParameter("count", count)); + conn.Open(); + using (SqlDataReader reader = cmd.ExecuteReader()) { while (reader.Read()) { diff --git a/OpenSim/Data/MSSQL/MSSQLAuthenticationData.cs b/OpenSim/Data/MSSQL/MSSQLAuthenticationData.cs index 801610a..1ae78c4 100644 --- a/OpenSim/Data/MSSQL/MSSQLAuthenticationData.cs +++ b/OpenSim/Data/MSSQL/MSSQLAuthenticationData.cs @@ -53,6 +53,7 @@ namespace OpenSim.Data.MSSQL { conn.Open(); Migration m = new Migration(conn, GetType().Assembly, "AuthStore"); + m_database = new MSSQLManager(m_ConnectionString); m.Update(); } } @@ -168,13 +169,14 @@ namespace OpenSim.Data.MSSQL { if (System.Environment.TickCount - m_LastExpire > 30000) DoExpire(); - string sql = "insert into tokens (UUID, token, validity) values (@principalID, @token, date_add(now(), interval @lifetime minute))"; + + string sql = "insert into tokens (UUID, token, validity) values (@principalID, @token, @lifetime)"; using (SqlConnection conn = new SqlConnection(m_ConnectionString)) using (SqlCommand cmd = new SqlCommand(sql, conn)) { cmd.Parameters.Add(m_database.CreateParameter("@principalID", principalID)); cmd.Parameters.Add(m_database.CreateParameter("@token", token)); - cmd.Parameters.Add(m_database.CreateParameter("@lifetime", lifetime)); + cmd.Parameters.Add(m_database.CreateParameter("@lifetime", DateTime.Now.AddMinutes(lifetime))); conn.Open(); if (cmd.ExecuteNonQuery() > 0) @@ -189,13 +191,15 @@ namespace OpenSim.Data.MSSQL { if (System.Environment.TickCount - m_LastExpire > 30000) DoExpire(); - string sql = "update tokens set validity = date_add(now(), interval @lifetime minute) where UUID = @principalID and token = @token and validity > now()"; + + DateTime validDate = DateTime.Now.AddMinutes(lifetime); + string sql = "update tokens set validity = @validDate where UUID = @principalID and token = @token and validity > GetDate()"; using (SqlConnection conn = new SqlConnection(m_ConnectionString)) using (SqlCommand cmd = new SqlCommand(sql, conn)) { cmd.Parameters.Add(m_database.CreateParameter("@principalID", principalID)); cmd.Parameters.Add(m_database.CreateParameter("@token", token)); - cmd.Parameters.Add(m_database.CreateParameter("@lifetime", lifetime)); + cmd.Parameters.Add(m_database.CreateParameter("@validDate", validDate)); conn.Open(); if (cmd.ExecuteNonQuery() > 0) @@ -208,11 +212,13 @@ namespace OpenSim.Data.MSSQL private void DoExpire() { - string sql = "delete from tokens where validity < now()"; + DateTime currentDateTime = DateTime.Now; + string sql = "delete from tokens where validity < @currentDateTime"; using (SqlConnection conn = new SqlConnection(m_ConnectionString)) using (SqlCommand cmd = new SqlCommand(sql, conn)) { conn.Open(); + cmd.Parameters.Add(m_database.CreateParameter("@currentDateTime", currentDateTime)); cmd.ExecuteNonQuery(); } m_LastExpire = System.Environment.TickCount; diff --git a/OpenSim/Data/MSSQL/MSSQLAvatarData.cs b/OpenSim/Data/MSSQL/MSSQLAvatarData.cs new file mode 100644 index 0000000..4992183 --- /dev/null +++ b/OpenSim/Data/MSSQL/MSSQLAvatarData.cs @@ -0,0 +1,71 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Data; +using System.Reflection; +using System.Threading; +using log4net; +using OpenMetaverse; +using OpenSim.Framework; +using System.Data.SqlClient; + +namespace OpenSim.Data.MSSQL +{ + /// + /// A MSSQL Interface for Avatar Storage + /// + public class MSSQLAvatarData : MSSQLGenericTableHandler, + IAvatarData + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + public MSSQLAvatarData(string connectionString, string realm) : + base(connectionString, realm, "Avatar") + { + } + + public bool Delete(UUID principalID, string name) + { + using (SqlConnection conn = new SqlConnection(m_ConnectionString)) + using (SqlCommand cmd = new SqlCommand()) + { + + cmd.CommandText = String.Format("DELETE FROM {0} where [PrincipalID] = @PrincipalID and [Name] = @Name", m_Realm); + cmd.Parameters.Add(m_database.CreateParameter("@PrincipalID", principalID.ToString())); + cmd.Parameters.Add(m_database.CreateParameter("@Name", name)); + cmd.Connection = conn; + conn.Open(); + if (cmd.ExecuteNonQuery() > 0) + return true; + + return false; + } + } + } +} diff --git a/OpenSim/Data/MSSQL/MSSQLEstateData.cs b/OpenSim/Data/MSSQL/MSSQLEstateData.cs index c0c6349..6f6f076 100644 --- a/OpenSim/Data/MSSQL/MSSQLEstateData.cs +++ b/OpenSim/Data/MSSQL/MSSQLEstateData.cs @@ -44,7 +44,7 @@ namespace OpenSim.Data.MSSQL private static readonly ILog _Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private MSSQLManager _Database; - + private string m_connectionString; private FieldInfo[] _Fields; private Dictionary _FieldMap = new Dictionary(); @@ -58,22 +58,9 @@ namespace OpenSim.Data.MSSQL { if (!string.IsNullOrEmpty(connectionString)) { + m_connectionString = connectionString; _Database = new MSSQLManager(connectionString); } - else - { - //TODO when can this be deleted - IniFile iniFile = new IniFile("mssql_connection.ini"); - string settingDataSource = iniFile.ParseFileReadValue("data_source"); - string settingInitialCatalog = iniFile.ParseFileReadValue("initial_catalog"); - string settingPersistSecurityInfo = iniFile.ParseFileReadValue("persist_security_info"); - string settingUserId = iniFile.ParseFileReadValue("user_id"); - string settingPassword = iniFile.ParseFileReadValue("password"); - - _Database = - new MSSQLManager(settingDataSource, settingInitialCatalog, settingPersistSecurityInfo, settingUserId, - settingPassword); - } //Migration settings _Database.CheckMigration(_migrationStore); @@ -103,11 +90,11 @@ namespace OpenSim.Data.MSSQL string sql = "select estate_settings." + String.Join(",estate_settings.", FieldList) + " from estate_map left join estate_settings on estate_map.EstateID = estate_settings.EstateID where estate_settings.EstateID is not null and RegionID = @RegionID"; bool insertEstate = false; - - using (AutoClosingSqlCommand cmd = _Database.Query(sql)) + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) { cmd.Parameters.Add(_Database.CreateParameter("@RegionID", regionID)); - + conn.Open(); using (SqlDataReader reader = cmd.ExecuteReader()) { if (reader.Read()) @@ -124,7 +111,7 @@ namespace OpenSim.Data.MSSQL } else if (_FieldMap[name].GetValue(es) is UUID) { - _FieldMap[name].SetValue(es, new UUID((Guid) reader[name])); // uuid); + _FieldMap[name].SetValue(es, new UUID((Guid)reader[name])); // uuid); } else { @@ -149,34 +136,36 @@ namespace OpenSim.Data.MSSQL sql = string.Format("insert into estate_settings ({0}) values ( @{1})", String.Join(",", names.ToArray()), String.Join(", @", names.ToArray())); //_Log.Debug("[DB ESTATE]: SQL: " + sql); - using (SqlConnection connection = _Database.DatabaseConnection()) + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand insertCommand = new SqlCommand(sql, conn)) { - using (SqlCommand insertCommand = connection.CreateCommand()) - { - insertCommand.CommandText = sql + " SET @ID = SCOPE_IDENTITY()"; - - foreach (string name in names) - { - insertCommand.Parameters.Add(_Database.CreateParameter("@" + name, _FieldMap[name].GetValue(es))); - } - SqlParameter idParameter = new SqlParameter("@ID", SqlDbType.Int); - idParameter.Direction = ParameterDirection.Output; - insertCommand.Parameters.Add(idParameter); - - insertCommand.ExecuteNonQuery(); + insertCommand.CommandText = sql + " SET @ID = SCOPE_IDENTITY()"; - es.EstateID = Convert.ToUInt32(idParameter.Value); + foreach (string name in names) + { + insertCommand.Parameters.Add(_Database.CreateParameter("@" + name, _FieldMap[name].GetValue(es))); } + SqlParameter idParameter = new SqlParameter("@ID", SqlDbType.Int); + idParameter.Direction = ParameterDirection.Output; + insertCommand.Parameters.Add(idParameter); + conn.Open(); + insertCommand.ExecuteNonQuery(); + + es.EstateID = Convert.ToUInt32(idParameter.Value); } - using (AutoClosingSqlCommand cmd = _Database.Query("INSERT INTO [estate_map] ([RegionID] ,[EstateID]) VALUES (@RegionID, @EstateID)")) + sql = "INSERT INTO [estate_map] ([RegionID] ,[EstateID]) VALUES (@RegionID, @EstateID)"; + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) { + cmd.Parameters.Add(_Database.CreateParameter("@RegionID", regionID)); cmd.Parameters.Add(_Database.CreateParameter("@EstateID", es.EstateID)); // This will throw on dupe key try { - cmd.ExecuteNonQuery(); + conn.Open(); + cmd.ExecuteNonQuery(); } catch (Exception e) { @@ -187,12 +176,14 @@ namespace OpenSim.Data.MSSQL // Munge and transfer the ban list sql = string.Format("insert into estateban select {0}, bannedUUID, bannedIp, bannedIpHostMask, '' from regionban where regionban.regionUUID = @UUID", es.EstateID); - using (AutoClosingSqlCommand cmd = _Database.Query(sql)) + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) { + cmd.Parameters.Add(_Database.CreateParameter("@UUID", regionID)); try { - + conn.Open(); cmd.ExecuteNonQuery(); } catch (Exception) @@ -226,7 +217,7 @@ namespace OpenSim.Data.MSSQL names.Remove("EstateID"); - string sql = string.Format("UPDATE estate_settings SET ") ; + string sql = string.Format("UPDATE estate_settings SET "); foreach (string name in names) { sql += name + " = @" + name + ", "; @@ -234,7 +225,8 @@ namespace OpenSim.Data.MSSQL sql = sql.Remove(sql.LastIndexOf(",")); sql += " WHERE EstateID = @EstateID"; - using (AutoClosingSqlCommand cmd = _Database.Query(sql)) + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) { foreach (string name in names) { @@ -242,6 +234,7 @@ namespace OpenSim.Data.MSSQL } cmd.Parameters.Add(_Database.CreateParameter("@EstateID", es.EstateID)); + conn.Open(); cmd.ExecuteNonQuery(); } @@ -266,12 +259,13 @@ namespace OpenSim.Data.MSSQL string sql = "select bannedUUID from estateban where EstateID = @EstateID"; - using (AutoClosingSqlCommand cmd = _Database.Query(sql)) + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) { SqlParameter idParameter = new SqlParameter("@EstateID", SqlDbType.Int); idParameter.Value = es.EstateID; cmd.Parameters.Add(idParameter); - + conn.Open(); using (SqlDataReader reader = cmd.ExecuteReader()) { while (reader.Read()) @@ -293,10 +287,11 @@ namespace OpenSim.Data.MSSQL string sql = string.Format("select uuid from {0} where EstateID = @EstateID", table); - using (AutoClosingSqlCommand cmd = _Database.Query(sql)) + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) { cmd.Parameters.Add(_Database.CreateParameter("@EstateID", estateID)); - + conn.Open(); using (SqlDataReader reader = cmd.ExecuteReader()) { while (reader.Read()) @@ -313,20 +308,24 @@ namespace OpenSim.Data.MSSQL { //Delete first string sql = "delete from estateban where EstateID = @EstateID"; - using (AutoClosingSqlCommand cmd = _Database.Query(sql)) + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) { cmd.Parameters.Add(_Database.CreateParameter("@EstateID", es.EstateID)); + conn.Open(); cmd.ExecuteNonQuery(); } //Insert after sql = "insert into estateban (EstateID, bannedUUID) values ( @EstateID, @bannedUUID )"; - using (AutoClosingSqlCommand cmd = _Database.Query(sql)) + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) { foreach (EstateBan b in es.EstateBans) { cmd.Parameters.Add(_Database.CreateParameter("@EstateID", es.EstateID)); cmd.Parameters.Add(_Database.CreateParameter("@bannedUUID", b.BannedUserID)); + conn.Open(); cmd.ExecuteNonQuery(); cmd.Parameters.Clear(); } @@ -337,14 +336,16 @@ namespace OpenSim.Data.MSSQL { //Delete first string sql = string.Format("delete from {0} where EstateID = @EstateID", table); - using (AutoClosingSqlCommand cmd = _Database.Query(sql)) + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) { cmd.Parameters.Add(_Database.CreateParameter("@EstateID", estateID)); cmd.ExecuteNonQuery(); } sql = string.Format("insert into {0} (EstateID, uuid) values ( @EstateID, @uuid )", table); - using (AutoClosingSqlCommand cmd = _Database.Query(sql)) + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) { cmd.Parameters.Add(_Database.CreateParameter("@EstateID", estateID)); @@ -359,7 +360,7 @@ namespace OpenSim.Data.MSSQL } else cmd.Parameters["@uuid"].Value = uuid.Guid; //.ToString(); //TODO check if this works - + conn.Open(); cmd.ExecuteNonQuery(); } } diff --git a/OpenSim/Data/MSSQL/MSSQLFriendsData.cs b/OpenSim/Data/MSSQL/MSSQLFriendsData.cs new file mode 100644 index 0000000..34da943 --- /dev/null +++ b/OpenSim/Data/MSSQL/MSSQLFriendsData.cs @@ -0,0 +1,83 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ''AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using OpenMetaverse; +using OpenSim.Framework; +using System.Data.SqlClient; +using System.Reflection; +using System.Text; + +namespace OpenSim.Data.MSSQL +{ + public class MSSQLFriendsData : MSSQLGenericTableHandler, IFriendsData + { + public MSSQLFriendsData(string connectionString, string realm) + : base(connectionString, realm, "FriendsStore") + { + using (SqlConnection conn = new SqlConnection(m_ConnectionString)) + { + conn.Open(); + Migration m = new Migration(conn, GetType().Assembly, "FriendsStore"); + m.Update(); + } + } + + public bool Delete(UUID principalID, string friend) + { + using (SqlConnection conn = new SqlConnection(m_ConnectionString)) + using (SqlCommand cmd = new SqlCommand()) + { + cmd.CommandText = String.Format("delete from {0} where PrincipalID = @PrincipalID and Friend = @Friend", m_Realm); + cmd.Parameters.Add(m_database.CreateParameter("@PrincipalID", principalID.ToString())); + cmd.Parameters.Add(m_database.CreateParameter("@Friend", friend)); + cmd.Connection = conn; + conn.Open(); + cmd.ExecuteNonQuery(); + + return true; + } + } + + public FriendsData[] GetFriends(UUID principalID) + { + using (SqlConnection conn = new SqlConnection(m_ConnectionString)) + using (SqlCommand cmd = new SqlCommand()) + { + + cmd.CommandText = String.Format("select a.*,b.Flags as TheirFlags from {0} as a left join {0} as b on a.PrincipalID = b.Friend and a.Friend = b.PrincipalID where a.PrincipalID = ?PrincipalID and b.Flags is not null", m_Realm); + cmd.Parameters.Add(m_database.CreateParameter("@PrincipalID", principalID.ToString())); + cmd.Connection = conn; + conn.Open(); + return DoQuery(cmd); + } + } + } +} diff --git a/OpenSim/Data/MSSQL/MSSQLGenericTableHandler.cs b/OpenSim/Data/MSSQL/MSSQLGenericTableHandler.cs new file mode 100644 index 0000000..506056d --- /dev/null +++ b/OpenSim/Data/MSSQL/MSSQLGenericTableHandler.cs @@ -0,0 +1,359 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Data; +using System.Reflection; +using log4net; +using System.Data.SqlClient; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using System.Text; + +namespace OpenSim.Data.MSSQL +{ + public class MSSQLGenericTableHandler where T : class, new() + { + private static readonly ILog m_log = + LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + protected string m_ConnectionString; + protected MSSQLManager m_database; //used for parameter type translation + protected Dictionary m_Fields = + new Dictionary(); + + protected List m_ColumnNames = null; + protected string m_Realm; + protected FieldInfo m_DataField = null; + + public MSSQLGenericTableHandler(string connectionString, + string realm, string storeName) + { + m_Realm = realm; + + if (storeName != String.Empty) + { + Assembly assem = GetType().Assembly; + m_ConnectionString = connectionString; + using (SqlConnection conn = new SqlConnection(m_ConnectionString)) + { + conn.Open(); + Migration m = new Migration(conn, assem, storeName); + m.Update(); + } + + } + m_database = new MSSQLManager(m_ConnectionString); + + Type t = typeof(T); + FieldInfo[] fields = t.GetFields(BindingFlags.Public | + BindingFlags.Instance | + BindingFlags.DeclaredOnly); + + if (fields.Length == 0) + return; + + foreach (FieldInfo f in fields) + { + if (f.Name != "Data") + m_Fields[f.Name] = f; + else + m_DataField = f; + } + + } + + private void CheckColumnNames(SqlDataReader reader) + { + if (m_ColumnNames != null) + return; + + m_ColumnNames = new List(); + + DataTable schemaTable = reader.GetSchemaTable(); + foreach (DataRow row in schemaTable.Rows) + { + if (row["ColumnName"] != null && + (!m_Fields.ContainsKey(row["ColumnName"].ToString()))) + m_ColumnNames.Add(row["ColumnName"].ToString()); + + } + } + + private List GetConstraints() + { + List constraints = new List(); + string query = string.Format(@"SELECT + COL_NAME(ic.object_id,ic.column_id) AS column_name + FROM sys.indexes AS i + INNER JOIN sys.index_columns AS ic + ON i.object_id = ic.object_id AND i.index_id = ic.index_id + WHERE i.is_primary_key = 1 + AND i.object_id = OBJECT_ID('{0}');", m_Realm); + using (SqlConnection conn = new SqlConnection(m_ConnectionString)) + using (SqlCommand cmd = new SqlCommand(query, conn)) + { + conn.Open(); + using (SqlDataReader rdr = cmd.ExecuteReader()) + { + while (rdr.Read()) + { + // query produces 0 to many rows of single column, so always add the first item in each row + constraints.Add((string)rdr[0]); + } + } + return constraints; + } + } + + public virtual T[] Get(string field, string key) + { + return Get(new string[] { field }, new string[] { key }); + } + + public virtual T[] Get(string[] fields, string[] keys) + { + if (fields.Length != keys.Length) + return new T[0]; + + List terms = new List(); + + using (SqlConnection conn = new SqlConnection(m_ConnectionString)) + using (SqlCommand cmd = new SqlCommand()) + { + + for (int i = 0; i < fields.Length; i++) + { + cmd.Parameters.Add(m_database.CreateParameter(fields[i], keys[i])); + terms.Add("[" + fields[i] + "] = @" + fields[i]); + } + + string where = String.Join(" AND ", terms.ToArray()); + + string query = String.Format("SELECT * FROM {0} WHERE {1}", + m_Realm, where); + + cmd.Connection = conn; + cmd.CommandText = query; + conn.Open(); + return DoQuery(cmd); + } + } + + protected T[] DoQuery(SqlCommand cmd) + { + using (SqlDataReader reader = cmd.ExecuteReader()) + { + if (reader == null) + return new T[0]; + + CheckColumnNames(reader); + + List result = new List(); + + while (reader.Read()) + { + T row = new T(); + + foreach (string name in m_Fields.Keys) + { + if (m_Fields[name].GetValue(row) is bool) + { + int v = Convert.ToInt32(reader[name]); + m_Fields[name].SetValue(row, v != 0 ? true : false); + } + else if (m_Fields[name].GetValue(row) is UUID) + { + UUID uuid = UUID.Zero; + + UUID.TryParse(reader[name].ToString(), out uuid); + m_Fields[name].SetValue(row, uuid); + } + else if (m_Fields[name].GetValue(row) is int) + { + int v = Convert.ToInt32(reader[name]); + m_Fields[name].SetValue(row, v); + } + else + { + m_Fields[name].SetValue(row, reader[name]); + } + } + + if (m_DataField != null) + { + Dictionary data = + new Dictionary(); + + foreach (string col in m_ColumnNames) + { + data[col] = reader[col].ToString(); + if (data[col] == null) + data[col] = String.Empty; + } + + m_DataField.SetValue(row, data); + } + + result.Add(row); + } + return result.ToArray(); + } + } + + public virtual T[] Get(string where) + { + using (SqlConnection conn = new SqlConnection(m_ConnectionString)) + using (SqlCommand cmd = new SqlCommand()) + { + + string query = String.Format("SELECT * FROM {0} WHERE {1}", + m_Realm, where); + cmd.Connection = conn; + cmd.CommandText = query; + + //m_log.WarnFormat("[MSSQLGenericTable]: SELECT {0} WHERE {1}", m_Realm, where); + + conn.Open(); + return DoQuery(cmd); + } + } + + public virtual bool Store(T row) + { + List constraintFields = GetConstraints(); + List> constraints = new List>(); + + using (SqlConnection conn = new SqlConnection(m_ConnectionString)) + using (SqlCommand cmd = new SqlCommand()) + { + + StringBuilder query = new StringBuilder(); + List names = new List(); + List values = new List(); + + foreach (FieldInfo fi in m_Fields.Values) + { + names.Add(fi.Name); + values.Add("@" + fi.Name); + if (constraintFields.Count > 0 && constraintFields.Contains(fi.Name)) + { + constraints.Add(new KeyValuePair(fi.Name, fi.GetValue(row).ToString())); + } + cmd.Parameters.Add(m_database.CreateParameter(fi.Name, fi.GetValue(row).ToString())); + } + + if (m_DataField != null) + { + Dictionary data = + (Dictionary)m_DataField.GetValue(row); + + foreach (KeyValuePair kvp in data) + { + if (constraintFields.Count > 0 && constraintFields.Contains(kvp.Key)) + { + constraints.Add(new KeyValuePair(kvp.Key, kvp.Key)); + } + names.Add(kvp.Key); + values.Add("@" + kvp.Key); + cmd.Parameters.Add(m_database.CreateParameter("@" + kvp.Key, kvp.Value)); + } + + } + + query.AppendFormat("UPDATE {0} SET ", m_Realm); + int i = 0; + for (i = 0; i < names.Count - 1; i++) + { + query.AppendFormat("[{0}] = {1}, ", names[i], values[i]); + } + query.AppendFormat("[{0}] = {1} ", names[i], values[i]); + if (constraints.Count > 0) + { + List terms = new List(); + for (int j = 0; j < constraints.Count; j++) + { + terms.Add(" [" + constraints[j].Key + "] = @" + constraints[j].Key); + } + string where = String.Join(" AND ", terms.ToArray()); + query.AppendFormat(" WHERE {0} ", where); + + } + cmd.Connection = conn; + cmd.CommandText = query.ToString(); + + conn.Open(); + if (cmd.ExecuteNonQuery() > 0) + { + //m_log.WarnFormat("[MSSQLGenericTable]: Updating {0}", m_Realm); + return true; + } + else + { + // assume record has not yet been inserted + + query = new StringBuilder(); + query.AppendFormat("INSERT INTO {0} ([", m_Realm); + query.Append(String.Join("],[", names.ToArray())); + query.Append("]) values (" + String.Join(",", values.ToArray()) + ")"); + cmd.Connection = conn; + cmd.CommandText = query.ToString(); + //m_log.WarnFormat("[MSSQLGenericTable]: Inserting into {0}", m_Realm); + if (conn.State != ConnectionState.Open) + conn.Open(); + if (cmd.ExecuteNonQuery() > 0) + return true; + } + + return false; + } + } + + public virtual bool Delete(string field, string val) + { + using (SqlConnection conn = new SqlConnection(m_ConnectionString)) + using (SqlCommand cmd = new SqlCommand()) + { + string deleteCommand = String.Format("DELETE FROM {0} WHERE [{1}] = @{1}", m_Realm, field); + cmd.CommandText = deleteCommand; + + cmd.Parameters.Add(m_database.CreateParameter(field, val)); + cmd.Connection = conn; + conn.Open(); + + if (cmd.ExecuteNonQuery() > 0) + { + //m_log.Warn("[MSSQLGenericTable]: " + deleteCommand); + return true; + } + return false; + } + } + } +} diff --git a/OpenSim/Data/MSSQL/MSSQLGridData.cs b/OpenSim/Data/MSSQL/MSSQLGridData.cs new file mode 100644 index 0000000..6adb5f3 --- /dev/null +++ b/OpenSim/Data/MSSQL/MSSQLGridData.cs @@ -0,0 +1,582 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.SqlClient; +using System.Reflection; +using log4net; +using OpenMetaverse; +using OpenSim.Framework; + +namespace OpenSim.Data.MSSQL +{ + /// + /// A grid data interface for MSSQL Server + /// + public class MSSQLGridData : GridDataBase + { + private const string _migrationStore = "GridStore"; + + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// Database manager + /// + private MSSQLManager database; + private string m_connectionString; + + private string m_regionsTableName = "regions"; + + #region IPlugin Members + + // [Obsolete("Cannot be default-initialized!")] + override public void Initialise() + { + m_log.Info("[GRID DB]: " + Name + " cannot be default-initialized!"); + throw new PluginNotInitialisedException(Name); + } + + /// + /// Initialises the Grid Interface + /// + /// connect string + /// use mssql_connection.ini + override public void Initialise(string connectionString) + { + m_connectionString = connectionString; + database = new MSSQLManager(connectionString); + + //New migrations check of store + database.CheckMigration(_migrationStore); + } + + /// + /// Shuts down the grid interface + /// + override public void Dispose() + { + database = null; + } + + /// + /// The name of this DB provider. + /// + /// A string containing the storage system name + override public string Name + { + get { return "MSSQL OpenGridData"; } + } + + /// + /// Database provider version. + /// + /// A string containing the storage system version + override public string Version + { + get { return "0.1"; } + } + + #endregion + + #region Public override GridDataBase methods + + /// + /// Returns a list of regions within the specified ranges + /// + /// minimum X coordinate + /// minimum Y coordinate + /// maximum X coordinate + /// maximum Y coordinate + /// null + /// always return null + override public RegionProfileData[] GetProfilesInRange(uint xmin, uint ymin, uint xmax, uint ymax) + { + string sql = "SELECT * FROM regions WHERE locX >= @xmin AND locX <= @xmax AND locY >= @ymin AND locY <= @ymax"; + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.Add(database.CreateParameter("xmin", xmin)); + cmd.Parameters.Add(database.CreateParameter("ymin", ymin)); + cmd.Parameters.Add(database.CreateParameter("xmax", xmax)); + cmd.Parameters.Add(database.CreateParameter("ymax", ymax)); + + List rows = new List(); + conn.Open(); + using (SqlDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + rows.Add(ReadSimRow(reader)); + } + } + + if (rows.Count > 0) + { + return rows.ToArray(); + } + } + m_log.Info("[GRID DB] : Found no regions within range."); + return null; + } + + + /// + /// Returns up to maxNum profiles of regions that have a name starting with namePrefix + /// + /// The name to match against + /// Maximum number of profiles to return + /// A list of sim profiles + override public List GetRegionsByName (string namePrefix, uint maxNum) + { + string sql = "SELECT * FROM regions WHERE regionName LIKE @name"; + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.Add(database.CreateParameter("name", namePrefix + "%")); + + List rows = new List(); + conn.Open(); + using (SqlDataReader reader = cmd.ExecuteReader()) + { + while (rows.Count < maxNum && reader.Read()) + { + rows.Add(ReadSimRow(reader)); + } + } + + return rows; + } + } + + /// + /// Returns a sim profile from its location + /// + /// Region location handle + /// Sim profile + override public RegionProfileData GetProfileByHandle(ulong handle) + { + string sql = "SELECT * FROM " + m_regionsTableName + " WHERE regionHandle = @handle"; + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.Add(database.CreateParameter("handle", handle)); + conn.Open(); + using (SqlDataReader reader = cmd.ExecuteReader()) + { + if (reader.Read()) + { + return ReadSimRow(reader); + } + } + } + m_log.InfoFormat("[GRID DB] : No region found with handle : {0}", handle); + return null; + } + + /// + /// Returns a sim profile from its UUID + /// + /// The region UUID + /// The sim profile + override public RegionProfileData GetProfileByUUID(UUID uuid) + { + string sql = "SELECT * FROM " + m_regionsTableName + " WHERE uuid = @uuid"; + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.Add(database.CreateParameter("uuid", uuid)); + conn.Open(); + using (SqlDataReader reader = cmd.ExecuteReader()) + { + if (reader.Read()) + { + return ReadSimRow(reader); + } + } + } + m_log.InfoFormat("[GRID DB] : No region found with UUID : {0}", uuid); + return null; + } + + /// + /// Returns a sim profile from it's Region name string + /// + /// The region name search query + /// The sim profile + override public RegionProfileData GetProfileByString(string regionName) + { + if (regionName.Length > 2) + { + string sql = "SELECT top 1 * FROM " + m_regionsTableName + " WHERE regionName like @regionName order by regionName"; + + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.Add(database.CreateParameter("regionName", regionName + "%")); + conn.Open(); + using (SqlDataReader reader = cmd.ExecuteReader()) + { + if (reader.Read()) + { + return ReadSimRow(reader); + } + } + } + m_log.InfoFormat("[GRID DB] : No region found with regionName : {0}", regionName); + return null; + } + + m_log.Error("[GRID DB]: Searched for a Region Name shorter then 3 characters"); + return null; + } + + /// + /// Adds a new specified region to the database + /// + /// The profile to add + /// A dataresponse enum indicating success + override public DataResponse StoreProfile(RegionProfileData profile) + { + if (GetProfileByUUID(profile.UUID) == null) + { + if (InsertRegionRow(profile)) + { + return DataResponse.RESPONSE_OK; + } + } + else + { + if (UpdateRegionRow(profile)) + { + return DataResponse.RESPONSE_OK; + } + } + + return DataResponse.RESPONSE_ERROR; + } + + /// + /// Deletes a sim profile from the database + /// + /// the sim UUID + /// Successful? + //public DataResponse DeleteProfile(RegionProfileData profile) + override public DataResponse DeleteProfile(string uuid) + { + string sql = "DELETE FROM regions WHERE uuid = @uuid;"; + + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.Add(database.CreateParameter("uuid", uuid)); + try + { + conn.Open(); + cmd.ExecuteNonQuery(); + return DataResponse.RESPONSE_OK; + } + catch (Exception e) + { + m_log.DebugFormat("[GRID DB] : Error deleting region info, error is : {0}", e.Message); + return DataResponse.RESPONSE_ERROR; + } + } + } + + #endregion + + #region Methods that are not used or deprecated (still needed because of base class) + + /// + /// DEPRECATED. Attempts to authenticate a region by comparing a shared secret. + /// + /// The UUID of the challenger + /// The attempted regionHandle of the challenger + /// The secret + /// Whether the secret and regionhandle match the database entry for UUID + override public bool AuthenticateSim(UUID uuid, ulong handle, string authkey) + { + bool throwHissyFit = false; // Should be true by 1.0 + + if (throwHissyFit) + throw new Exception("CRYPTOWEAK AUTHENTICATE: Refusing to authenticate due to replay potential."); + + RegionProfileData data = GetProfileByUUID(uuid); + + return (handle == data.regionHandle && authkey == data.regionSecret); + } + + /// + /// NOT YET FUNCTIONAL. Provides a cryptographic authentication of a region + /// + /// This requires a security audit. + /// + /// + /// + /// + /// + public bool AuthenticateSim(UUID uuid, ulong handle, string authhash, string challenge) + { + // SHA512Managed HashProvider = new SHA512Managed(); + // Encoding TextProvider = new UTF8Encoding(); + + // byte[] stream = TextProvider.GetBytes(uuid.ToString() + ":" + handle.ToString() + ":" + challenge); + // byte[] hash = HashProvider.ComputeHash(stream); + return false; + } + + /// + /// NOT IMPLEMENTED + /// WHEN IS THIS GONNA BE IMPLEMENTED. + /// + /// + /// + /// null + override public ReservationData GetReservationAtPoint(uint x, uint y) + { + return null; + } + + #endregion + + #region private methods + + /// + /// Reads a region row from a database reader + /// + /// An active database reader + /// A region profile + private static RegionProfileData ReadSimRow(IDataRecord reader) + { + RegionProfileData retval = new RegionProfileData(); + + // Region Main gotta-have-or-we-return-null parts + UInt64 tmp64; + if (!UInt64.TryParse(reader["regionHandle"].ToString(), out tmp64)) + { + return null; + } + + retval.regionHandle = tmp64; + +// UUID tmp_uuid; +// if (!UUID.TryParse((string)reader["uuid"], out tmp_uuid)) +// { +// return null; +// } + + retval.UUID = new UUID((Guid)reader["uuid"]); // tmp_uuid; + + // non-critical parts + retval.regionName = reader["regionName"].ToString(); + retval.originUUID = new UUID((Guid)reader["originUUID"]); + + // Secrets + retval.regionRecvKey = reader["regionRecvKey"].ToString(); + retval.regionSecret = reader["regionSecret"].ToString(); + retval.regionSendKey = reader["regionSendKey"].ToString(); + + // Region Server + retval.regionDataURI = reader["regionDataURI"].ToString(); + retval.regionOnline = false; // Needs to be pinged before this can be set. + retval.serverIP = reader["serverIP"].ToString(); + retval.serverPort = Convert.ToUInt32(reader["serverPort"]); + retval.serverURI = reader["serverURI"].ToString(); + retval.httpPort = Convert.ToUInt32(reader["serverHttpPort"].ToString()); + retval.remotingPort = Convert.ToUInt32(reader["serverRemotingPort"].ToString()); + + // Location + retval.regionLocX = Convert.ToUInt32(reader["locX"].ToString()); + retval.regionLocY = Convert.ToUInt32(reader["locY"].ToString()); + retval.regionLocZ = Convert.ToUInt32(reader["locZ"].ToString()); + + // Neighbours - 0 = No Override + retval.regionEastOverrideHandle = Convert.ToUInt64(reader["eastOverrideHandle"].ToString()); + retval.regionWestOverrideHandle = Convert.ToUInt64(reader["westOverrideHandle"].ToString()); + retval.regionSouthOverrideHandle = Convert.ToUInt64(reader["southOverrideHandle"].ToString()); + retval.regionNorthOverrideHandle = Convert.ToUInt64(reader["northOverrideHandle"].ToString()); + + // Assets + retval.regionAssetURI = reader["regionAssetURI"].ToString(); + retval.regionAssetRecvKey = reader["regionAssetRecvKey"].ToString(); + retval.regionAssetSendKey = reader["regionAssetSendKey"].ToString(); + + // Userserver + retval.regionUserURI = reader["regionUserURI"].ToString(); + retval.regionUserRecvKey = reader["regionUserRecvKey"].ToString(); + retval.regionUserSendKey = reader["regionUserSendKey"].ToString(); + + // World Map Addition + retval.regionMapTextureID = new UUID((Guid)reader["regionMapTexture"]); + retval.owner_uuid = new UUID((Guid)reader["owner_uuid"]); + retval.maturity = Convert.ToUInt32(reader["access"]); + return retval; + } + + /// + /// Update the specified region in the database + /// + /// The profile to update + /// success ? + private bool UpdateRegionRow(RegionProfileData profile) + { + bool returnval = false; + + //Insert new region + string sql = + "UPDATE " + m_regionsTableName + @" SET + [regionHandle]=@regionHandle, [regionName]=@regionName, + [regionRecvKey]=@regionRecvKey, [regionSecret]=@regionSecret, [regionSendKey]=@regionSendKey, + [regionDataURI]=@regionDataURI, [serverIP]=@serverIP, [serverPort]=@serverPort, [serverURI]=@serverURI, + [locX]=@locX, [locY]=@locY, [locZ]=@locZ, [eastOverrideHandle]=@eastOverrideHandle, + [westOverrideHandle]=@westOverrideHandle, [southOverrideHandle]=@southOverrideHandle, + [northOverrideHandle]=@northOverrideHandle, [regionAssetURI]=@regionAssetURI, + [regionAssetRecvKey]=@regionAssetRecvKey, [regionAssetSendKey]=@regionAssetSendKey, + [regionUserURI]=@regionUserURI, [regionUserRecvKey]=@regionUserRecvKey, [regionUserSendKey]=@regionUserSendKey, + [regionMapTexture]=@regionMapTexture, [serverHttpPort]=@serverHttpPort, + [serverRemotingPort]=@serverRemotingPort, [owner_uuid]=@owner_uuid , [originUUID]=@originUUID + where [uuid]=@uuid"; + + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand command = new SqlCommand(sql, conn)) + { + command.Parameters.Add(database.CreateParameter("regionHandle", profile.regionHandle)); + command.Parameters.Add(database.CreateParameter("regionName", profile.regionName)); + command.Parameters.Add(database.CreateParameter("uuid", profile.UUID)); + command.Parameters.Add(database.CreateParameter("regionRecvKey", profile.regionRecvKey)); + command.Parameters.Add(database.CreateParameter("regionSecret", profile.regionSecret)); + command.Parameters.Add(database.CreateParameter("regionSendKey", profile.regionSendKey)); + command.Parameters.Add(database.CreateParameter("regionDataURI", profile.regionDataURI)); + command.Parameters.Add(database.CreateParameter("serverIP", profile.serverIP)); + command.Parameters.Add(database.CreateParameter("serverPort", profile.serverPort)); + command.Parameters.Add(database.CreateParameter("serverURI", profile.serverURI)); + command.Parameters.Add(database.CreateParameter("locX", profile.regionLocX)); + command.Parameters.Add(database.CreateParameter("locY", profile.regionLocY)); + command.Parameters.Add(database.CreateParameter("locZ", profile.regionLocZ)); + command.Parameters.Add(database.CreateParameter("eastOverrideHandle", profile.regionEastOverrideHandle)); + command.Parameters.Add(database.CreateParameter("westOverrideHandle", profile.regionWestOverrideHandle)); + command.Parameters.Add(database.CreateParameter("northOverrideHandle", profile.regionNorthOverrideHandle)); + command.Parameters.Add(database.CreateParameter("southOverrideHandle", profile.regionSouthOverrideHandle)); + command.Parameters.Add(database.CreateParameter("regionAssetURI", profile.regionAssetURI)); + command.Parameters.Add(database.CreateParameter("regionAssetRecvKey", profile.regionAssetRecvKey)); + command.Parameters.Add(database.CreateParameter("regionAssetSendKey", profile.regionAssetSendKey)); + command.Parameters.Add(database.CreateParameter("regionUserURI", profile.regionUserURI)); + command.Parameters.Add(database.CreateParameter("regionUserRecvKey", profile.regionUserRecvKey)); + command.Parameters.Add(database.CreateParameter("regionUserSendKey", profile.regionUserSendKey)); + command.Parameters.Add(database.CreateParameter("regionMapTexture", profile.regionMapTextureID)); + command.Parameters.Add(database.CreateParameter("serverHttpPort", profile.httpPort)); + command.Parameters.Add(database.CreateParameter("serverRemotingPort", profile.remotingPort)); + command.Parameters.Add(database.CreateParameter("owner_uuid", profile.owner_uuid)); + command.Parameters.Add(database.CreateParameter("originUUID", profile.originUUID)); + conn.Open(); + try + { + command.ExecuteNonQuery(); + returnval = true; + } + catch (Exception e) + { + m_log.Error("[GRID DB] : Error updating region, error: " + e.Message); + } + } + + return returnval; + } + + /// + /// Creates a new region in the database + /// + /// The region profile to insert + /// Successful? + private bool InsertRegionRow(RegionProfileData profile) + { + bool returnval = false; + + //Insert new region + string sql = + "INSERT INTO " + m_regionsTableName + @" ([regionHandle], [regionName], [uuid], [regionRecvKey], [regionSecret], [regionSendKey], [regionDataURI], + [serverIP], [serverPort], [serverURI], [locX], [locY], [locZ], [eastOverrideHandle], [westOverrideHandle], + [southOverrideHandle], [northOverrideHandle], [regionAssetURI], [regionAssetRecvKey], [regionAssetSendKey], + [regionUserURI], [regionUserRecvKey], [regionUserSendKey], [regionMapTexture], [serverHttpPort], + [serverRemotingPort], [owner_uuid], [originUUID], [access]) + VALUES (@regionHandle, @regionName, @uuid, @regionRecvKey, @regionSecret, @regionSendKey, @regionDataURI, + @serverIP, @serverPort, @serverURI, @locX, @locY, @locZ, @eastOverrideHandle, @westOverrideHandle, + @southOverrideHandle, @northOverrideHandle, @regionAssetURI, @regionAssetRecvKey, @regionAssetSendKey, + @regionUserURI, @regionUserRecvKey, @regionUserSendKey, @regionMapTexture, @serverHttpPort, @serverRemotingPort, @owner_uuid, @originUUID, @access);"; + + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand command = new SqlCommand(sql, conn)) + { + command.Parameters.Add(database.CreateParameter("regionHandle", profile.regionHandle)); + command.Parameters.Add(database.CreateParameter("regionName", profile.regionName)); + command.Parameters.Add(database.CreateParameter("uuid", profile.UUID)); + command.Parameters.Add(database.CreateParameter("regionRecvKey", profile.regionRecvKey)); + command.Parameters.Add(database.CreateParameter("regionSecret", profile.regionSecret)); + command.Parameters.Add(database.CreateParameter("regionSendKey", profile.regionSendKey)); + command.Parameters.Add(database.CreateParameter("regionDataURI", profile.regionDataURI)); + command.Parameters.Add(database.CreateParameter("serverIP", profile.serverIP)); + command.Parameters.Add(database.CreateParameter("serverPort", profile.serverPort)); + command.Parameters.Add(database.CreateParameter("serverURI", profile.serverURI)); + command.Parameters.Add(database.CreateParameter("locX", profile.regionLocX)); + command.Parameters.Add(database.CreateParameter("locY", profile.regionLocY)); + command.Parameters.Add(database.CreateParameter("locZ", profile.regionLocZ)); + command.Parameters.Add(database.CreateParameter("eastOverrideHandle", profile.regionEastOverrideHandle)); + command.Parameters.Add(database.CreateParameter("westOverrideHandle", profile.regionWestOverrideHandle)); + command.Parameters.Add(database.CreateParameter("northOverrideHandle", profile.regionNorthOverrideHandle)); + command.Parameters.Add(database.CreateParameter("southOverrideHandle", profile.regionSouthOverrideHandle)); + command.Parameters.Add(database.CreateParameter("regionAssetURI", profile.regionAssetURI)); + command.Parameters.Add(database.CreateParameter("regionAssetRecvKey", profile.regionAssetRecvKey)); + command.Parameters.Add(database.CreateParameter("regionAssetSendKey", profile.regionAssetSendKey)); + command.Parameters.Add(database.CreateParameter("regionUserURI", profile.regionUserURI)); + command.Parameters.Add(database.CreateParameter("regionUserRecvKey", profile.regionUserRecvKey)); + command.Parameters.Add(database.CreateParameter("regionUserSendKey", profile.regionUserSendKey)); + command.Parameters.Add(database.CreateParameter("regionMapTexture", profile.regionMapTextureID)); + command.Parameters.Add(database.CreateParameter("serverHttpPort", profile.httpPort)); + command.Parameters.Add(database.CreateParameter("serverRemotingPort", profile.remotingPort)); + command.Parameters.Add(database.CreateParameter("owner_uuid", profile.owner_uuid)); + command.Parameters.Add(database.CreateParameter("originUUID", profile.originUUID)); + command.Parameters.Add(database.CreateParameter("access", profile.maturity)); + conn.Open(); + try + { + command.ExecuteNonQuery(); + returnval = true; + } + catch (Exception e) + { + m_log.Error("[GRID DB] : Error inserting region, error: " + e.Message); + } + } + + return returnval; + } + + #endregion + } +} diff --git a/OpenSim/Data/MSSQL/MSSQLInventoryData.cs b/OpenSim/Data/MSSQL/MSSQLInventoryData.cs index 1482184..4815700 100644 --- a/OpenSim/Data/MSSQL/MSSQLInventoryData.cs +++ b/OpenSim/Data/MSSQL/MSSQLInventoryData.cs @@ -49,6 +49,7 @@ namespace OpenSim.Data.MSSQL /// The database manager /// private MSSQLManager database; + private string m_connectionString; #region IPlugin members @@ -66,24 +67,9 @@ namespace OpenSim.Data.MSSQL /// use mssql_connection.ini public void Initialise(string connectionString) { - if (!string.IsNullOrEmpty(connectionString)) - { - database = new MSSQLManager(connectionString); - } - else - { - IniFile gridDataMSSqlFile = new IniFile("mssql_connection.ini"); - string settingDataSource = gridDataMSSqlFile.ParseFileReadValue("data_source"); - string settingInitialCatalog = gridDataMSSqlFile.ParseFileReadValue("initial_catalog"); - string settingPersistSecurityInfo = gridDataMSSqlFile.ParseFileReadValue("persist_security_info"); - string settingUserId = gridDataMSSqlFile.ParseFileReadValue("user_id"); - string settingPassword = gridDataMSSqlFile.ParseFileReadValue("password"); - - database = - new MSSQLManager(settingDataSource, settingInitialCatalog, settingPersistSecurityInfo, settingUserId, - settingPassword); - } - + m_connectionString = connectionString; + database = new MSSQLManager(connectionString); + //New migrations check of store database.CheckMigration(_migrationStore); } @@ -169,11 +155,13 @@ namespace OpenSim.Data.MSSQL /// A folder class public InventoryFolderBase getInventoryFolder(UUID folderID) { - using (AutoClosingSqlCommand command = database.Query("SELECT * FROM inventoryfolders WHERE folderID = @folderID")) + string sql = "SELECT * FROM inventoryfolders WHERE folderID = @folderID"; + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) { - command.Parameters.Add(database.CreateParameter("folderID", folderID)); - - using (IDataReader reader = command.ExecuteReader()) + cmd.Parameters.Add(database.CreateParameter("folderID", folderID)); + conn.Open(); + using (SqlDataReader reader = cmd.ExecuteReader()) { if (reader.Read()) { @@ -197,18 +185,19 @@ namespace OpenSim.Data.MSSQL //Note this is changed so it opens only one connection to the database and not everytime it wants to get data. List folders = new List(); - - using (AutoClosingSqlCommand command = database.Query("SELECT * FROM inventoryfolders WHERE parentFolderID = @parentID")) + string sql = "SELECT * FROM inventoryfolders WHERE parentFolderID = @parentID"; + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) { - command.Parameters.Add(database.CreateParameter("@parentID", parentID)); - - folders.AddRange(getInventoryFolders(command)); + cmd.Parameters.Add(database.CreateParameter("@parentID", parentID)); + conn.Open(); + folders.AddRange(getInventoryFolders(cmd)); List tempFolders = new List(); foreach (InventoryFolderBase folderBase in folders) { - tempFolders.AddRange(getFolderHierarchy(folderBase.ID, command)); + tempFolders.AddRange(getFolderHierarchy(folderBase.ID, cmd)); } if (tempFolders.Count > 0) { @@ -233,20 +222,19 @@ namespace OpenSim.Data.MSSQL folderName = folderName.Substring(0, 64); m_log.Warn("[INVENTORY DB]: Name field truncated from " + folder.Name.Length.ToString() + " to " + folderName.Length + " characters on add"); } - - using (AutoClosingSqlCommand command = database.Query(sql)) + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) { - command.Parameters.Add(database.CreateParameter("folderID", folder.ID)); - command.Parameters.Add(database.CreateParameter("agentID", folder.Owner)); - command.Parameters.Add(database.CreateParameter("parentFolderID", folder.ParentID)); - command.Parameters.Add(database.CreateParameter("folderName", folderName)); - command.Parameters.Add(database.CreateParameter("type", folder.Type)); - command.Parameters.Add(database.CreateParameter("version", folder.Version)); - + cmd.Parameters.Add(database.CreateParameter("folderID", folder.ID)); + cmd.Parameters.Add(database.CreateParameter("agentID", folder.Owner)); + cmd.Parameters.Add(database.CreateParameter("parentFolderID", folder.ParentID)); + cmd.Parameters.Add(database.CreateParameter("folderName", folderName)); + cmd.Parameters.Add(database.CreateParameter("type", folder.Type)); + cmd.Parameters.Add(database.CreateParameter("version", folder.Version)); + conn.Open(); try { - //IDbCommand result = database.Query(sql, param); - command.ExecuteNonQuery(); + cmd.ExecuteNonQuery(); } catch (Exception e) { @@ -275,20 +263,20 @@ namespace OpenSim.Data.MSSQL folderName = folderName.Substring(0, 64); m_log.Warn("[INVENTORY DB]: Name field truncated from " + folder.Name.Length.ToString() + " to " + folderName.Length + " characters on update"); } - - using (AutoClosingSqlCommand command = database.Query(sql)) - { - command.Parameters.Add(database.CreateParameter("folderID", folder.ID)); - command.Parameters.Add(database.CreateParameter("agentID", folder.Owner)); - command.Parameters.Add(database.CreateParameter("parentFolderID", folder.ParentID)); - command.Parameters.Add(database.CreateParameter("folderName", folderName)); - command.Parameters.Add(database.CreateParameter("type", folder.Type)); - command.Parameters.Add(database.CreateParameter("version", folder.Version)); - command.Parameters.Add(database.CreateParameter("@keyFolderID", folder.ID)); - + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.Add(database.CreateParameter("folderID", folder.ID)); + cmd.Parameters.Add(database.CreateParameter("agentID", folder.Owner)); + cmd.Parameters.Add(database.CreateParameter("parentFolderID", folder.ParentID)); + cmd.Parameters.Add(database.CreateParameter("folderName", folderName)); + cmd.Parameters.Add(database.CreateParameter("type", folder.Type)); + cmd.Parameters.Add(database.CreateParameter("version", folder.Version)); + cmd.Parameters.Add(database.CreateParameter("@keyFolderID", folder.ID)); + conn.Open(); try { - command.ExecuteNonQuery(); + cmd.ExecuteNonQuery(); } catch (Exception e) { @@ -304,14 +292,15 @@ namespace OpenSim.Data.MSSQL public void moveInventoryFolder(InventoryFolderBase folder) { string sql = @"UPDATE inventoryfolders SET parentFolderID = @parentFolderID WHERE folderID = @folderID"; - using (IDbCommand command = database.Query(sql)) + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) { - command.Parameters.Add(database.CreateParameter("parentFolderID", folder.ParentID)); - command.Parameters.Add(database.CreateParameter("@folderID", folder.ID)); - + cmd.Parameters.Add(database.CreateParameter("parentFolderID", folder.ParentID)); + cmd.Parameters.Add(database.CreateParameter("@folderID", folder.ID)); + conn.Open(); try { - command.ExecuteNonQuery(); + cmd.ExecuteNonQuery(); } catch (Exception e) { @@ -326,30 +315,27 @@ namespace OpenSim.Data.MSSQL /// Id of folder to delete public void deleteInventoryFolder(UUID folderID) { - using (SqlConnection connection = database.DatabaseConnection()) + string sql = "SELECT * FROM inventoryfolders WHERE parentFolderID = @parentID"; + + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) { List subFolders; - using (SqlCommand command = new SqlCommand("SELECT * FROM inventoryfolders WHERE parentFolderID = @parentID", connection)) - { - command.Parameters.Add(database.CreateParameter("@parentID", UUID.Zero)); - - AutoClosingSqlCommand autoCommand = new AutoClosingSqlCommand(command); - - subFolders = getFolderHierarchy(folderID, autoCommand); - } + cmd.Parameters.Add(database.CreateParameter("@parentID", UUID.Zero)); + conn.Open(); + subFolders = getFolderHierarchy(folderID, cmd); + //Delete all sub-folders foreach (InventoryFolderBase f in subFolders) { - DeleteOneFolder(f.ID, connection); - DeleteItemsInFolder(f.ID, connection); + DeleteOneFolder(f.ID, conn); + DeleteItemsInFolder(f.ID, conn); } //Delete the actual row - DeleteOneFolder(folderID, connection); - DeleteItemsInFolder(folderID, connection); - - connection.Close(); + DeleteOneFolder(folderID, conn); + DeleteItemsInFolder(folderID, conn); } } @@ -364,13 +350,15 @@ namespace OpenSim.Data.MSSQL /// A list containing inventory items public List getInventoryInFolder(UUID folderID) { - using (AutoClosingSqlCommand command = database.Query("SELECT * FROM inventoryitems WHERE parentFolderID = @parentFolderID")) + string sql = "SELECT * FROM inventoryitems WHERE parentFolderID = @parentFolderID"; + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) { - command.Parameters.Add(database.CreateParameter("parentFolderID", folderID)); - + cmd.Parameters.Add(database.CreateParameter("parentFolderID", folderID)); + conn.Open(); List items = new List(); - using (SqlDataReader reader = command.ExecuteReader()) + using (SqlDataReader reader = cmd.ExecuteReader()) { while (reader.Read()) { @@ -388,11 +376,13 @@ namespace OpenSim.Data.MSSQL /// An inventory item public InventoryItemBase getInventoryItem(UUID itemID) { - using (AutoClosingSqlCommand result = database.Query("SELECT * FROM inventoryitems WHERE inventoryID = @inventoryID")) + string sql = "SELECT * FROM inventoryitems WHERE inventoryID = @inventoryID"; + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) { - result.Parameters.Add(database.CreateParameter("inventoryID", itemID)); - - using (IDataReader reader = result.ExecuteReader()) + cmd.Parameters.Add(database.CreateParameter("inventoryID", itemID)); + conn.Open(); + using (SqlDataReader reader = cmd.ExecuteReader()) { if (reader.Read()) { @@ -441,8 +431,9 @@ namespace OpenSim.Data.MSSQL itemDesc = item.Description.Substring(0, 128); m_log.Warn("[INVENTORY DB]: Description field truncated from " + item.Description.Length.ToString() + " to " + itemDesc.Length.ToString() + " characters"); } - - using (AutoClosingSqlCommand command = database.Query(sql)) + + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand command = new SqlCommand(sql, conn)) { command.Parameters.Add(database.CreateParameter("inventoryID", item.ID)); command.Parameters.Add(database.CreateParameter("assetID", item.AssetID)); @@ -464,7 +455,7 @@ namespace OpenSim.Data.MSSQL command.Parameters.Add(database.CreateParameter("groupID", item.GroupID)); command.Parameters.Add(database.CreateParameter("groupOwned", item.GroupOwned)); command.Parameters.Add(database.CreateParameter("flags", item.Flags)); - + conn.Open(); try { command.ExecuteNonQuery(); @@ -476,9 +467,11 @@ namespace OpenSim.Data.MSSQL } sql = "UPDATE inventoryfolders SET version = version + 1 WHERE folderID = @folderID"; - using (AutoClosingSqlCommand command = database.Query(sql)) + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand command = new SqlCommand(sql, conn)) { command.Parameters.Add(database.CreateParameter("folderID", item.Folder.ToString())); + conn.Open(); try { command.ExecuteNonQuery(); @@ -530,8 +523,9 @@ namespace OpenSim.Data.MSSQL itemDesc = item.Description.Substring(0, 128); m_log.Warn("[INVENTORY DB]: Description field truncated from " + item.Description.Length.ToString() + " to " + itemDesc.Length.ToString() + " characters on update"); } - - using (AutoClosingSqlCommand command = database.Query(sql)) + + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand command = new SqlCommand(sql, conn)) { command.Parameters.Add(database.CreateParameter("inventoryID", item.ID)); command.Parameters.Add(database.CreateParameter("assetID", item.AssetID)); @@ -552,8 +546,8 @@ namespace OpenSim.Data.MSSQL command.Parameters.Add(database.CreateParameter("groupID", item.GroupID)); command.Parameters.Add(database.CreateParameter("groupOwned", item.GroupOwned)); command.Parameters.Add(database.CreateParameter("flags", item.Flags)); - command.Parameters.Add(database.CreateParameter("@keyInventoryID", item.ID)); - + command.Parameters.Add(database.CreateParameter("keyInventoryID", item.ID)); + conn.Open(); try { command.ExecuteNonQuery(); @@ -573,13 +567,15 @@ namespace OpenSim.Data.MSSQL /// the item UUID public void deleteInventoryItem(UUID itemID) { - using (AutoClosingSqlCommand command = database.Query("DELETE FROM inventoryitems WHERE inventoryID=@inventoryID")) + string sql = "DELETE FROM inventoryitems WHERE inventoryID=@inventoryID"; + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) { - command.Parameters.Add(database.CreateParameter("inventoryID", itemID)); + cmd.Parameters.Add(database.CreateParameter("inventoryID", itemID)); try { - - command.ExecuteNonQuery(); + conn.Open(); + cmd.ExecuteNonQuery(); } catch (Exception e) { @@ -607,12 +603,14 @@ namespace OpenSim.Data.MSSQL /// public List fetchActiveGestures(UUID avatarID) { - using (AutoClosingSqlCommand command = database.Query("SELECT * FROM inventoryitems WHERE avatarId = @uuid AND assetType = @assetType and flags = 1")) - { - command.Parameters.Add(database.CreateParameter("uuid", avatarID)); - command.Parameters.Add(database.CreateParameter("assetType", (int)AssetType.Gesture)); - - using (IDataReader reader = command.ExecuteReader()) + string sql = "SELECT * FROM inventoryitems WHERE avatarId = @uuid AND assetType = @assetType and flags = 1"; + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.Add(database.CreateParameter("uuid", avatarID)); + cmd.Parameters.Add(database.CreateParameter("assetType", (int)AssetType.Gesture)); + conn.Open(); + using (SqlDataReader reader = cmd.ExecuteReader()) { List gestureList = new List(); while (reader.Read()) @@ -656,7 +654,7 @@ namespace OpenSim.Data.MSSQL /// parent ID. /// SQL command/connection to database /// - private static List getFolderHierarchy(UUID parentID, AutoClosingSqlCommand command) + private static List getFolderHierarchy(UUID parentID, SqlCommand command) { command.Parameters["@parentID"].Value = parentID.Guid; //.ToString(); @@ -687,7 +685,9 @@ namespace OpenSim.Data.MSSQL /// private List getInventoryFolders(UUID parentID, UUID user) { - using (AutoClosingSqlCommand command = database.Query("SELECT * FROM inventoryfolders WHERE parentFolderID = @parentID AND agentID LIKE @uuid")) + string sql = "SELECT * FROM inventoryfolders WHERE parentFolderID = @parentID AND agentID LIKE @uuid"; + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand command = new SqlCommand(sql, conn)) { if (user == UUID.Zero) { @@ -698,7 +698,7 @@ namespace OpenSim.Data.MSSQL command.Parameters.Add(database.CreateParameter("uuid", user)); } command.Parameters.Add(database.CreateParameter("parentID", parentID)); - + conn.Open(); return getInventoryFolders(command); } } @@ -708,9 +708,9 @@ namespace OpenSim.Data.MSSQL /// /// SQLcommand. /// - private static List getInventoryFolders(AutoClosingSqlCommand command) + private static List getInventoryFolders(SqlCommand command) { - using (IDataReader reader = command.ExecuteReader()) + using (SqlDataReader reader = command.ExecuteReader()) { List items = new List(); @@ -727,7 +727,7 @@ namespace OpenSim.Data.MSSQL /// /// A MSSQL Data Reader /// A List containing inventory folders - protected static InventoryFolderBase readInventoryFolder(IDataReader reader) + protected static InventoryFolderBase readInventoryFolder(SqlDataReader reader) { try { diff --git a/OpenSim/Data/MSSQL/MSSQLLegacyRegionData.cs b/OpenSim/Data/MSSQL/MSSQLLegacyRegionData.cs index 6371307..c849f38 100644 --- a/OpenSim/Data/MSSQL/MSSQLLegacyRegionData.cs +++ b/OpenSim/Data/MSSQL/MSSQLLegacyRegionData.cs @@ -54,28 +54,16 @@ namespace OpenSim.Data.MSSQL /// The database manager /// private MSSQLManager _Database; - + private string m_connectionString; /// /// Initialises the region datastore /// /// The connection string. public void Initialise(string connectionString) { - if (!string.IsNullOrEmpty(connectionString)) - { - _Database = new MSSQLManager(connectionString); - } - else - { - IniFile iniFile = new IniFile("mssql_connection.ini"); - string settingDataSource = iniFile.ParseFileReadValue("data_source"); - string settingInitialCatalog = iniFile.ParseFileReadValue("initial_catalog"); - string settingPersistSecurityInfo = iniFile.ParseFileReadValue("persist_security_info"); - string settingUserId = iniFile.ParseFileReadValue("user_id"); - string settingPassword = iniFile.ParseFileReadValue("password"); - - _Database = new MSSQLManager(settingDataSource, settingInitialCatalog, settingPersistSecurityInfo, settingUserId, settingPassword); - } + m_connectionString = connectionString; + _Database = new MSSQLManager(connectionString); + //Migration settings _Database.CheckMigration(_migrationStore); @@ -102,17 +90,18 @@ namespace OpenSim.Data.MSSQL SceneObjectGroup grp = null; - string query = "SELECT *, " + + string sql = "SELECT *, " + "sort = CASE WHEN prims.UUID = prims.SceneGroupID THEN 0 ELSE 1 END " + "FROM prims " + "LEFT JOIN primshapes ON prims.UUID = primshapes.UUID " + "WHERE RegionUUID = @RegionUUID " + "ORDER BY SceneGroupID asc, sort asc, LinkNumber asc"; - using (AutoClosingSqlCommand command = _Database.Query(query)) + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand command = new SqlCommand(sql, conn)) { command.Parameters.Add(_Database.CreateParameter("@regionUUID", regionUUID)); - + conn.Open(); using (SqlDataReader reader = command.ExecuteReader()) { while (reader.Read()) @@ -122,7 +111,7 @@ namespace OpenSim.Data.MSSQL sceneObjectPart.Shape = PrimitiveBaseShape.Default; else sceneObjectPart.Shape = BuildShape(reader); - + prims[sceneObjectPart.UUID] = sceneObjectPart; UUID groupID = new UUID((Guid)reader["SceneGroupID"]); @@ -133,7 +122,7 @@ namespace OpenSim.Data.MSSQL objects[grp.UUID] = grp; lastGroupID = groupID; - + // There sometimes exist OpenSim bugs that 'orphan groups' so that none of the prims are // recorded as the root prim (for which the UUID must equal the persisted group UUID). In // this case, force the UUID to be the same as the group UUID so that at least these can be @@ -142,7 +131,7 @@ namespace OpenSim.Data.MSSQL if (sceneObjectPart.UUID != groupID && groupID != UUID.Zero) { _Log.WarnFormat( - "[REGION DB]: Found root prim {0} {1} at {2} where group was actually {3}. Forcing UUID to group UUID", + "[REGION DB]: Found root prim {0} {1} at {2} where group was actually {3}. Forcing UUID to group UUID", sceneObjectPart.Name, sceneObjectPart.UUID, sceneObjectPart.GroupPosition, groupID); sceneObjectPart.UUID = groupID; @@ -174,8 +163,10 @@ namespace OpenSim.Data.MSSQL // LoadItems only on those List primsWithInventory = new List(); string qry = "select distinct primID from primitems"; - using (AutoClosingSqlCommand command = _Database.Query(qry)) + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand command = new SqlCommand(qry, conn)) { + conn.Open(); using (SqlDataReader itemReader = command.ExecuteReader()) { while (itemReader.Read()) @@ -205,14 +196,16 @@ namespace OpenSim.Data.MSSQL /// all prims with inventory on a region private void LoadItems(List allPrimsWithInventory) { - - using (AutoClosingSqlCommand command = _Database.Query("SELECT * FROM primitems WHERE PrimID = @PrimID")) + string sql = "SELECT * FROM primitems WHERE PrimID = @PrimID"; + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand command = new SqlCommand(sql, conn)) { + conn.Open(); foreach (SceneObjectPart objectPart in allPrimsWithInventory) { command.Parameters.Clear(); command.Parameters.Add(_Database.CreateParameter("@PrimID", objectPart.UUID)); - + List inventory = new List(); using (SqlDataReader reader = command.ExecuteReader()) @@ -241,8 +234,9 @@ namespace OpenSim.Data.MSSQL { _Log.InfoFormat("[MSSQL]: Adding/Changing SceneObjectGroup: {0} to region: {1}, object has {2} prims.", obj.UUID, regionUUID, obj.Children.Count); - using (SqlConnection conn = _Database.DatabaseConnection()) + using (SqlConnection conn = new SqlConnection(m_connectionString)) { + conn.Open(); SqlTransaction transaction = conn.BeginTransaction(); try @@ -437,8 +431,12 @@ ELSE lock (_Database) { //Using the non transaction mode. - using (AutoClosingSqlCommand cmd = _Database.Query(sqlPrimShapes)) + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand()) { + cmd.Connection = conn; + cmd.CommandText = sqlPrimShapes; + conn.Open(); cmd.Parameters.Add(_Database.CreateParameter("objectID", objectID)); cmd.ExecuteNonQuery(); @@ -466,24 +464,30 @@ ELSE //Delete everything from PrimID //TODO add index on PrimID in DB, if not already exist - using (AutoClosingSqlCommand cmd = _Database.Query("DELETE PRIMITEMS WHERE primID = @primID")) + + string sql = "DELETE PRIMITEMS WHERE primID = @primID"; + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) { cmd.Parameters.Add(_Database.CreateParameter("@primID", primID)); + conn.Open(); cmd.ExecuteNonQuery(); } - string sql = + sql = @"INSERT INTO primitems ( itemID,primID,assetID,parentFolderID,invType,assetType,name,description,creationDate,creatorID,ownerID,lastOwnerID,groupID, nextPermissions,currentPermissions,basePermissions,everyonePermissions,groupPermissions,flags) VALUES (@itemID,@primID,@assetID,@parentFolderID,@invType,@assetType,@name,@description,@creationDate,@creatorID,@ownerID, @lastOwnerID,@groupID,@nextPermissions,@currentPermissions,@basePermissions,@everyonePermissions,@groupPermissions,@flags)"; - using (AutoClosingSqlCommand cmd = _Database.Query(sql)) + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) { foreach (TaskInventoryItem taskItem in items) { cmd.Parameters.AddRange(CreatePrimInventoryParameters(taskItem)); + conn.Open(); cmd.ExecuteNonQuery(); cmd.Parameters.Clear(); @@ -505,11 +509,12 @@ ELSE string sql = "select top 1 RegionUUID, Revision, Heightfield from terrain where RegionUUID = @RegionUUID order by Revision desc"; - using (AutoClosingSqlCommand cmd = _Database.Query(sql)) + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) { // MySqlParameter param = new MySqlParameter(); cmd.Parameters.Add(_Database.CreateParameter("@RegionUUID", regionID)); - + conn.Open(); using (SqlDataReader reader = cmd.ExecuteReader()) { int rev; @@ -549,19 +554,23 @@ ELSE //Delete old terrain map string sql = "delete from terrain where RegionUUID=@RegionUUID"; - using (AutoClosingSqlCommand cmd = _Database.Query(sql)) + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) { cmd.Parameters.Add(_Database.CreateParameter("@RegionUUID", regionID)); + conn.Open(); cmd.ExecuteNonQuery(); } sql = "insert into terrain(RegionUUID, Revision, Heightfield) values(@RegionUUID, @Revision, @Heightfield)"; - using (AutoClosingSqlCommand cmd = _Database.Query(sql)) + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) { cmd.Parameters.Add(_Database.CreateParameter("@RegionUUID", regionID)); cmd.Parameters.Add(_Database.CreateParameter("@Revision", revision)); cmd.Parameters.Add(_Database.CreateParameter("@Heightfield", serializeTerrain(terrain))); + conn.Open(); cmd.ExecuteNonQuery(); } @@ -580,11 +589,12 @@ ELSE string sql = "select * from land where RegionUUID = @RegionUUID"; //Retrieve all land data from region - using (AutoClosingSqlCommand cmdLandData = _Database.Query(sql)) + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) { - cmdLandData.Parameters.Add(_Database.CreateParameter("@RegionUUID", regionUUID)); - - using (SqlDataReader readerLandData = cmdLandData.ExecuteReader()) + cmd.Parameters.Add(_Database.CreateParameter("@RegionUUID", regionUUID)); + conn.Open(); + using (SqlDataReader readerLandData = cmd.ExecuteReader()) { while (readerLandData.Read()) { @@ -597,10 +607,12 @@ ELSE foreach (LandData LandData in LandDataForRegion) { sql = "select * from landaccesslist where LandUUID = @LandUUID"; - using (AutoClosingSqlCommand cmdAccessList = _Database.Query(sql)) + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) { - cmdAccessList.Parameters.Add(_Database.CreateParameter("@LandUUID", LandData.GlobalID)); - using (SqlDataReader readerAccessList = cmdAccessList.ExecuteReader()) + cmd.Parameters.Add(_Database.CreateParameter("@LandUUID", LandData.GlobalID)); + conn.Open(); + using (SqlDataReader readerAccessList = cmd.ExecuteReader()) { while (readerAccessList.Read()) { @@ -632,17 +644,20 @@ ELSE VALUES (@UUID,@RegionUUID,@LocalLandID,@Bitmap,@Name,@Description,@OwnerUUID,@IsGroupOwned,@Area,@AuctionID,@Category,@ClaimDate,@ClaimPrice,@GroupUUID,@SalePrice,@LandStatus,@LandFlags,@LandingType,@MediaAutoScale,@MediaTextureUUID,@MediaURL,@MusicURL,@PassHours,@PassPrice,@SnapshotUUID,@UserLocationX,@UserLocationY,@UserLocationZ,@UserLookAtX,@UserLookAtY,@UserLookAtZ,@AuthbuyerID,@OtherCleanTime,@Dwell)"; - using (AutoClosingSqlCommand cmd = _Database.Query(sql)) + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) { cmd.Parameters.AddRange(CreateLandParameters(parcel.LandData, parcel.RegionUUID)); - + conn.Open(); cmd.ExecuteNonQuery(); } sql = "INSERT INTO [landaccesslist] ([LandUUID],[AccessUUID],[Flags]) VALUES (@LandUUID,@AccessUUID,@Flags)"; - using (AutoClosingSqlCommand cmd = _Database.Query(sql)) + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) { + conn.Open(); foreach (ParcelManager.ParcelAccessEntry parcelAccessEntry in parcel.LandData.ParcelAccessList) { cmd.Parameters.AddRange(CreateLandAccessParameters(parcelAccessEntry, parcel.RegionUUID)); @@ -659,15 +674,20 @@ VALUES /// UUID of landobject public void RemoveLandObject(UUID globalID) { - using (AutoClosingSqlCommand cmd = _Database.Query("delete from land where UUID=@UUID")) + string sql = "delete from land where UUID=@UUID"; + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) { cmd.Parameters.Add(_Database.CreateParameter("@UUID", globalID)); + conn.Open(); cmd.ExecuteNonQuery(); } - - using (AutoClosingSqlCommand cmd = _Database.Query("delete from landaccesslist where LandUUID=@UUID")) + sql = "delete from landaccesslist where LandUUID=@UUID"; + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) { cmd.Parameters.Add(_Database.CreateParameter("@UUID", globalID)); + conn.Open(); cmd.ExecuteNonQuery(); } } @@ -681,9 +701,11 @@ VALUES { string sql = "select * from regionsettings where regionUUID = @regionUUID"; RegionSettings regionSettings; - using (AutoClosingSqlCommand cmd = _Database.Query(sql)) + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) { cmd.Parameters.Add(_Database.CreateParameter("@regionUUID", regionUUID)); + conn.Open(); using (SqlDataReader reader = cmd.ExecuteReader()) { if (reader.Read()) @@ -715,9 +737,12 @@ VALUES { //Little check if regionUUID already exist in DB string regionUUID; - using (AutoClosingSqlCommand cmd = _Database.Query("SELECT regionUUID FROM regionsettings WHERE regionUUID = @regionUUID")) + string sql = "SELECT regionUUID FROM regionsettings WHERE regionUUID = @regionUUID"; + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) { cmd.Parameters.Add(_Database.CreateParameter("@regionUUID", regionSettings.RegionUUID)); + conn.Open(); regionUUID = cmd.ExecuteScalar().ToString(); } @@ -728,8 +753,8 @@ VALUES else { //This method only updates region settings!!! First call LoadRegionSettings to create new region settings in DB - string sql = - @"UPDATE [regionsettings] SET [block_terraform] = @block_terraform ,[block_fly] = @block_fly ,[allow_damage] = @allow_damage + sql = + @"UPDATE [regionsettings] SET [block_terraform] = @block_terraform ,[block_fly] = @block_fly ,[allow_damage] = @allow_damage ,[restrict_pushing] = @restrict_pushing ,[allow_land_resell] = @allow_land_resell ,[allow_land_join_divide] = @allow_land_join_divide ,[block_show_in_search] = @block_show_in_search ,[agent_limit] = @agent_limit ,[object_bonus] = @object_bonus ,[maturity] = @maturity ,[disable_scripts] = @disable_scripts ,[disable_collisions] = @disable_collisions ,[disable_physics] = @disable_physics @@ -741,10 +766,11 @@ VALUES ,[covenant] = @covenant , [sunvectorx] = @sunvectorx, [sunvectory] = @sunvectory, [sunvectorz] = @sunvectorz, [Sandbox] = @Sandbox, [loaded_creation_datetime] = @loaded_creation_datetime, [loaded_creation_id] = @loaded_creation_id WHERE [regionUUID] = @regionUUID"; - using (AutoClosingSqlCommand cmd = _Database.Query(sql)) + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) { cmd.Parameters.AddRange(CreateRegionSettingParameters(regionSettings)); - + conn.Open(); cmd.ExecuteNonQuery(); } } @@ -801,9 +827,11 @@ VALUES @elevation_2_ne,@elevation_1_se,@elevation_2_se,@elevation_1_sw,@elevation_2_sw,@water_height,@terrain_raise_limit, @terrain_lower_limit,@use_estate_sun,@fixed_sun,@sun_position,@covenant,@sunvectorx,@sunvectory, @sunvectorz, @Sandbox, @loaded_creation_datetime, @loaded_creation_id)"; - using (AutoClosingSqlCommand cmd = _Database.Query(sql)) + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) { cmd.Parameters.AddRange(CreateRegionSettingParameters(regionSettings)); + conn.Open(); cmd.ExecuteNonQuery(); } } @@ -907,15 +935,15 @@ VALUES newData.PassHours = Convert.ToSingle(row["PassHours"]); newData.PassPrice = Convert.ToInt32(row["PassPrice"]); -// UUID authedbuyer; -// UUID snapshotID; -// -// if (UUID.TryParse((string)row["AuthBuyerID"], out authedbuyer)) -// newData.AuthBuyerID = authedbuyer; -// -// if (UUID.TryParse((string)row["SnapshotUUID"], out snapshotID)) -// newData.SnapshotID = snapshotID; - newData.AuthBuyerID = new UUID((Guid) row["AuthBuyerID"]); + // UUID authedbuyer; + // UUID snapshotID; + // + // if (UUID.TryParse((string)row["AuthBuyerID"], out authedbuyer)) + // newData.AuthBuyerID = authedbuyer; + // + // if (UUID.TryParse((string)row["SnapshotUUID"], out snapshotID)) + // newData.SnapshotID = snapshotID; + newData.AuthBuyerID = new UUID((Guid)row["AuthBuyerID"]); newData.SnapshotID = new UUID((Guid)row["SnapshotUUID"]); newData.OtherCleanTime = Convert.ToInt32(row["OtherCleanTime"]); @@ -1184,7 +1212,7 @@ VALUES #endregion #region Create parameters methods - + /// /// Creates the prim inventory parameters. /// @@ -1468,7 +1496,7 @@ VALUES parameters.Add(_Database.CreateParameter("CollisionSound", prim.CollisionSound)); parameters.Add(_Database.CreateParameter("CollisionSoundVolume", prim.CollisionSoundVolume)); - if (prim.PassTouches) + if (prim.PassTouches) parameters.Add(_Database.CreateParameter("PassTouches", 1)); else parameters.Add(_Database.CreateParameter("PassTouches", 0)); @@ -1523,7 +1551,7 @@ VALUES return parameters.ToArray(); } - + #endregion #endregion diff --git a/OpenSim/Data/MSSQL/MSSQLManager.cs b/OpenSim/Data/MSSQL/MSSQLManager.cs index 3d7a768..4309b42 100644 --- a/OpenSim/Data/MSSQL/MSSQLManager.cs +++ b/OpenSim/Data/MSSQL/MSSQLManager.cs @@ -46,22 +46,7 @@ namespace OpenSim.Data.MSSQL /// /// Connection string for ADO.net /// - private readonly string connectionString; - - public MSSQLManager(string dataSource, string initialCatalog, string persistSecurityInfo, string userId, - string password) - { - SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(); - - builder.DataSource = dataSource; - builder.InitialCatalog = initialCatalog; - builder.PersistSecurityInfo = Convert.ToBoolean(persistSecurityInfo); - builder.UserID = userId; - builder.Password = password; - builder.ApplicationName = Assembly.GetEntryAssembly().Location; - - connectionString = builder.ToString(); - } + private readonly string connectionString; /// /// Initialize the manager and set the connectionstring @@ -72,94 +57,6 @@ namespace OpenSim.Data.MSSQL connectionString = connection; } - public SqlConnection DatabaseConnection() - { - SqlConnection conn = new SqlConnection(connectionString); - - //TODO is this good??? Opening connection here - conn.Open(); - - return conn; - } - - #region Obsolete functions, can be removed! - - /// - /// - /// - /// - /// - /// - [Obsolete("Do not use!")] - protected static void createCol(DataTable dt, string name, Type type) - { - DataColumn col = new DataColumn(name, type); - dt.Columns.Add(col); - } - - /// - /// Define Table function - /// - /// - /// -/* - [Obsolete("Do not use!")] - protected static string defineTable(DataTable dt) - { - string sql = "create table " + dt.TableName + "("; - string subsql = String.Empty; - foreach (DataColumn col in dt.Columns) - { - if (subsql.Length > 0) - { - // a map function would rock so much here - subsql += ",\n"; - } - - subsql += col.ColumnName + " " + SqlType(col.DataType); - if (col == dt.PrimaryKey[0]) - { - subsql += " primary key"; - } - } - sql += subsql; - sql += ")"; - return sql; - } -*/ - - #endregion - - /// - /// Type conversion function - /// - /// a type - /// a sqltype - /// this is something we'll need to implement for each db slightly differently. -/* - [Obsolete("Used by a obsolete methods")] - public static string SqlType(Type type) - { - if (type == typeof(String)) - { - return "varchar(255)"; - } - if (type == typeof(Int32)) - { - return "integer"; - } - if (type == typeof(Double)) - { - return "float"; - } - if (type == typeof(Byte[])) - { - return "image"; - } - return "varchar(255)"; - } -*/ - /// /// Type conversion to a SQLDbType functions /// @@ -286,134 +183,20 @@ namespace OpenSim.Data.MSSQL private static readonly Dictionary emptyDictionary = new Dictionary(); /// - /// Run a query and return a sql db command - /// - /// The SQL query. - /// - internal AutoClosingSqlCommand Query(string sql) - { - return Query(sql, emptyDictionary); - } - - /// - /// Runs a query with protection against SQL Injection by using parameterised input. - /// - /// The SQL string - replace any variables such as WHERE x = "y" with WHERE x = @y - /// The parameters - index so that @y is indexed as 'y' - /// A Sql DB Command - internal AutoClosingSqlCommand Query(string sql, Dictionary parameters) - { - SqlCommand dbcommand = DatabaseConnection().CreateCommand(); - dbcommand.CommandText = sql; - foreach (KeyValuePair param in parameters) - { - dbcommand.Parameters.AddWithValue(param.Key, param.Value); - } - - return new AutoClosingSqlCommand(dbcommand); - } - - /// - /// Runs a query with protection against SQL Injection by using parameterised input. - /// - /// The SQL string - replace any variables such as WHERE x = "y" with WHERE x = @y - /// A parameter - use createparameter to create parameter - /// - internal AutoClosingSqlCommand Query(string sql, SqlParameter sqlParameter) - { - SqlCommand dbcommand = DatabaseConnection().CreateCommand(); - dbcommand.CommandText = sql; - dbcommand.Parameters.Add(sqlParameter); - - return new AutoClosingSqlCommand(dbcommand); - } - - /// /// Checks if we need to do some migrations to the database /// /// migrationStore. public void CheckMigration(string migrationStore) { - using (SqlConnection connection = DatabaseConnection()) + using (SqlConnection connection = new SqlConnection(connectionString)) { + connection.Open(); Assembly assem = GetType().Assembly; MSSQLMigration migration = new MSSQLMigration(connection, assem, migrationStore); migration.Update(); - - connection.Close(); } - } - - #region Old Testtable functions - - /// - /// Execute a SQL statement stored in a resource, as a string - /// - /// the ressource string - public void ExecuteResourceSql(string name) - { - using (IDbCommand cmd = Query(getResourceString(name), new Dictionary())) - { - cmd.ExecuteNonQuery(); - } - } - - /// - /// Given a list of tables, return the version of the tables, as seen in the database - /// - /// - public void GetTableVersion(Dictionary tableList) - { - Dictionary param = new Dictionary(); - param["dbname"] = new SqlConnectionStringBuilder(connectionString).InitialCatalog; - - using (IDbCommand tablesCmd = - Query("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_CATALOG=@dbname", param)) - using (IDataReader tables = tablesCmd.ExecuteReader()) - { - while (tables.Read()) - { - try - { - string tableName = (string)tables["TABLE_NAME"]; - if (tableList.ContainsKey(tableName)) - tableList[tableName] = tableName; - } - catch (Exception e) - { - m_log.Error(e.ToString()); - } - } - tables.Close(); - } - - } - - /// - /// - /// - /// - /// - private string getResourceString(string name) - { - Assembly assem = GetType().Assembly; - string[] names = assem.GetManifestResourceNames(); - - foreach (string s in names) - if (s.EndsWith(name)) - using (Stream resource = assem.GetManifestResourceStream(s)) - { - using (StreamReader resourceReader = new StreamReader(resource)) - { - string resourceString = resourceReader.ReadToEnd(); - return resourceString; - } - } - throw new Exception(string.Format("Resource '{0}' was not found", name)); - } - - #endregion + } /// /// Returns the version of this DB provider diff --git a/OpenSim/Data/MSSQL/MSSQLPresenceData.cs b/OpenSim/Data/MSSQL/MSSQLPresenceData.cs new file mode 100644 index 0000000..5a4ad3a --- /dev/null +++ b/OpenSim/Data/MSSQL/MSSQLPresenceData.cs @@ -0,0 +1,170 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Data; +using System.Reflection; +using System.Threading; +using log4net; +using OpenMetaverse; +using OpenSim.Framework; +using System.Data.SqlClient; + +namespace OpenSim.Data.MSSQL +{ + /// + /// A MySQL Interface for the Presence Server + /// + public class MSSQLPresenceData : MSSQLGenericTableHandler, + IPresenceData + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + public MSSQLPresenceData(string connectionString, string realm) : + base(connectionString, realm, "Presence") + { + } + + public PresenceData Get(UUID sessionID) + { + PresenceData[] ret = Get("SessionID", + sessionID.ToString()); + + if (ret.Length == 0) + return null; + + return ret[0]; + } + + public void LogoutRegionAgents(UUID regionID) + { + using (SqlConnection conn = new SqlConnection(m_ConnectionString)) + using (SqlCommand cmd = new SqlCommand()) + { + + cmd.CommandText = String.Format("UPDATE {0} SET Online='false' WHERE [RegionID]=@RegionID", m_Realm); + + cmd.Parameters.Add(m_database.CreateParameter("@RegionID", regionID.ToString())); + cmd.Connection = conn; + conn.Open(); + cmd.ExecuteNonQuery(); + } + } + + public bool ReportAgent(UUID sessionID, UUID regionID, string position, + string lookAt) + { + PresenceData[] pd = Get("SessionID", sessionID.ToString()); + if (pd.Length == 0) + return false; + + using (SqlConnection conn = new SqlConnection(m_ConnectionString)) + using (SqlCommand cmd = new SqlCommand()) + { + + cmd.CommandText = String.Format(@"UPDATE {0} SET + [RegionID] = @RegionID, + [Position] = @Position, + [LookAt] = @LookAt, + [Online] = 'true' + WHERE [SessionID] = @SessionID", m_Realm); + + cmd.Parameters.Add(m_database.CreateParameter("@SessionID", sessionID.ToString())); + cmd.Parameters.Add(m_database.CreateParameter("@RegionID", regionID.ToString())); + cmd.Parameters.Add(m_database.CreateParameter("@Position", position.ToString())); + cmd.Parameters.Add(m_database.CreateParameter("@LookAt", lookAt.ToString())); + cmd.Connection = conn; + conn.Open(); + if (cmd.ExecuteNonQuery() == 0) + return false; + } + return true; + } + + public bool SetHomeLocation(string userID, UUID regionID, Vector3 position, Vector3 lookAt) + { + PresenceData[] pd = Get("UserID", userID); + if (pd.Length == 0) + return false; + + using (SqlConnection conn = new SqlConnection(m_ConnectionString)) + using (SqlCommand cmd = new SqlCommand()) + { + + cmd.CommandText = String.Format(@"UPDATE {0} SET + [HomeRegionID] = @HomeRegionID, + [HomePosition] = @HomePosition, + [HomeLookAt] = @HomeLookAt + WHERE [UserID] = @UserID", m_Realm); + + cmd.Parameters.Add(m_database.CreateParameter("@UserID", userID)); + cmd.Parameters.Add(m_database.CreateParameter("@HomeRegionID", regionID.ToString())); + cmd.Parameters.Add(m_database.CreateParameter("@HomePosition", position)); + cmd.Parameters.Add(m_database.CreateParameter("@HomeLookAt", lookAt)); + cmd.Connection = conn; + conn.Open(); + if (cmd.ExecuteNonQuery() == 0) + return false; + } + return true; + } + + public void Prune(string userID) + { + using (SqlConnection conn = new SqlConnection(m_ConnectionString)) + using (SqlCommand cmd = new SqlCommand()) + { + cmd.CommandText = String.Format("SELECT * from {0} WHERE [UserID] = @UserID", m_Realm); + + cmd.Parameters.Add(m_database.CreateParameter("@UserID", userID)); + cmd.Connection = conn; + conn.Open(); + + using (SqlDataReader reader = cmd.ExecuteReader()) + { + List deleteSessions = new List(); + int online = 0; + + while (reader.Read()) + { + if (bool.Parse(reader["Online"].ToString())) + online++; + else + deleteSessions.Add(new UUID(reader["SessionID"].ToString())); + } + + if (online == 0 && deleteSessions.Count > 0) + deleteSessions.RemoveAt(0); + + foreach (UUID s in deleteSessions) + Delete("SessionID", s.ToString()); + } + } + } + } +} diff --git a/OpenSim/Data/MSSQL/MSSQLRegionData.cs b/OpenSim/Data/MSSQL/MSSQLRegionData.cs index fbfb78e..66c3f81 100644 --- a/OpenSim/Data/MSSQL/MSSQLRegionData.cs +++ b/OpenSim/Data/MSSQL/MSSQLRegionData.cs @@ -129,10 +129,10 @@ namespace OpenSim.Data.MSSQL using (SqlConnection conn = new SqlConnection(m_ConnectionString)) using (SqlCommand cmd = new SqlCommand(sql, conn)) { - cmd.Parameters.Add(m_database.CreateParameter("@startX", startX.ToString())); - cmd.Parameters.Add(m_database.CreateParameter("@startY", startY.ToString())); - cmd.Parameters.Add(m_database.CreateParameter("@endX", endX.ToString())); - cmd.Parameters.Add(m_database.CreateParameter("@endY", endY.ToString())); + cmd.Parameters.Add(m_database.CreateParameter("@startX", startX)); + cmd.Parameters.Add(m_database.CreateParameter("@startY", startY)); + cmd.Parameters.Add(m_database.CreateParameter("@endX", endX)); + cmd.Parameters.Add(m_database.CreateParameter("@endY", endY)); cmd.Parameters.Add(m_database.CreateParameter("@scopeID", scopeID)); conn.Open(); return RunCommand(cmd); @@ -310,12 +310,34 @@ namespace OpenSim.Data.MSSQL public List GetDefaultRegions(UUID scopeID) { - return null; + string sql = "SELECT * FROM [" + m_Realm + "] WHERE (flags & 1) <> 0"; + if (scopeID != UUID.Zero) + sql += " AND ScopeID = @scopeID"; + + using (SqlConnection conn = new SqlConnection(m_ConnectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.Add(m_database.CreateParameter("@scopeID", scopeID)); + conn.Open(); + return RunCommand(cmd); + } + } public List GetFallbackRegions(UUID scopeID, int x, int y) { - return null; + string sql = "SELECT * FROM [" + m_Realm + "] WHERE (flags & 2) <> 0"; + if (scopeID != UUID.Zero) + sql += " AND ScopeID = @scopeID"; + + using (SqlConnection conn = new SqlConnection(m_ConnectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.Add(m_database.CreateParameter("@scopeID", scopeID)); + conn.Open(); + // TODO: distance-sort results + return RunCommand(cmd); + } } } } diff --git a/OpenSim/Data/MSSQL/MSSQLUserAccountData.cs b/OpenSim/Data/MSSQL/MSSQLUserAccountData.cs index 01c64dc..9f18e5e 100644 --- a/OpenSim/Data/MSSQL/MSSQLUserAccountData.cs +++ b/OpenSim/Data/MSSQL/MSSQLUserAccountData.cs @@ -36,168 +36,207 @@ using System.Text; namespace OpenSim.Data.MSSQL { - public class MSSQLUserAccountData : IUserAccountData + public class MSSQLUserAccountData : MSSQLGenericTableHandler,IUserAccountData { - private string m_Realm; - private List m_ColumnNames = null; - private string m_ConnectionString; - private MSSQLManager m_database; - - public MSSQLUserAccountData(string connectionString, string realm) - { - m_Realm = realm; - m_ConnectionString = connectionString; - m_database = new MSSQLManager(connectionString); - - using (SqlConnection conn = new SqlConnection(m_ConnectionString)) - { - conn.Open(); - Migration m = new Migration(conn, GetType().Assembly, "UserStore"); - m.Update(); - } - } - - public List Query(UUID principalID, UUID scopeID, string query) + public MSSQLUserAccountData(string connectionString, string realm) : + base(connectionString, realm, "UserAccount") { - return null; } + //private string m_Realm; + //private List m_ColumnNames = null; + //private MSSQLManager m_database; + + //public MSSQLUserAccountData(string connectionString, string realm) + //{ + // m_Realm = realm; + // m_ConnectionString = connectionString; + // m_database = new MSSQLManager(connectionString); + + // using (SqlConnection conn = new SqlConnection(m_ConnectionString)) + // { + // conn.Open(); + // Migration m = new Migration(conn, GetType().Assembly, "UserStore"); + // m.Update(); + // } + //} + + //public List Query(UUID principalID, UUID scopeID, string query) + //{ + // return null; + //} + + //public UserAccountData Get(UUID principalID, UUID scopeID) + //{ + // UserAccountData ret = new UserAccountData(); + // ret.Data = new Dictionary(); + + // string sql = string.Format("select * from {0} where UUID = @principalID", m_Realm); + // if (scopeID != UUID.Zero) + // sql += " and ScopeID = @scopeID"; + + // using (SqlConnection conn = new SqlConnection(m_ConnectionString)) + // using (SqlCommand cmd = new SqlCommand(sql, conn)) + // { + // cmd.Parameters.Add(m_database.CreateParameter("@principalID", principalID)); + // cmd.Parameters.Add(m_database.CreateParameter("@scopeID", scopeID)); + + // conn.Open(); + // using (SqlDataReader result = cmd.ExecuteReader()) + // { + // if (result.Read()) + // { + // ret.PrincipalID = principalID; + // UUID scope; + // UUID.TryParse(result["ScopeID"].ToString(), out scope); + // ret.ScopeID = scope; + + // if (m_ColumnNames == null) + // { + // m_ColumnNames = new List(); + + // DataTable schemaTable = result.GetSchemaTable(); + // foreach (DataRow row in schemaTable.Rows) + // m_ColumnNames.Add(row["ColumnName"].ToString()); + // } + + // foreach (string s in m_ColumnNames) + // { + // if (s == "UUID") + // continue; + // if (s == "ScopeID") + // continue; + + // ret.Data[s] = result[s].ToString(); + // } + // return ret; + // } + // } + // } + // return null; + //} + + //public bool Store(UserAccountData data) + //{ + // if (data.Data.ContainsKey("UUID")) + // data.Data.Remove("UUID"); + // if (data.Data.ContainsKey("ScopeID")) + // data.Data.Remove("ScopeID"); + + // string[] fields = new List(data.Data.Keys).ToArray(); + + // using (SqlConnection conn = new SqlConnection(m_ConnectionString)) + // using (SqlCommand cmd = new SqlCommand()) + // { + // StringBuilder updateBuilder = new StringBuilder(); + // updateBuilder.AppendFormat("update {0} set ", m_Realm); + // bool first = true; + // foreach (string field in fields) + // { + // if (!first) + // updateBuilder.Append(", "); + // updateBuilder.AppendFormat("{0} = @{0}", field); + + // first = false; + // cmd.Parameters.Add(m_database.CreateParameter("@" + field, data.Data[field])); + // } + + // updateBuilder.Append(" where UUID = @principalID"); + + // if (data.ScopeID != UUID.Zero) + // updateBuilder.Append(" and ScopeID = @scopeID"); + + // cmd.CommandText = updateBuilder.ToString(); + // cmd.Connection = conn; + // cmd.Parameters.Add(m_database.CreateParameter("@principalID", data.PrincipalID)); + // cmd.Parameters.Add(m_database.CreateParameter("@scopeID", data.ScopeID)); + // conn.Open(); + + // if (cmd.ExecuteNonQuery() < 1) + // { + // StringBuilder insertBuilder = new StringBuilder(); + // insertBuilder.AppendFormat("insert into {0} (UUID, ScopeID, ", m_Realm); + // insertBuilder.Append(String.Join(", ", fields)); + // insertBuilder.Append(") values (@principalID, @scopeID, @"); + // insertBuilder.Append(String.Join(", @", fields)); + // insertBuilder.Append(")"); + + // cmd.CommandText = insertBuilder.ToString(); + + // if (cmd.ExecuteNonQuery() < 1) + // { + // return false; + // } + // } + // } + // return true; + //} + + //public bool Store(UserAccountData data, UUID principalID, string token) + //{ + // return false; + //} + + //public bool SetDataItem(UUID principalID, string item, string value) + //{ + // string sql = string.Format("update {0} set {1} = @{1} where UUID = @UUID", m_Realm, item); + // using (SqlConnection conn = new SqlConnection(m_ConnectionString)) + // using (SqlCommand cmd = new SqlCommand(sql, conn)) + // { + // cmd.Parameters.Add(m_database.CreateParameter("@" + item, value)); + // cmd.Parameters.Add(m_database.CreateParameter("@UUID", principalID)); + + // conn.Open(); + + // if (cmd.ExecuteNonQuery() > 0) + // return true; + // } + // return false; + //} + + //public UserAccountData[] Get(string[] keys, string[] vals) + //{ + // return null; + //} - public UserAccountData Get(UUID principalID, UUID scopeID) + public UserAccountData[] GetUsers(UUID scopeID, string query) { - UserAccountData ret = new UserAccountData(); - ret.Data = new Dictionary(); + string[] words = query.Split(new char[] { ' ' }); - string sql = string.Format("select * from {0} where UUID = @principalID", m_Realm); - if (scopeID != UUID.Zero) - sql += " and ScopeID = @scopeID"; - - using (SqlConnection conn = new SqlConnection(m_ConnectionString)) - using (SqlCommand cmd = new SqlCommand(sql, conn)) + for (int i = 0; i < words.Length; i++) { - cmd.Parameters.Add(m_database.CreateParameter("@principalID", principalID)); - cmd.Parameters.Add(m_database.CreateParameter("@scopeID", scopeID)); - - conn.Open(); - using (SqlDataReader result = cmd.ExecuteReader()) + if (words[i].Length < 3) { - if (result.Read()) - { - ret.PrincipalID = principalID; - UUID scope; - UUID.TryParse(result["ScopeID"].ToString(), out scope); - ret.ScopeID = scope; - - if (m_ColumnNames == null) - { - m_ColumnNames = new List(); - - DataTable schemaTable = result.GetSchemaTable(); - foreach (DataRow row in schemaTable.Rows) - m_ColumnNames.Add(row["ColumnName"].ToString()); - } - - foreach (string s in m_ColumnNames) - { - if (s == "UUID") - continue; - if (s == "ScopeID") - continue; - - ret.Data[s] = result[s].ToString(); - } - return ret; - } + if (i != words.Length - 1) + Array.Copy(words, i + 1, words, i, words.Length - i - 1); + Array.Resize(ref words, words.Length - 1); } } - return null; - } - public bool Store(UserAccountData data) - { - if (data.Data.ContainsKey("UUID")) - data.Data.Remove("UUID"); - if (data.Data.ContainsKey("ScopeID")) - data.Data.Remove("ScopeID"); + if (words.Length == 0) + return new UserAccountData[0]; - string[] fields = new List(data.Data.Keys).ToArray(); + if (words.Length > 2) + return new UserAccountData[0]; using (SqlConnection conn = new SqlConnection(m_ConnectionString)) using (SqlCommand cmd = new SqlCommand()) { - StringBuilder updateBuilder = new StringBuilder(); - updateBuilder.AppendFormat("update {0} set ", m_Realm); - bool first = true; - foreach (string field in fields) + if (words.Length == 1) { - if (!first) - updateBuilder.Append(", "); - updateBuilder.AppendFormat("{0} = @{0}", field); - - first = false; - cmd.Parameters.Add(m_database.CreateParameter("@" + field, data.Data[field])); + cmd.CommandText = String.Format("select * from {0} where ([ScopeID]=@ScopeID or [ScopeID]='00000000-0000-0000-0000-000000000000') and ([FirstName] like @search or [LastName] like @search)", m_Realm); + cmd.Parameters.Add(m_database.CreateParameter("@scopeID", scopeID)); + cmd.Parameters.Add(m_database.CreateParameter("@search", "%" + words[0] + "%")); } - - updateBuilder.Append(" where UUID = @principalID"); - - if (data.ScopeID != UUID.Zero) - updateBuilder.Append(" and ScopeID = @scopeID"); - - cmd.CommandText = updateBuilder.ToString(); - cmd.Connection = conn; - cmd.Parameters.Add(m_database.CreateParameter("@principalID", data.PrincipalID)); - cmd.Parameters.Add(m_database.CreateParameter("@scopeID", data.ScopeID)); - conn.Open(); - - if (cmd.ExecuteNonQuery() < 1) + else { - StringBuilder insertBuilder = new StringBuilder(); - insertBuilder.AppendFormat("insert into {0} (UUID, ScopeID, ", m_Realm); - insertBuilder.Append(String.Join(", ", fields)); - insertBuilder.Append(") values (@principalID, @scopeID, @"); - insertBuilder.Append(String.Join(", @", fields)); - insertBuilder.Append(")"); - - cmd.CommandText = insertBuilder.ToString(); - - if (cmd.ExecuteNonQuery() < 1) - { - return false; - } + cmd.CommandText = String.Format("select * from {0} where ([ScopeID]=@ScopeID or [ScopeID]='00000000-0000-0000-0000-000000000000') and ([FirstName] like @searchFirst or [LastName] like @searchLast)", m_Realm); + cmd.Parameters.Add(m_database.CreateParameter("@searchFirst", "%" + words[0] + "%")); + cmd.Parameters.Add(m_database.CreateParameter("@searchLast", "%" + words[1] + "%")); + cmd.Parameters.Add(m_database.CreateParameter("@ScopeID", scopeID.ToString())); } - } - return true; - } - - public bool Store(UserAccountData data, UUID principalID, string token) - { - return false; - } - - public bool SetDataItem(UUID principalID, string item, string value) - { - string sql = string.Format("update {0} set {1} = @{1} where UUID = @UUID", m_Realm, item); - using (SqlConnection conn = new SqlConnection(m_ConnectionString)) - using (SqlCommand cmd = new SqlCommand(sql, conn)) - { - cmd.Parameters.Add(m_database.CreateParameter("@" + item, value)); - cmd.Parameters.Add(m_database.CreateParameter("@UUID", principalID)); - - conn.Open(); - if (cmd.ExecuteNonQuery() > 0) - return true; + return DoQuery(cmd); } - return false; - } - - public UserAccountData[] Get(string[] keys, string[] vals) - { - return null; - } - - public UserAccountData[] GetUsers(UUID scopeID, string query) - { - return null; } } } diff --git a/OpenSim/Data/MSSQL/MSSQLUserData.cs b/OpenSim/Data/MSSQL/MSSQLUserData.cs new file mode 100644 index 0000000..6bdb559 --- /dev/null +++ b/OpenSim/Data/MSSQL/MSSQLUserData.cs @@ -0,0 +1,1238 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using System.Data.SqlClient; +using System.Reflection; +using log4net; +using OpenMetaverse; +using OpenSim.Framework; + +namespace OpenSim.Data.MSSQL +{ + /// + /// A database interface class to a user profile storage system + /// + public class MSSQLUserData : UserDataBase + { + private const string _migrationStore = "UserStore"; + + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// Database manager for MSSQL + /// + public MSSQLManager database; + private string m_connectionString; + + private const string m_agentsTableName = "agents"; + private const string m_usersTableName = "users"; + private const string m_userFriendsTableName = "userfriends"; + + // [Obsolete("Cannot be default-initialized!")] + override public void Initialise() + { + m_log.Info("[MSSQLUserData]: " + Name + " cannot be default-initialized!"); + throw new PluginNotInitialisedException(Name); + } + + /// + /// Loads and initialises the MSSQL storage plugin + /// + /// connectionstring + /// use mssql_connection.ini + override public void Initialise(string connect) + { + m_connectionString = connect; + database = new MSSQLManager(connect); + + + //Check migration on DB + database.CheckMigration(_migrationStore); + } + + /// + /// Releases unmanaged and - optionally - managed resources + /// + override public void Dispose() { } + + #region User table methods + + /// + /// Searches the database for a specified user profile by name components + /// + /// The first part of the account name + /// The second part of the account name + /// A user profile + override public UserProfileData GetUserByName(string user, string last) + { + string sql = string.Format(@"SELECT * FROM {0} + WHERE username = @first AND lastname = @second", m_usersTableName); + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.Add(database.CreateParameter("first", user)); + cmd.Parameters.Add(database.CreateParameter("second", last)); + try + { + conn.Open(); + using (SqlDataReader reader = cmd.ExecuteReader()) + { + return ReadUserRow(reader); + } + } + catch (Exception e) + { + m_log.ErrorFormat("[USER DB] Error getting user profile for {0} {1}: {2}", user, last, e.Message); + return null; + } + } + } + + /// + /// See IUserDataPlugin + /// + /// + /// + override public UserProfileData GetUserByUUID(UUID uuid) + { + string sql = string.Format("SELECT * FROM {0} WHERE UUID = @uuid", m_usersTableName); + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.Add(database.CreateParameter("uuid", uuid)); + conn.Open(); + try + { + using (SqlDataReader reader = cmd.ExecuteReader()) + { + return ReadUserRow(reader); + } + } + catch (Exception e) + { + m_log.ErrorFormat("[USER DB] Error getting user profile by UUID {0}, error: {1}", uuid, e.Message); + return null; + } + } + } + + + /// + /// Creates a new users profile + /// + /// The user profile to create + override public void AddNewUserProfile(UserProfileData user) + { + try + { + InsertUserRow(user.ID, user.FirstName, user.SurName, user.Email, user.PasswordHash, user.PasswordSalt, + user.HomeRegion, user.HomeLocation.X, user.HomeLocation.Y, + user.HomeLocation.Z, + user.HomeLookAt.X, user.HomeLookAt.Y, user.HomeLookAt.Z, user.Created, + user.LastLogin, user.UserInventoryURI, user.UserAssetURI, + user.CanDoMask, user.WantDoMask, + user.AboutText, user.FirstLifeAboutText, user.Image, + user.FirstLifeImage, user.WebLoginKey, user.HomeRegionID, + user.GodLevel, user.UserFlags, user.CustomType, user.Partner); + } + catch (Exception e) + { + m_log.ErrorFormat("[USER DB] Error adding new profile, error: {0}", e.Message); + } + } + + /// + /// update a user profile + /// + /// the profile to update + /// + override public bool UpdateUserProfile(UserProfileData user) + { + string sql = string.Format(@"UPDATE {0} + SET UUID = @uuid, + username = @username, + lastname = @lastname, + email = @email, + passwordHash = @passwordHash, + passwordSalt = @passwordSalt, + homeRegion = @homeRegion, + homeLocationX = @homeLocationX, + homeLocationY = @homeLocationY, + homeLocationZ = @homeLocationZ, + homeLookAtX = @homeLookAtX, + homeLookAtY = @homeLookAtY, + homeLookAtZ = @homeLookAtZ, + created = @created, + lastLogin = @lastLogin, + userInventoryURI = @userInventoryURI, + userAssetURI = @userAssetURI, + profileCanDoMask = @profileCanDoMask, + profileWantDoMask = @profileWantDoMask, + profileAboutText = @profileAboutText, + profileFirstText = @profileFirstText, + profileImage = @profileImage, + profileFirstImage = @profileFirstImage, + webLoginKey = @webLoginKey, + homeRegionID = @homeRegionID, + userFlags = @userFlags, + godLevel = @godLevel, + customType = @customType, + partner = @partner WHERE UUID = @keyUUUID;", m_usersTableName); + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand command = new SqlCommand(sql, conn)) + { + command.Parameters.Add(database.CreateParameter("uuid", user.ID)); + command.Parameters.Add(database.CreateParameter("username", user.FirstName)); + command.Parameters.Add(database.CreateParameter("lastname", user.SurName)); + command.Parameters.Add(database.CreateParameter("email", user.Email)); + command.Parameters.Add(database.CreateParameter("passwordHash", user.PasswordHash)); + command.Parameters.Add(database.CreateParameter("passwordSalt", user.PasswordSalt)); + command.Parameters.Add(database.CreateParameter("homeRegion", user.HomeRegion)); + command.Parameters.Add(database.CreateParameter("homeLocationX", user.HomeLocation.X)); + command.Parameters.Add(database.CreateParameter("homeLocationY", user.HomeLocation.Y)); + command.Parameters.Add(database.CreateParameter("homeLocationZ", user.HomeLocation.Z)); + command.Parameters.Add(database.CreateParameter("homeLookAtX", user.HomeLookAt.X)); + command.Parameters.Add(database.CreateParameter("homeLookAtY", user.HomeLookAt.Y)); + command.Parameters.Add(database.CreateParameter("homeLookAtZ", user.HomeLookAt.Z)); + command.Parameters.Add(database.CreateParameter("created", user.Created)); + command.Parameters.Add(database.CreateParameter("lastLogin", user.LastLogin)); + command.Parameters.Add(database.CreateParameter("userInventoryURI", user.UserInventoryURI)); + command.Parameters.Add(database.CreateParameter("userAssetURI", user.UserAssetURI)); + command.Parameters.Add(database.CreateParameter("profileCanDoMask", user.CanDoMask)); + command.Parameters.Add(database.CreateParameter("profileWantDoMask", user.WantDoMask)); + command.Parameters.Add(database.CreateParameter("profileAboutText", user.AboutText)); + command.Parameters.Add(database.CreateParameter("profileFirstText", user.FirstLifeAboutText)); + command.Parameters.Add(database.CreateParameter("profileImage", user.Image)); + command.Parameters.Add(database.CreateParameter("profileFirstImage", user.FirstLifeImage)); + command.Parameters.Add(database.CreateParameter("webLoginKey", user.WebLoginKey)); + command.Parameters.Add(database.CreateParameter("homeRegionID", user.HomeRegionID)); + command.Parameters.Add(database.CreateParameter("userFlags", user.UserFlags)); + command.Parameters.Add(database.CreateParameter("godLevel", user.GodLevel)); + command.Parameters.Add(database.CreateParameter("customType", user.CustomType)); + command.Parameters.Add(database.CreateParameter("partner", user.Partner)); + command.Parameters.Add(database.CreateParameter("keyUUUID", user.ID)); + conn.Open(); + try + { + int affected = command.ExecuteNonQuery(); + return (affected != 0); + } + catch (Exception e) + { + m_log.ErrorFormat("[USER DB] Error updating profile, error: {0}", e.Message); + } + } + return false; + } + + #endregion + + #region Agent table methods + + /// + /// Returns a user session searching by name + /// + /// The account name + /// The users session + override public UserAgentData GetAgentByName(string name) + { + return GetAgentByName(name.Split(' ')[0], name.Split(' ')[1]); + } + + /// + /// Returns a user session by account name + /// + /// First part of the users account name + /// Second part of the users account name + /// The users session + override public UserAgentData GetAgentByName(string user, string last) + { + UserProfileData profile = GetUserByName(user, last); + return GetAgentByUUID(profile.ID); + } + + /// + /// Returns an agent session by account UUID + /// + /// The accounts UUID + /// The users session + override public UserAgentData GetAgentByUUID(UUID uuid) + { + string sql = string.Format("SELECT * FROM {0} WHERE UUID = @uuid", m_agentsTableName); + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.Add(database.CreateParameter("uuid", uuid)); + conn.Open(); + try + { + using (SqlDataReader reader = cmd.ExecuteReader()) + { + return readAgentRow(reader); + } + } + catch (Exception e) + { + m_log.ErrorFormat("[USER DB] Error updating agentdata by UUID, error: {0}", e.Message); + return null; + } + } + } + + /// + /// Creates a new agent + /// + /// The agent to create + override public void AddNewUserAgent(UserAgentData agent) + { + try + { + InsertUpdateAgentRow(agent); + } + catch (Exception e) + { + m_log.ErrorFormat("[USER DB] Error adding new agentdata, error: {0}", e.Message); + } + } + + #endregion + + #region User Friends List Data + + /// + /// Add a new friend in the friendlist + /// + /// UUID of the friendlist owner + /// Friend's UUID + /// Permission flag + override public void AddNewUserFriend(UUID friendlistowner, UUID friend, uint perms) + { + int dtvalue = Util.UnixTimeSinceEpoch(); + string sql = string.Format(@"INSERT INTO {0} + (ownerID,friendID,friendPerms,datetimestamp) + VALUES + (@ownerID,@friendID,@friendPerms,@datetimestamp)", m_userFriendsTableName); + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.Add(database.CreateParameter("ownerID", friendlistowner)); + cmd.Parameters.Add(database.CreateParameter("friendID", friend)); + cmd.Parameters.Add(database.CreateParameter("friendPerms", perms)); + cmd.Parameters.Add(database.CreateParameter("datetimestamp", dtvalue)); + conn.Open(); + cmd.ExecuteNonQuery(); + + try + { + sql = string.Format(@"INSERT INTO {0} + (ownerID,friendID,friendPerms,datetimestamp) + VALUES + (@friendID,@ownerID,@friendPerms,@datetimestamp)", m_userFriendsTableName); + cmd.CommandText = sql; + cmd.ExecuteNonQuery(); + } + catch (Exception e) + { + m_log.ErrorFormat("[USER DB] Error adding new userfriend, error: {0}", e.Message); + return; + } + } + } + + /// + /// Remove an friend from the friendlist + /// + /// UUID of the friendlist owner + /// UUID of the not-so-friendly user to remove from the list + override public void RemoveUserFriend(UUID friendlistowner, UUID friend) + { + string sql = string.Format(@"DELETE from {0} + WHERE ownerID = @ownerID + AND friendID = @friendID", m_userFriendsTableName); + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.Add(database.CreateParameter("@ownerID", friendlistowner)); + cmd.Parameters.Add(database.CreateParameter("@friendID", friend)); + cmd.ExecuteNonQuery(); + sql = string.Format(@"DELETE from {0} + WHERE ownerID = @friendID + AND friendID = @ownerID", m_userFriendsTableName); + cmd.CommandText = sql; + conn.Open(); + try + { + cmd.ExecuteNonQuery(); + } + catch (Exception e) + { + m_log.ErrorFormat("[USER DB] Error removing userfriend, error: {0}", e.Message); + } + } + } + + /// + /// Update friendlist permission flag for a friend + /// + /// UUID of the friendlist owner + /// UUID of the friend + /// new permission flag + override public void UpdateUserFriendPerms(UUID friendlistowner, UUID friend, uint perms) + { + string sql = string.Format(@"UPDATE {0} SET friendPerms = @friendPerms + WHERE ownerID = @ownerID + AND friendID = @friendID", m_userFriendsTableName); + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.Add(database.CreateParameter("@ownerID", friendlistowner)); + cmd.Parameters.Add(database.CreateParameter("@friendID", friend)); + cmd.Parameters.Add(database.CreateParameter("@friendPerms", perms)); + conn.Open(); + try + { + cmd.ExecuteNonQuery(); + } + catch (Exception e) + { + m_log.ErrorFormat("[USER DB] Error updating userfriend, error: {0}", e.Message); + } + } + } + + /// + /// Get (fetch?) the user's friendlist + /// + /// UUID of the friendlist owner + /// Friendlist list + override public List GetUserFriendList(UUID friendlistowner) + { + List friendList = new List(); + + //Left Join userfriends to itself + string sql = string.Format(@"SELECT a.ownerID, a.friendID, a.friendPerms, b.friendPerms AS ownerperms + FROM {0} as a, {0} as b + WHERE a.ownerID = @ownerID + AND b.ownerID = a.friendID + AND b.friendID = a.ownerID", m_userFriendsTableName); + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.Add(database.CreateParameter("@ownerID", friendlistowner)); + conn.Open(); + try + { + using (SqlDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + FriendListItem fli = new FriendListItem(); + fli.FriendListOwner = new UUID((Guid)reader["ownerID"]); + fli.Friend = new UUID((Guid)reader["friendID"]); + fli.FriendPerms = (uint)Convert.ToInt32(reader["friendPerms"]); + + // This is not a real column in the database table, it's a joined column from the opposite record + fli.FriendListOwnerPerms = (uint)Convert.ToInt32(reader["ownerperms"]); + friendList.Add(fli); + } + } + } + catch (Exception e) + { + m_log.ErrorFormat("[USER DB] Error updating userfriend, error: {0}", e.Message); + } + } + return friendList; + } + + override public Dictionary GetFriendRegionInfos(List uuids) + { + Dictionary infos = new Dictionary(); + try + { + foreach (UUID uuid in uuids) + { + string sql = string.Format(@"SELECT agentOnline,currentHandle + FROM {0} WHERE UUID = @uuid", m_agentsTableName); + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + + cmd.Parameters.Add(database.CreateParameter("@uuid", uuid)); + conn.Open(); + using (SqlDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + FriendRegionInfo fri = new FriendRegionInfo(); + fri.isOnline = (byte)reader["agentOnline"] != 0; + fri.regionHandle = Convert.ToUInt64(reader["currentHandle"].ToString()); + + infos[uuid] = fri; + } + } + } + } + } + catch (Exception e) + { + m_log.Warn("[MSSQL]: Got exception on trying to find friends regions:", e); + } + + return infos; + } + #endregion + + #region Money functions (not used) + + /// + /// Performs a money transfer request between two accounts + /// + /// The senders account ID + /// The receivers account ID + /// The amount to transfer + /// false + override public bool MoneyTransferRequest(UUID from, UUID to, uint amount) + { + return false; + } + + /// + /// Performs an inventory transfer request between two accounts + /// + /// TODO: Move to inventory server + /// The senders account ID + /// The receivers account ID + /// The item to transfer + /// false + override public bool InventoryTransferRequest(UUID from, UUID to, UUID item) + { + return false; + } + + #endregion + + #region Appearance methods + + /// + /// Gets the user appearance. + /// + /// The user. + /// + override public AvatarAppearance GetUserAppearance(UUID user) + { + try + { + AvatarAppearance appearance = new AvatarAppearance(); + string sql = "SELECT * FROM avatarappearance WHERE owner = @UUID"; + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + + cmd.Parameters.Add(database.CreateParameter("@UUID", user)); + conn.Open(); + using (SqlDataReader reader = cmd.ExecuteReader()) + { + if (reader.Read()) + appearance = readUserAppearance(reader); + else + { + m_log.WarnFormat("[USER DB] No appearance found for user {0}", user.ToString()); + return null; + } + + } + } + + appearance.SetAttachments(GetUserAttachments(user)); + + return appearance; + } + catch (Exception e) + { + m_log.ErrorFormat("[USER DB] Error updating userfriend, error: {0}", e.Message); + } + return null; + } + + /// + /// Update a user appearence into database + /// + /// the used UUID + /// the appearence + override public void UpdateUserAppearance(UUID user, AvatarAppearance appearance) + { + string sql = @"DELETE FROM avatarappearance WHERE owner=@owner; + INSERT INTO avatarappearance + (owner, serial, visual_params, texture, avatar_height, + body_item, body_asset, skin_item, skin_asset, hair_item, + hair_asset, eyes_item, eyes_asset, shirt_item, shirt_asset, + pants_item, pants_asset, shoes_item, shoes_asset, socks_item, + socks_asset, jacket_item, jacket_asset, gloves_item, gloves_asset, + undershirt_item, undershirt_asset, underpants_item, underpants_asset, + skirt_item, skirt_asset) + VALUES + (@owner, @serial, @visual_params, @texture, @avatar_height, + @body_item, @body_asset, @skin_item, @skin_asset, @hair_item, + @hair_asset, @eyes_item, @eyes_asset, @shirt_item, @shirt_asset, + @pants_item, @pants_asset, @shoes_item, @shoes_asset, @socks_item, + @socks_asset, @jacket_item, @jacket_asset, @gloves_item, @gloves_asset, + @undershirt_item, @undershirt_asset, @underpants_item, @underpants_asset, + @skirt_item, @skirt_asset)"; + + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.Add(database.CreateParameter("@owner", appearance.Owner)); + cmd.Parameters.Add(database.CreateParameter("@serial", appearance.Serial)); + cmd.Parameters.Add(database.CreateParameter("@visual_params", appearance.VisualParams)); + cmd.Parameters.Add(database.CreateParameter("@texture", appearance.Texture.GetBytes())); + cmd.Parameters.Add(database.CreateParameter("@avatar_height", appearance.AvatarHeight)); + cmd.Parameters.Add(database.CreateParameter("@body_item", appearance.BodyItem)); + cmd.Parameters.Add(database.CreateParameter("@body_asset", appearance.BodyAsset)); + cmd.Parameters.Add(database.CreateParameter("@skin_item", appearance.SkinItem)); + cmd.Parameters.Add(database.CreateParameter("@skin_asset", appearance.SkinAsset)); + cmd.Parameters.Add(database.CreateParameter("@hair_item", appearance.HairItem)); + cmd.Parameters.Add(database.CreateParameter("@hair_asset", appearance.HairAsset)); + cmd.Parameters.Add(database.CreateParameter("@eyes_item", appearance.EyesItem)); + cmd.Parameters.Add(database.CreateParameter("@eyes_asset", appearance.EyesAsset)); + cmd.Parameters.Add(database.CreateParameter("@shirt_item", appearance.ShirtItem)); + cmd.Parameters.Add(database.CreateParameter("@shirt_asset", appearance.ShirtAsset)); + cmd.Parameters.Add(database.CreateParameter("@pants_item", appearance.PantsItem)); + cmd.Parameters.Add(database.CreateParameter("@pants_asset", appearance.PantsAsset)); + cmd.Parameters.Add(database.CreateParameter("@shoes_item", appearance.ShoesItem)); + cmd.Parameters.Add(database.CreateParameter("@shoes_asset", appearance.ShoesAsset)); + cmd.Parameters.Add(database.CreateParameter("@socks_item", appearance.SocksItem)); + cmd.Parameters.Add(database.CreateParameter("@socks_asset", appearance.SocksAsset)); + cmd.Parameters.Add(database.CreateParameter("@jacket_item", appearance.JacketItem)); + cmd.Parameters.Add(database.CreateParameter("@jacket_asset", appearance.JacketAsset)); + cmd.Parameters.Add(database.CreateParameter("@gloves_item", appearance.GlovesItem)); + cmd.Parameters.Add(database.CreateParameter("@gloves_asset", appearance.GlovesAsset)); + cmd.Parameters.Add(database.CreateParameter("@undershirt_item", appearance.UnderShirtItem)); + cmd.Parameters.Add(database.CreateParameter("@undershirt_asset", appearance.UnderShirtAsset)); + cmd.Parameters.Add(database.CreateParameter("@underpants_item", appearance.UnderPantsItem)); + cmd.Parameters.Add(database.CreateParameter("@underpants_asset", appearance.UnderPantsAsset)); + cmd.Parameters.Add(database.CreateParameter("@skirt_item", appearance.SkirtItem)); + cmd.Parameters.Add(database.CreateParameter("@skirt_asset", appearance.SkirtAsset)); + conn.Open(); + try + { + cmd.ExecuteNonQuery(); + } + catch (Exception e) + { + m_log.ErrorFormat("[USER DB] Error updating user appearance, error: {0}", e.Message); + } + } + UpdateUserAttachments(user, appearance.GetAttachments()); + } + + #endregion + + #region Attachment methods + + /// + /// Gets all attachment of a agent. + /// + /// agent ID. + /// + public Hashtable GetUserAttachments(UUID agentID) + { + Hashtable returnTable = new Hashtable(); + string sql = "select attachpoint, item, asset from avatarattachments where UUID = @uuid"; + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.Add(database.CreateParameter("@uuid", agentID)); + conn.Open(); + using (SqlDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + int attachpoint = Convert.ToInt32(reader["attachpoint"]); + if (returnTable.ContainsKey(attachpoint)) + continue; + Hashtable item = new Hashtable(); + item.Add("item", reader["item"].ToString()); + item.Add("asset", reader["asset"].ToString()); + + returnTable.Add(attachpoint, item); + } + } + } + return returnTable; + } + + /// + /// Updates all attachments of the agent. + /// + /// agentID. + /// data with all items on attachmentpoints + public void UpdateUserAttachments(UUID agentID, Hashtable data) + { + string sql = "DELETE FROM avatarattachments WHERE UUID = @uuid"; + + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.Add(database.CreateParameter("uuid", agentID)); + conn.Open(); + cmd.ExecuteNonQuery(); + } + if (data == null) + return; + + sql = @"INSERT INTO avatarattachments (UUID, attachpoint, item, asset) + VALUES (@uuid, @attachpoint, @item, @asset)"; + + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + bool firstTime = true; + foreach (DictionaryEntry e in data) + { + int attachpoint = Convert.ToInt32(e.Key); + + Hashtable item = (Hashtable)e.Value; + + if (firstTime) + { + cmd.Parameters.Add(database.CreateParameter("@uuid", agentID)); + cmd.Parameters.Add(database.CreateParameter("@attachpoint", attachpoint)); + cmd.Parameters.Add(database.CreateParameter("@item", new UUID(item["item"].ToString()))); + cmd.Parameters.Add(database.CreateParameter("@asset", new UUID(item["asset"].ToString()))); + firstTime = false; + } + cmd.Parameters["@uuid"].Value = agentID.Guid; //.ToString(); + cmd.Parameters["@attachpoint"].Value = attachpoint; + cmd.Parameters["@item"].Value = new Guid(item["item"].ToString()); + cmd.Parameters["@asset"].Value = new Guid(item["asset"].ToString()); + + try + { + conn.Open(); + cmd.ExecuteNonQuery(); + } + catch (Exception ex) + { + m_log.DebugFormat("[USER DB] : Error adding user attachment. {0}", ex.Message); + } + } + } + } + + /// + /// Resets all attachments of a agent in the database. + /// + /// agentID. + override public void ResetAttachments(UUID agentID) + { + string sql = "UPDATE avatarattachments SET asset = '00000000-0000-0000-0000-000000000000' WHERE UUID = @uuid"; + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.Add(database.CreateParameter("uuid", agentID)); + conn.Open(); + cmd.ExecuteNonQuery(); + } + } + + override public void LogoutUsers(UUID regionID) + { + } + + #endregion + + #region Other public methods + + /// + /// + /// + /// + /// + /// + override public List GeneratePickerResults(UUID queryID, string query) + { + List returnlist = new List(); + string[] querysplit = query.Split(' '); + if (querysplit.Length == 2) + { + try + { + string sql = string.Format(@"SELECT UUID,username,lastname FROM {0} + WHERE username LIKE @first AND lastname LIKE @second", m_usersTableName); + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + //Add wildcard to the search + cmd.Parameters.Add(database.CreateParameter("first", querysplit[0] + "%")); + cmd.Parameters.Add(database.CreateParameter("second", querysplit[1] + "%")); + conn.Open(); + using (SqlDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + AvatarPickerAvatar user = new AvatarPickerAvatar(); + user.AvatarID = new UUID((Guid)reader["UUID"]); + user.firstName = (string)reader["username"]; + user.lastName = (string)reader["lastname"]; + returnlist.Add(user); + } + } + } + } + catch (Exception e) + { + m_log.Error(e.ToString()); + } + } + else if (querysplit.Length == 1) + { + try + { + string sql = string.Format(@"SELECT UUID,username,lastname FROM {0} + WHERE username LIKE @first OR lastname LIKE @first", m_usersTableName); + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand cmd = new SqlCommand(sql, conn)) + { + cmd.Parameters.Add(database.CreateParameter("first", querysplit[0] + "%")); + conn.Open(); + using (SqlDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + AvatarPickerAvatar user = new AvatarPickerAvatar(); + user.AvatarID = new UUID((Guid)reader["UUID"]); + user.firstName = (string)reader["username"]; + user.lastName = (string)reader["lastname"]; + returnlist.Add(user); + } + } + } + } + catch (Exception e) + { + m_log.Error(e.ToString()); + } + } + return returnlist; + } + + /// + /// Store a weblogin key + /// + /// The agent UUID + /// the WebLogin Key + /// unused ? + override public void StoreWebLoginKey(UUID AgentID, UUID WebLoginKey) + { + UserProfileData user = GetUserByUUID(AgentID); + user.WebLoginKey = WebLoginKey; + UpdateUserProfile(user); + } + + /// + /// Database provider name + /// + /// Provider name + override public string Name + { + get { return "MSSQL Userdata Interface"; } + } + + /// + /// Database provider version + /// + /// provider version + override public string Version + { + get { return database.getVersion(); } + } + + #endregion + + #region Private functions + + /// + /// Reads a one item from an SQL result + /// + /// The SQL Result + /// the item read + private static AvatarAppearance readUserAppearance(SqlDataReader reader) + { + try + { + AvatarAppearance appearance = new AvatarAppearance(); + + appearance.Owner = new UUID((Guid)reader["owner"]); + appearance.Serial = Convert.ToInt32(reader["serial"]); + appearance.VisualParams = (byte[])reader["visual_params"]; + appearance.Texture = new Primitive.TextureEntry((byte[])reader["texture"], 0, ((byte[])reader["texture"]).Length); + appearance.AvatarHeight = (float)Convert.ToDouble(reader["avatar_height"]); + appearance.BodyItem = new UUID((Guid)reader["body_item"]); + appearance.BodyAsset = new UUID((Guid)reader["body_asset"]); + appearance.SkinItem = new UUID((Guid)reader["skin_item"]); + appearance.SkinAsset = new UUID((Guid)reader["skin_asset"]); + appearance.HairItem = new UUID((Guid)reader["hair_item"]); + appearance.HairAsset = new UUID((Guid)reader["hair_asset"]); + appearance.EyesItem = new UUID((Guid)reader["eyes_item"]); + appearance.EyesAsset = new UUID((Guid)reader["eyes_asset"]); + appearance.ShirtItem = new UUID((Guid)reader["shirt_item"]); + appearance.ShirtAsset = new UUID((Guid)reader["shirt_asset"]); + appearance.PantsItem = new UUID((Guid)reader["pants_item"]); + appearance.PantsAsset = new UUID((Guid)reader["pants_asset"]); + appearance.ShoesItem = new UUID((Guid)reader["shoes_item"]); + appearance.ShoesAsset = new UUID((Guid)reader["shoes_asset"]); + appearance.SocksItem = new UUID((Guid)reader["socks_item"]); + appearance.SocksAsset = new UUID((Guid)reader["socks_asset"]); + appearance.JacketItem = new UUID((Guid)reader["jacket_item"]); + appearance.JacketAsset = new UUID((Guid)reader["jacket_asset"]); + appearance.GlovesItem = new UUID((Guid)reader["gloves_item"]); + appearance.GlovesAsset = new UUID((Guid)reader["gloves_asset"]); + appearance.UnderShirtItem = new UUID((Guid)reader["undershirt_item"]); + appearance.UnderShirtAsset = new UUID((Guid)reader["undershirt_asset"]); + appearance.UnderPantsItem = new UUID((Guid)reader["underpants_item"]); + appearance.UnderPantsAsset = new UUID((Guid)reader["underpants_asset"]); + appearance.SkirtItem = new UUID((Guid)reader["skirt_item"]); + appearance.SkirtAsset = new UUID((Guid)reader["skirt_asset"]); + + return appearance; + } + catch (SqlException e) + { + m_log.Error(e.ToString()); + } + + return null; + } + + /// + /// Insert/Update a agent row in the DB. + /// + /// agentdata. + private void InsertUpdateAgentRow(UserAgentData agentdata) + { + string sql = @" + +IF EXISTS (SELECT * FROM agents WHERE UUID = @UUID) + BEGIN + UPDATE agents SET UUID = @UUID, sessionID = @sessionID, secureSessionID = @secureSessionID, agentIP = @agentIP, agentPort = @agentPort, agentOnline = @agentOnline, loginTime = @loginTime, logoutTime = @logoutTime, currentRegion = @currentRegion, currentHandle = @currentHandle, currentPos = @currentPos + WHERE UUID = @UUID + END +ELSE + BEGIN + INSERT INTO + agents (UUID, sessionID, secureSessionID, agentIP, agentPort, agentOnline, loginTime, logoutTime, currentRegion, currentHandle, currentPos) VALUES + (@UUID, @sessionID, @secureSessionID, @agentIP, @agentPort, @agentOnline, @loginTime, @logoutTime, @currentRegion, @currentHandle, @currentPos) + END +"; + + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand command = new SqlCommand(sql, conn)) + { + command.Parameters.Add(database.CreateParameter("@UUID", agentdata.ProfileID)); + command.Parameters.Add(database.CreateParameter("@sessionID", agentdata.SessionID)); + command.Parameters.Add(database.CreateParameter("@secureSessionID", agentdata.SecureSessionID)); + command.Parameters.Add(database.CreateParameter("@agentIP", agentdata.AgentIP)); + command.Parameters.Add(database.CreateParameter("@agentPort", agentdata.AgentPort)); + command.Parameters.Add(database.CreateParameter("@agentOnline", agentdata.AgentOnline)); + command.Parameters.Add(database.CreateParameter("@loginTime", agentdata.LoginTime)); + command.Parameters.Add(database.CreateParameter("@logoutTime", agentdata.LogoutTime)); + command.Parameters.Add(database.CreateParameter("@currentRegion", agentdata.Region)); + command.Parameters.Add(database.CreateParameter("@currentHandle", agentdata.Handle)); + command.Parameters.Add(database.CreateParameter("@currentPos", "<" + ((int)agentdata.Position.X) + "," + ((int)agentdata.Position.Y) + "," + ((int)agentdata.Position.Z) + ">")); + conn.Open(); + + command.Transaction = command.Connection.BeginTransaction(IsolationLevel.Serializable); + try + { + if (command.ExecuteNonQuery() > 0) + { + command.Transaction.Commit(); + return; + } + + command.Transaction.Rollback(); + return; + } + catch (Exception e) + { + command.Transaction.Rollback(); + m_log.Error(e.ToString()); + return; + } + } + + } + + /// + /// Reads an agent row from a database reader + /// + /// An active database reader + /// A user session agent + private UserAgentData readAgentRow(SqlDataReader reader) + { + UserAgentData retval = new UserAgentData(); + + if (reader.Read()) + { + // Agent IDs + retval.ProfileID = new UUID((Guid)reader["UUID"]); + retval.SessionID = new UUID((Guid)reader["sessionID"]); + retval.SecureSessionID = new UUID((Guid)reader["secureSessionID"]); + + // Agent Who? + retval.AgentIP = (string)reader["agentIP"]; + retval.AgentPort = Convert.ToUInt32(reader["agentPort"].ToString()); + retval.AgentOnline = Convert.ToInt32(reader["agentOnline"].ToString()) != 0; + + // Login/Logout times (UNIX Epoch) + retval.LoginTime = Convert.ToInt32(reader["loginTime"].ToString()); + retval.LogoutTime = Convert.ToInt32(reader["logoutTime"].ToString()); + + // Current position + retval.Region = new UUID((Guid)reader["currentRegion"]); + retval.Handle = Convert.ToUInt64(reader["currentHandle"].ToString()); + Vector3 tmp_v; + Vector3.TryParse((string)reader["currentPos"], out tmp_v); + retval.Position = tmp_v; + + } + else + { + return null; + } + return retval; + } + + /// + /// Creates a new user and inserts it into the database + /// + /// User ID + /// First part of the login + /// Second part of the login + /// Email of person + /// A salted hash of the users password + /// The salt used for the password hash + /// A regionHandle of the users home region + /// Home region position vector + /// Home region position vector + /// Home region position vector + /// Home region 'look at' vector + /// Home region 'look at' vector + /// Home region 'look at' vector + /// Account created (unix timestamp) + /// Last login (unix timestamp) + /// Users inventory URI + /// Users asset URI + /// I can do mask + /// I want to do mask + /// Profile text + /// Firstlife text + /// UUID for profile image + /// UUID for firstlife image + /// web login key + /// homeregion UUID + /// has the user godlevel + /// unknown + /// unknown + /// UUID of partner + /// Success? + private void InsertUserRow(UUID uuid, string username, string lastname, string email, string passwordHash, + string passwordSalt, UInt64 homeRegion, float homeLocX, float homeLocY, float homeLocZ, + float homeLookAtX, float homeLookAtY, float homeLookAtZ, int created, int lastlogin, + string inventoryURI, string assetURI, uint canDoMask, uint wantDoMask, + string aboutText, string firstText, + UUID profileImage, UUID firstImage, UUID webLoginKey, UUID homeRegionID, + int godLevel, int userFlags, string customType, UUID partnerID) + { + string sql = string.Format(@"INSERT INTO {0} + ([UUID], [username], [lastname], [email], [passwordHash], [passwordSalt], + [homeRegion], [homeLocationX], [homeLocationY], [homeLocationZ], [homeLookAtX], + [homeLookAtY], [homeLookAtZ], [created], [lastLogin], [userInventoryURI], + [userAssetURI], [profileCanDoMask], [profileWantDoMask], [profileAboutText], + [profileFirstText], [profileImage], [profileFirstImage], [webLoginKey], + [homeRegionID], [userFlags], [godLevel], [customType], [partner]) + VALUES + (@UUID, @username, @lastname, @email, @passwordHash, @passwordSalt, + @homeRegion, @homeLocationX, @homeLocationY, @homeLocationZ, @homeLookAtX, + @homeLookAtY, @homeLookAtZ, @created, @lastLogin, @userInventoryURI, + @userAssetURI, @profileCanDoMask, @profileWantDoMask, @profileAboutText, + @profileFirstText, @profileImage, @profileFirstImage, @webLoginKey, + @homeRegionID, @userFlags, @godLevel, @customType, @partner)", m_usersTableName); + + try + { + using (SqlConnection conn = new SqlConnection(m_connectionString)) + using (SqlCommand command = new SqlCommand(sql, conn)) + { + command.Parameters.Add(database.CreateParameter("UUID", uuid)); + command.Parameters.Add(database.CreateParameter("username", username)); + command.Parameters.Add(database.CreateParameter("lastname", lastname)); + command.Parameters.Add(database.CreateParameter("email", email)); + command.Parameters.Add(database.CreateParameter("passwordHash", passwordHash)); + command.Parameters.Add(database.CreateParameter("passwordSalt", passwordSalt)); + command.Parameters.Add(database.CreateParameter("homeRegion", homeRegion)); + command.Parameters.Add(database.CreateParameter("homeLocationX", homeLocX)); + command.Parameters.Add(database.CreateParameter("homeLocationY", homeLocY)); + command.Parameters.Add(database.CreateParameter("homeLocationZ", homeLocZ)); + command.Parameters.Add(database.CreateParameter("homeLookAtX", homeLookAtX)); + command.Parameters.Add(database.CreateParameter("homeLookAtY", homeLookAtY)); + command.Parameters.Add(database.CreateParameter("homeLookAtZ", homeLookAtZ)); + command.Parameters.Add(database.CreateParameter("created", created)); + command.Parameters.Add(database.CreateParameter("lastLogin", lastlogin)); + command.Parameters.Add(database.CreateParameter("userInventoryURI", inventoryURI)); + command.Parameters.Add(database.CreateParameter("userAssetURI", assetURI)); + command.Parameters.Add(database.CreateParameter("profileCanDoMask", canDoMask)); + command.Parameters.Add(database.CreateParameter("profileWantDoMask", wantDoMask)); + command.Parameters.Add(database.CreateParameter("profileAboutText", aboutText)); + command.Parameters.Add(database.CreateParameter("profileFirstText", firstText)); + command.Parameters.Add(database.CreateParameter("profileImage", profileImage)); + command.Parameters.Add(database.CreateParameter("profileFirstImage", firstImage)); + command.Parameters.Add(database.CreateParameter("webLoginKey", webLoginKey)); + command.Parameters.Add(database.CreateParameter("homeRegionID", homeRegionID)); + command.Parameters.Add(database.CreateParameter("userFlags", userFlags)); + command.Parameters.Add(database.CreateParameter("godLevel", godLevel)); + command.Parameters.Add(database.CreateParameter("customType", customType)); + command.Parameters.Add(database.CreateParameter("partner", partnerID)); + conn.Open(); + command.ExecuteNonQuery(); + return; + } + } + catch (Exception e) + { + m_log.Error(e.ToString()); + return; + } + } + + /// + /// Reads a user profile from an active data reader + /// + /// An active database reader + /// A user profile + private static UserProfileData ReadUserRow(SqlDataReader reader) + { + UserProfileData retval = new UserProfileData(); + + if (reader.Read()) + { + retval.ID = new UUID((Guid)reader["UUID"]); + retval.FirstName = (string)reader["username"]; + retval.SurName = (string)reader["lastname"]; + if (reader.IsDBNull(reader.GetOrdinal("email"))) + retval.Email = ""; + else + retval.Email = (string)reader["email"]; + + retval.PasswordHash = (string)reader["passwordHash"]; + retval.PasswordSalt = (string)reader["passwordSalt"]; + + retval.HomeRegion = Convert.ToUInt64(reader["homeRegion"].ToString()); + retval.HomeLocation = new Vector3( + Convert.ToSingle(reader["homeLocationX"].ToString()), + Convert.ToSingle(reader["homeLocationY"].ToString()), + Convert.ToSingle(reader["homeLocationZ"].ToString())); + retval.HomeLookAt = new Vector3( + Convert.ToSingle(reader["homeLookAtX"].ToString()), + Convert.ToSingle(reader["homeLookAtY"].ToString()), + Convert.ToSingle(reader["homeLookAtZ"].ToString())); + + if (reader.IsDBNull(reader.GetOrdinal("homeRegionID"))) + retval.HomeRegionID = UUID.Zero; + else + retval.HomeRegionID = new UUID((Guid)reader["homeRegionID"]); + + retval.Created = Convert.ToInt32(reader["created"].ToString()); + retval.LastLogin = Convert.ToInt32(reader["lastLogin"].ToString()); + + if (reader.IsDBNull(reader.GetOrdinal("userInventoryURI"))) + retval.UserInventoryURI = ""; + else + retval.UserInventoryURI = (string)reader["userInventoryURI"]; + + if (reader.IsDBNull(reader.GetOrdinal("userAssetURI"))) + retval.UserAssetURI = ""; + else + retval.UserAssetURI = (string)reader["userAssetURI"]; + + retval.CanDoMask = Convert.ToUInt32(reader["profileCanDoMask"].ToString()); + retval.WantDoMask = Convert.ToUInt32(reader["profileWantDoMask"].ToString()); + + + if (reader.IsDBNull(reader.GetOrdinal("profileAboutText"))) + retval.AboutText = ""; + else + retval.AboutText = (string)reader["profileAboutText"]; + + if (reader.IsDBNull(reader.GetOrdinal("profileFirstText"))) + retval.FirstLifeAboutText = ""; + else + retval.FirstLifeAboutText = (string)reader["profileFirstText"]; + + if (reader.IsDBNull(reader.GetOrdinal("profileImage"))) + retval.Image = UUID.Zero; + else + retval.Image = new UUID((Guid)reader["profileImage"]); + + if (reader.IsDBNull(reader.GetOrdinal("profileFirstImage"))) + retval.Image = UUID.Zero; + else + retval.FirstLifeImage = new UUID((Guid)reader["profileFirstImage"]); + + if (reader.IsDBNull(reader.GetOrdinal("webLoginKey"))) + retval.WebLoginKey = UUID.Zero; + else + retval.WebLoginKey = new UUID((Guid)reader["webLoginKey"]); + + retval.UserFlags = Convert.ToInt32(reader["userFlags"].ToString()); + retval.GodLevel = Convert.ToInt32(reader["godLevel"].ToString()); + if (reader.IsDBNull(reader.GetOrdinal("customType"))) + retval.CustomType = ""; + else + retval.CustomType = reader["customType"].ToString(); + + if (reader.IsDBNull(reader.GetOrdinal("partner"))) + retval.Partner = UUID.Zero; + else + retval.Partner = new UUID((Guid)reader["partner"]); + } + else + { + return null; + } + return retval; + } + #endregion + } + +} diff --git a/OpenSim/Data/MSSQL/MSSQLXInventoryData.cs b/OpenSim/Data/MSSQL/MSSQLXInventoryData.cs new file mode 100644 index 0000000..739eb55 --- /dev/null +++ b/OpenSim/Data/MSSQL/MSSQLXInventoryData.cs @@ -0,0 +1,166 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ''AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using OpenMetaverse; +using OpenSim.Framework; +using System.Data.SqlClient; +using System.Reflection; +using System.Text; +using log4net; + +namespace OpenSim.Data.MSSQL +{ + public class MSSQLXInventoryData : IXInventoryData + { + private static readonly ILog m_log = LogManager.GetLogger( + MethodBase.GetCurrentMethod().DeclaringType); + + private MSSQLGenericTableHandler m_Folders; + private MSSQLItemHandler m_Items; + + public MSSQLXInventoryData(string conn, string realm) + { + m_Folders = new MSSQLGenericTableHandler( + conn, "inventoryfolders", "InventoryStore"); + m_Items = new MSSQLItemHandler( + conn, "inventoryitems", String.Empty); + } + + public XInventoryFolder[] GetFolders(string[] fields, string[] vals) + { + return m_Folders.Get(fields, vals); + } + + public XInventoryItem[] GetItems(string[] fields, string[] vals) + { + return m_Items.Get(fields, vals); + } + + public bool StoreFolder(XInventoryFolder folder) + { + return m_Folders.Store(folder); + } + + public bool StoreItem(XInventoryItem item) + { + return m_Items.Store(item); + } + + public bool DeleteFolders(string field, string val) + { + return m_Folders.Delete(field, val); + } + + public bool DeleteItems(string field, string val) + { + return m_Items.Delete(field, val); + } + + public bool MoveItem(string id, string newParent) + { + return m_Items.MoveItem(id, newParent); + } + + public XInventoryItem[] GetActiveGestures(UUID principalID) + { + return m_Items.GetActiveGestures(principalID); + } + + public int GetAssetPermissions(UUID principalID, UUID assetID) + { + return m_Items.GetAssetPermissions(principalID, assetID); + } + } + + public class MSSQLItemHandler : MSSQLGenericTableHandler + { + public MSSQLItemHandler(string c, string t, string m) : + base(c, t, m) + { + } + + public bool MoveItem(string id, string newParent) + { + using (SqlConnection conn = new SqlConnection(m_ConnectionString)) + using (SqlCommand cmd = new SqlCommand()) + { + + cmd.CommandText = String.Format("update {0} set parentFolderID = @ParentFolderID where inventoryID = @InventoryID", m_Realm); + cmd.Parameters.Add(m_database.CreateParameter("@ParentFolderID", newParent)); + cmd.Parameters.Add(m_database.CreateParameter("@InventoryID", id)); + cmd.Connection = conn; + conn.Open(); + return cmd.ExecuteNonQuery() == 0 ? false : true; + } + } + + public XInventoryItem[] GetActiveGestures(UUID principalID) + { + using (SqlConnection conn = new SqlConnection(m_ConnectionString)) + using (SqlCommand cmd = new SqlCommand()) + { + cmd.CommandText = String.Format("select * from inventoryitems where avatarId = @uuid and assetType = @type and flags = 1", m_Realm); + + cmd.Parameters.Add(m_database.CreateParameter("@uuid", principalID.ToString())); + cmd.Parameters.Add(m_database.CreateParameter("@type", (int)AssetType.Gesture)); + cmd.Connection = conn; + conn.Open(); + return DoQuery(cmd); + } + } + + public int GetAssetPermissions(UUID principalID, UUID assetID) + { + using (SqlConnection conn = new SqlConnection(m_ConnectionString)) + using (SqlCommand cmd = new SqlCommand()) + { + cmd.CommandText = String.Format("select bit_or(inventoryCurrentPermissions) as inventoryCurrentPermissions from inventoryitems where avatarID = @PrincipalID and assetID = @AssetID group by assetID", m_Realm); + cmd.Parameters.Add(m_database.CreateParameter("@PrincipalID", principalID.ToString())); + cmd.Parameters.Add(m_database.CreateParameter("@AssetID", assetID.ToString())); + cmd.Connection = conn; + conn.Open(); + using (SqlDataReader reader = cmd.ExecuteReader()) + { + + int perms = 0; + + if (reader.Read()) + { + perms = Convert.ToInt32(reader["inventoryCurrentPermissions"]); + } + + return perms; + } + + } + } + } +} diff --git a/OpenSim/Data/MSSQL/Resources/001_AuthStore.sql b/OpenSim/Data/MSSQL/Resources/001_AuthStore.sql new file mode 100644 index 0000000..c70a193 --- /dev/null +++ b/OpenSim/Data/MSSQL/Resources/001_AuthStore.sql @@ -0,0 +1,17 @@ +BEGIN TRANSACTION + +CREATE TABLE [auth] ( + [uuid] [uniqueidentifier] NOT NULL default '00000000-0000-0000-0000-000000000000', + [passwordHash] [varchar](32) NOT NULL, + [passwordSalt] [varchar](32) NOT NULL, + [webLoginKey] [varchar](255) NOT NULL, + [accountType] VARCHAR(32) NOT NULL DEFAULT 'UserAccount', +) ON [PRIMARY] + +CREATE TABLE [tokens] ( + [uuid] [uniqueidentifier] NOT NULL default '00000000-0000-0000-0000-000000000000', + [token] [varchar](255) NOT NULL, + [validity] [datetime] NOT NULL ) + ON [PRIMARY] + +COMMIT \ No newline at end of file diff --git a/OpenSim/Data/MSSQL/Resources/001_Avatar.sql b/OpenSim/Data/MSSQL/Resources/001_Avatar.sql new file mode 100644 index 0000000..48f4c00 --- /dev/null +++ b/OpenSim/Data/MSSQL/Resources/001_Avatar.sql @@ -0,0 +1,15 @@ +BEGIN TRANSACTION + +CREATE TABLE [Avatars] ( +[PrincipalID] uniqueidentifier NOT NULL, +[Name] varchar(32) NOT NULL, +[Value] varchar(255) NOT NULL DEFAULT '', +PRIMARY KEY CLUSTERED +( + [PrincipalID] ASC, [Name] ASC +)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] +) ON [PRIMARY] + + + +COMMIT \ No newline at end of file diff --git a/OpenSim/Data/MSSQL/Resources/001_FriendsStore.sql b/OpenSim/Data/MSSQL/Resources/001_FriendsStore.sql new file mode 100644 index 0000000..f6480f7 --- /dev/null +++ b/OpenSim/Data/MSSQL/Resources/001_FriendsStore.sql @@ -0,0 +1,11 @@ +BEGIN TRANSACTION + +CREATE TABLE [Friends] ( +[PrincipalID] uniqueidentifier NOT NULL, +[FriendID] varchar(255) NOT NULL, +[Flags] char(16) NOT NULL DEFAULT '0', +[Offered] varchar(32) NOT NULL DEFAULT 0) + ON [PRIMARY] + + +COMMIT \ No newline at end of file diff --git a/OpenSim/Data/MSSQL/Resources/001_Presence.sql b/OpenSim/Data/MSSQL/Resources/001_Presence.sql new file mode 100644 index 0000000..877881c --- /dev/null +++ b/OpenSim/Data/MSSQL/Resources/001_Presence.sql @@ -0,0 +1,19 @@ +BEGIN TRANSACTION + +CREATE TABLE [Presence] ( +[UserID] varchar(255) NOT NULL, +[RegionID] uniqueidentifier NOT NULL, +[SessionID] uniqueidentifier NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000', +[SecureSessionID] uniqueidentifier NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000', +[Online] char(5) NOT NULL DEFAULT 'false', +[Login] char(16) NOT NULL DEFAULT '0', +[Logout] char(16) NOT NULL DEFAULT '0', +[Position] char(64) NOT NULL DEFAULT '<0,0,0>', +[LookAt] char(64) NOT NULL DEFAULT '<0,0,0>', +[HomeRegionID] uniqueidentifier NOT NULL, +[HomePosition] CHAR(64) NOT NULL DEFAULT '<0,0,0>', +[HomeLookAt] CHAR(64) NOT NULL DEFAULT '<0,0,0>', +) + ON [PRIMARY] + +COMMIT \ No newline at end of file diff --git a/OpenSim/Data/MSSQL/Resources/002_AuthStore.sql b/OpenSim/Data/MSSQL/Resources/002_AuthStore.sql new file mode 100644 index 0000000..daed955 --- /dev/null +++ b/OpenSim/Data/MSSQL/Resources/002_AuthStore.sql @@ -0,0 +1,6 @@ +BEGIN TRANSACTION + +INSERT INTO auth (UUID, passwordHash, passwordSalt, webLoginKey, accountType) SELECT [UUID] AS UUID, [passwordHash] AS passwordHash, [passwordSalt] AS passwordSalt, [webLoginKey] AS webLoginKey, 'UserAccount' as [accountType] FROM users; + + +COMMIT \ No newline at end of file diff --git a/OpenSim/Data/MSSQL/Resources/002_FriendsStore.sql b/OpenSim/Data/MSSQL/Resources/002_FriendsStore.sql new file mode 100644 index 0000000..7762a26 --- /dev/null +++ b/OpenSim/Data/MSSQL/Resources/002_FriendsStore.sql @@ -0,0 +1,6 @@ +BEGIN TRANSACTION + +INSERT INTO Friends (PrincipalID, FriendID, Flags, Offered) SELECT [ownerID], [friendID], [friendPerms], 0 FROM userfriends; + + +COMMIT \ No newline at end of file diff --git a/OpenSim/Data/MSSQL/Resources/002_Presence.sql b/OpenSim/Data/MSSQL/Resources/002_Presence.sql new file mode 100644 index 0000000..a67671d --- /dev/null +++ b/OpenSim/Data/MSSQL/Resources/002_Presence.sql @@ -0,0 +1,6 @@ +BEGIN TRANSACTION + +CREATE UNIQUE INDEX SessionID ON Presence(SessionID); +CREATE INDEX UserID ON Presence(UserID); + +COMMIT \ No newline at end of file diff --git a/OpenSim/Data/MSSQL/Resources/002_UserAccount.sql b/OpenSim/Data/MSSQL/Resources/002_UserAccount.sql new file mode 100644 index 0000000..89d1f34 --- /dev/null +++ b/OpenSim/Data/MSSQL/Resources/002_UserAccount.sql @@ -0,0 +1,12 @@ +BEGIN TRANSACTION + +INSERT INTO UserAccounts (PrincipalID, ScopeID, FirstName, LastName, Email, ServiceURLs, Created) SELECT [UUID] AS PrincipalID, '00000000-0000-0000-0000-000000000000' AS ScopeID, +username AS FirstName, +lastname AS LastName, +email as Email, ( +'AssetServerURI=' + +userAssetURI + ' InventoryServerURI=' + userInventoryURI + ' GatewayURI= HomeURI=') AS ServiceURLs, +created as Created FROM users; + + +COMMIT \ No newline at end of file diff --git a/OpenSim/Data/MSSQL/Resources/007_GridStore.sql b/OpenSim/Data/MSSQL/Resources/007_GridStore.sql new file mode 100644 index 0000000..0b66d40 --- /dev/null +++ b/OpenSim/Data/MSSQL/Resources/007_GridStore.sql @@ -0,0 +1,9 @@ +BEGIN TRANSACTION + +ALTER TABLE regions ADD [flags] integer NOT NULL DEFAULT 0; +CREATE INDEX [flags] ON regions(flags); +ALTER TABLE [regions] ADD [last_seen] integer NOT NULL DEFAULT 0; +ALTER TABLE [regions] ADD [PrincipalID] uniqueidentifier NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000'; +ALTER TABLE [regions] ADD [Token] varchar(255) NOT NULL DEFAULT 0; + +COMMIT -- cgit v1.1