/* * 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 OpenSim 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 libsecondlife; using OpenSim.Framework; using OpenSim.Framework.Console; namespace OpenSim.Data.MSSQL { /// /// A MySQL interface for the inventory server /// public class MSSQLInventoryData : IInventoryData { private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); /// /// The database manager /// private MSSQLManager database; /// /// Loads and initialises this database plugin /// public void Initialise() { IniFile GridDataMySqlFile = new IniFile("mssql_connection.ini"); string settingDataSource = GridDataMySqlFile.ParseFileReadValue("data_source"); string settingInitialCatalog = GridDataMySqlFile.ParseFileReadValue("initial_catalog"); string settingPersistSecurityInfo = GridDataMySqlFile.ParseFileReadValue("persist_security_info"); string settingUserId = GridDataMySqlFile.ParseFileReadValue("user_id"); string settingPassword = GridDataMySqlFile.ParseFileReadValue("password"); database = new MSSQLManager(settingDataSource, settingInitialCatalog, settingPersistSecurityInfo, settingUserId, settingPassword); TestTables(); } #region Test and initialization code private void UpgradeFoldersTable(string tableName) { // null as the version, indicates that the table didn't exist if (tableName == null) { database.ExecuteResourceSql("CreateFoldersTable.sql"); //database.ExecuteResourceSql("UpgradeFoldersTableToVersion2.sql"); return; } } private void UpgradeItemsTable(string tableName) { // null as the version, indicates that the table didn't exist if (tableName == null) { database.ExecuteResourceSql("CreateItemsTable.sql"); //database.ExecuteResourceSql("UpgradeItemsTableToVersion2.sql"); return; } } private void TestTables() { Dictionary tableList = new Dictionary(); tableList["inventoryfolders"] = null; tableList["inventoryitems"] = null; database.GetTableVersion(tableList); UpgradeFoldersTable(tableList["inventoryfolders"]); UpgradeItemsTable(tableList["inventoryitems"]); } #endregion /// /// The name of this DB provider /// /// Name of DB provider public string getName() { return "MSSQL Inventory Data Interface"; } /// /// Closes this DB provider /// public void Close() { // Do nothing. } /// /// Returns the version of this DB provider /// /// A string containing the DB provider public string getVersion() { return database.getVersion(); } /// /// Returns a list of items in a specified folder /// /// The folder to search /// A list containing inventory items public List getInventoryInFolder(LLUUID folderID) { try { lock (database) { List items = new List(); Dictionary param = new Dictionary(); param["parentFolderID"] = folderID.ToString(); IDbCommand result = database.Query("SELECT * FROM inventoryitems WHERE parentFolderID = @parentFolderID", param); IDataReader reader = result.ExecuteReader(); while (reader.Read()) items.Add(readInventoryItem(reader)); reader.Close(); result.Dispose(); return items; } } catch (Exception e) { database.Reconnect(); m_log.Error(e.ToString()); return null; } } /// /// Returns a list of the root folders within a users inventory /// /// The user whos inventory is to be searched /// A list of folder objects public List getUserRootFolders(LLUUID user) { try { lock (database) { Dictionary param = new Dictionary(); param["uuid"] = user.ToString(); param["zero"] = LLUUID.Zero.ToString(); IDbCommand result = database.Query( "SELECT * FROM inventoryfolders WHERE parentFolderID = @zero AND agentID = @uuid", param); IDataReader reader = result.ExecuteReader(); List items = new List(); while (reader.Read()) items.Add(readInventoryFolder(reader)); reader.Close(); result.Dispose(); return items; } } catch (Exception e) { database.Reconnect(); m_log.Error(e.ToString()); return null; } } // see InventoryItemBase.getUserRootFolder public InventoryFolderBase getUserRootFolder(LLUUID user) { try { lock (database) { Dictionary param = new Dictionary(); param["uuid"] = user.ToString(); param["zero"] = LLUUID.Zero.ToString(); IDbCommand result = database.Query( "SELECT * FROM inventoryfolders WHERE parentFolderID = @zero AND agentID = @uuid", param); IDataReader reader = result.ExecuteReader(); List items = new List(); while (reader.Read()) items.Add(readInventoryFolder(reader)); InventoryFolderBase rootFolder = null; // There should only ever be one root folder for a user. However, if there's more // than one we'll simply use the first one rather than failing. It would be even // nicer to print some message to this effect, but this feels like it's too low a // to put such a message out, and it's too minor right now to spare the time to // suitably refactor. if (items.Count > 0) { rootFolder = items[0]; } reader.Close(); result.Dispose(); return rootFolder; } } catch (Exception e) { database.Reconnect(); m_log.Error(e.ToString()); return null; } } /// /// Returns a list of folders in a users inventory contained within the specified folder /// /// The folder to search /// A list of inventory folders public List getInventoryFolders(LLUUID parentID) { try { lock (database) { Dictionary param = new Dictionary(); param["parentFolderID"] = parentID.ToString(); IDbCommand result = database.Query("SELECT * FROM inventoryfolders WHERE parentFolderID = @parentFolderID", param); IDataReader reader = result.ExecuteReader(); List items = new List(); while (reader.Read()) items.Add(readInventoryFolder(reader)); reader.Close(); result.Dispose(); return items; } } catch (Exception e) { database.Reconnect(); m_log.Error(e.ToString()); return null; } } /// /// Reads a one item from an SQL result /// /// The SQL Result /// the item read private InventoryItemBase readInventoryItem(IDataReader reader) { try { InventoryItemBase item = new InventoryItemBase(); item.ID = new LLUUID((string) reader["inventoryID"]); item.AssetID = new LLUUID((string) reader["assetID"]); item.AssetType = (int) reader["assetType"]; item.Folder = new LLUUID((string) reader["parentFolderID"]); item.Owner = new LLUUID((string) reader["avatarID"]); item.Name = (string) reader["inventoryName"]; item.Description = (string) reader["inventoryDescription"]; item.NextPermissions = Convert.ToUInt32(reader["inventoryNextPermissions"]); item.CurrentPermissions = Convert.ToUInt32(reader["inventoryCurrentPermissions"]); item.InvType = (int) reader["invType"]; item.Creator = new LLUUID((string) reader["creatorID"]); item.BasePermissions = Convert.ToUInt32(reader["inventoryBasePermissions"]); item.EveryOnePermissions = Convert.ToUInt32(reader["inventoryEveryOnePermissions"]); return item; } catch (SqlException e) { m_log.Error(e.ToString()); } return null; } /// /// Returns a specified inventory item /// /// The item to return /// An inventory item public InventoryItemBase getInventoryItem(LLUUID itemID) { try { lock (database) { Dictionary param = new Dictionary(); param["inventoryID"] = itemID.ToString(); IDbCommand result = database.Query("SELECT * FROM inventoryitems WHERE inventoryID = @inventoryID", param); IDataReader reader = result.ExecuteReader(); InventoryItemBase item = null; if (reader.Read()) item = readInventoryItem(reader); reader.Close(); result.Dispose(); return item; } } catch (Exception e) { database.Reconnect(); m_log.Error(e.ToString()); } return null; } /// /// Reads a list of inventory folders returned by a query. /// /// A MySQL Data Reader /// A List containing inventory folders protected InventoryFolderBase readInventoryFolder(IDataReader reader) { try { InventoryFolderBase folder = new InventoryFolderBase(); folder.AgentID = new LLUUID((string) reader["agentID"]); folder.ParentID = new LLUUID((string) reader["parentFolderID"]); folder.ID = new LLUUID((string) reader["folderID"]); folder.Name = (string) reader["folderName"]; folder.Type = (short) reader["type"]; folder.Version = (ushort) ((int) reader["version"]); return folder; } catch (Exception e) { m_log.Error(e.ToString()); } return null; } /// /// Returns a specified inventory folder /// /// The folder to return /// A folder class public InventoryFolderBase getInventoryFolder(LLUUID folderID) { try { lock (database) { Dictionary param = new Dictionary(); param["uuid"] = folderID.ToString(); IDbCommand result = database.Query("SELECT * FROM inventoryfolders WHERE folderID = @uuid", param); IDataReader reader = result.ExecuteReader(); reader.Read(); InventoryFolderBase folder = readInventoryFolder(reader); reader.Close(); result.Dispose(); return folder; } } catch (Exception e) { database.Reconnect(); m_log.Error(e.ToString()); return null; } } /// /// Adds a specified item to the database /// /// The inventory item public void addInventoryItem(InventoryItemBase item) { if (getInventoryItem(item.ID) != null) { updateInventoryItem(item); return; } string sql = "INSERT INTO inventoryitems"; sql += "([inventoryID], [assetID], [assetType], [parentFolderID], [avatarID], [inventoryName], [inventoryDescription], [inventoryNextPermissions], [inventoryCurrentPermissions], [invType], [creatorID], [inventoryBasePermissions], [inventoryEveryOnePermissions]) VALUES "; sql += "(@inventoryID, @assetID, @assetType, @parentFolderID, @avatarID, @inventoryName, @inventoryDescription, @inventoryNextPermissions, @inventoryCurrentPermissions, @invType, @creatorID, @inventoryBasePermissions, @inventoryEveryOnePermissions);"; try { Dictionary param = new Dictionary(); param["inventoryID"] = item.ID.ToString(); param["assetID"] = item.AssetID.ToString(); param["assetType"] = item.AssetType.ToString(); param["parentFolderID"] = item.Folder.ToString(); param["avatarID"] = item.Owner.ToString(); param["inventoryName"] = item.Name; param["inventoryDescription"] = item.Description; param["inventoryNextPermissions"] = item.NextPermissions.ToString(); param["inventoryCurrentPermissions"] = item.CurrentPermissions.ToString(); param["invType"] = Convert.ToString(item.InvType); param["creatorID"] = item.Creator.ToString(); param["inventoryBasePermissions"] = Convert.ToString(item.BasePermissions); param["inventoryEveryOnePermissions"] = Convert.ToString(item.EveryOnePermissions); IDbCommand result = database.Query(sql, param); result.ExecuteNonQuery(); result.Dispose(); } catch (SqlException e) { m_log.Error(e.ToString()); } } /// /// Updates the specified inventory item /// /// Inventory item to update public void updateInventoryItem(InventoryItemBase item) { SqlCommand command = new SqlCommand("UPDATE inventoryitems set inventoryID = @inventoryID, " + "assetID = @assetID, " + "assetType = @assetType" + "parentFolderID = @parentFolderID" + "avatarID = @avatarID" + "inventoryName = @inventoryName" + "inventoryDescription = @inventoryDescription" + "inventoryNextPermissions = @inventoryNextPermissions" + "inventoryCurrentPermissions = @inventoryCurrentPermissions" + "invType = @invType" + "creatorID = @creatorID" + "inventoryBasePermissions = @inventoryBasePermissions" + "inventoryEveryOnePermissions = @inventoryEveryOnePermissions) where " + "inventoryID = @keyInventoryID;", database.getConnection()); SqlParameter param1 = new SqlParameter("@inventoryID", item.ID.ToString()); SqlParameter param2 = new SqlParameter("@assetID", item.AssetID); SqlParameter param3 = new SqlParameter("@assetType", item.AssetType); SqlParameter param4 = new SqlParameter("@parentFolderID", item.Folder); SqlParameter param5 = new SqlParameter("@avatarID", item.Owner); SqlParameter param6 = new SqlParameter("@inventoryName", item.Name); SqlParameter param7 = new SqlParameter("@inventoryDescription", item.Description); SqlParameter param8 = new SqlParameter("@inventoryNextPermissions", item.NextPermissions); SqlParameter param9 = new SqlParameter("@inventoryCurrentPermissions", item.CurrentPermissions); SqlParameter param10 = new SqlParameter("@invType", item.InvType); SqlParameter param11 = new SqlParameter("@creatorID", item.Creator); SqlParameter param12 = new SqlParameter("@inventoryBasePermissions", item.BasePermissions); SqlParameter param13 = new SqlParameter("@inventoryEveryOnePermissions", item.EveryOnePermissions); SqlParameter param14 = new SqlParameter("@keyInventoryID", item.ID.ToString()); command.Parameters.Add(param1); command.Parameters.Add(param2); command.Parameters.Add(param3); command.Parameters.Add(param4); command.Parameters.Add(param5); command.Parameters.Add(param6); command.Parameters.Add(param7); command.Parameters.Add(param8); command.Parameters.Add(param9); command.Parameters.Add(param10); command.Parameters.Add(param11); command.Parameters.Add(param12); command.Parameters.Add(param13); command.Parameters.Add(param14); try { command.ExecuteNonQuery(); } catch (Exception e) { m_log.Error(e.ToString()); } } /// /// /// /// public void deleteInventoryItem(LLUUID itemID) { try { Dictionary param = new Dictionary(); param["uuid"] = itemID.ToString(); IDbCommand cmd = database.Query("DELETE FROM inventoryitems WHERE inventoryID=@uuid", param); cmd.ExecuteNonQuery(); cmd.Dispose(); } catch (SqlException e) { database.Reconnect(); m_log.Error(e.ToString()); } } /// /// Creates a new inventory folder /// /// Folder to create public void addInventoryFolder(InventoryFolderBase folder) { string sql = "INSERT INTO inventoryfolders ([folderID], [agentID], [parentFolderID], [folderName], [type], [version]) VALUES "; sql += "(@folderID, @agentID, @parentFolderID, @folderName, @type, @version);"; Dictionary param = new Dictionary(); param["folderID"] = folder.ID.ToString(); param["agentID"] = folder.AgentID.ToString(); param["parentFolderID"] = folder.ParentID.ToString(); param["folderName"] = folder.Name; param["type"] = Convert.ToString(folder.Type); param["version"] = Convert.ToString(folder.Version); try { IDbCommand result = database.Query(sql, param); result.ExecuteNonQuery(); result.Dispose(); } catch (Exception e) { m_log.Error(e.ToString()); } } /// /// Updates an inventory folder /// /// Folder to update public void updateInventoryFolder(InventoryFolderBase folder) { SqlCommand command = new SqlCommand("UPDATE inventoryfolders set folderID = @folderID, " + "agentID = @agentID, " + "parentFolderID = @parentFolderID," + "folderName = @folderName," + "type = @type," + "version = @version where " + "folderID = @keyFolderID;", database.getConnection()); SqlParameter param1 = new SqlParameter("@folderID", folder.ID.ToString()); SqlParameter param2 = new SqlParameter("@agentID", folder.AgentID.ToString()); SqlParameter param3 = new SqlParameter("@parentFolderID", folder.ParentID.ToString()); SqlParameter param4 = new SqlParameter("@folderName", folder.Name); SqlParameter param5 = new SqlParameter("@type", folder.Type); SqlParameter param6 = new SqlParameter("@version", folder.Version); SqlParameter param7 = new SqlParameter("@keyFolderID", folder.ID.ToString()); command.Parameters.Add(param1); command.Parameters.Add(param2); command.Parameters.Add(param3); command.Parameters.Add(param4); command.Parameters.Add(param5); command.Parameters.Add(param6); command.Parameters.Add(param7); try { command.ExecuteNonQuery(); } catch (Exception e) { m_log.Error(e.ToString()); } } /// /// Updates an inventory folder /// /// Folder to update public void moveInventoryFolder(InventoryFolderBase folder) { SqlCommand command = new SqlCommand("UPDATE inventoryfolders set folderID = @folderID, " + "parentFolderID = @parentFolderID," + "folderID = @keyFolderID;", database.getConnection()); SqlParameter param1 = new SqlParameter("@folderID", folder.ID.ToString()); SqlParameter param2 = new SqlParameter("@parentFolderID", folder.ParentID.ToString()); SqlParameter param3 = new SqlParameter("@keyFolderID", folder.ID.ToString()); command.Parameters.Add(param1); command.Parameters.Add(param2); command.Parameters.Add(param3); try { command.ExecuteNonQuery(); } catch (Exception e) { m_log.Error(e.ToString()); } } /// /// Append a list of all the child folders of a parent folder /// /// list where folders will be appended /// ID of parent protected void getInventoryFolders(ref List folders, LLUUID parentID) { List subfolderList = getInventoryFolders(parentID); foreach (InventoryFolderBase f in subfolderList) folders.Add(f); } // See IInventoryData public List getFolderHierarchy(LLUUID parentID) { List folders = new List(); getInventoryFolders(ref folders, parentID); for (int i = 0; i < folders.Count; i++) getInventoryFolders(ref folders, folders[i].ID); return folders; } protected void deleteOneFolder(LLUUID folderID) { try { Dictionary param = new Dictionary(); param["folderID"] = folderID.ToString(); IDbCommand cmd = database.Query("DELETE FROM inventoryfolders WHERE folderID=@folderID", param); cmd.ExecuteNonQuery(); cmd.Dispose(); } catch (SqlException e) { database.Reconnect(); m_log.Error(e.ToString()); } } protected void deleteItemsInFolder(LLUUID folderID) { try { Dictionary param = new Dictionary(); param["parentFolderID"] = folderID.ToString(); IDbCommand cmd = database.Query("DELETE FROM inventoryitems WHERE parentFolderID=@parentFolderID", param); cmd.ExecuteNonQuery(); cmd.Dispose(); } catch (SqlException e) { database.Reconnect(); m_log.Error(e.ToString()); } } /// /// Delete an inventory folder /// /// Id of folder to delete public void deleteInventoryFolder(LLUUID folderID) { lock (database) { List subFolders = getFolderHierarchy(folderID); //Delete all sub-folders foreach (InventoryFolderBase f in subFolders) { deleteOneFolder(f.ID); deleteItemsInFolder(f.ID); } //Delete the actual row deleteOneFolder(folderID); deleteItemsInFolder(folderID); } } } }