2007-07-16 15:40:11 +00:00
/ *
2008-03-18 05:16:43 +00:00
* 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 .
2009-06-01 06:37:14 +00:00
* * Neither the name of the OpenSimulator Project nor the
2008-03-18 05:16:43 +00:00
* 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 .
* /
2007-07-16 15:40:11 +00:00
using System ;
2007-10-08 10:30:15 +00:00
using System.Collections.Generic ;
2008-04-21 07:09:17 +00:00
using System.Reflection ;
using log4net ;
2007-10-08 10:30:15 +00:00
using MySql.Data.MySqlClient ;
2009-02-12 09:53:12 +00:00
using OpenMetaverse ;
2008-04-02 16:00:40 +00:00
using OpenSim.Framework ;
2010-05-18 11:28:12 +00:00
using OpenSim.Data ;
2007-07-16 15:40:11 +00:00
2008-04-02 15:36:01 +00:00
namespace OpenSim.Data.MySQL
2007-07-16 15:40:11 +00:00
{
/// <summary>
/// A MySQL interface for the inventory server
/// </summary>
2008-07-31 09:24:28 +00:00
public class MySQLInventoryData : IInventoryDataPlugin
2007-07-16 15:40:11 +00:00
{
2008-05-16 01:22:11 +00:00
private static readonly ILog m_log
2008-04-21 07:09:17 +00:00
= LogManager . GetLogger ( MethodBase . GetCurrentMethod ( ) . DeclaringType ) ;
2008-02-05 19:44:27 +00:00
2010-02-04 21:19:30 +00:00
private string m_connectionString ;
private object m_dbLock = new object ( ) ;
2007-07-16 15:40:11 +00:00
2010-02-04 21:19:30 +00:00
public string Version { get { return "1.0.0.0" ; } }
2009-11-23 05:08:06 +00:00
2008-08-18 00:39:10 +00:00
public void Initialise ( )
{
2008-07-31 09:24:28 +00:00
m_log . Info ( "[MySQLInventoryData]: " + Name + " cannot be default-initialized!" ) ;
throw new PluginNotInitialisedException ( Name ) ;
}
2008-06-26 01:12:28 +00:00
/// <summary>
2008-06-26 12:38:03 +00:00
/// <para>Initialises Inventory interface</para>
/// <para>
/// <list type="bullet">
/// <item>Loads and initialises the MySQL storage plugin</item>
/// <item>warns and uses the obsolete mysql_connection.ini if connect string is empty.</item>
/// <item>Check for migration</item>
/// </list>
/// </para>
2008-06-26 01:12:28 +00:00
/// </summary>
2008-06-26 12:38:03 +00:00
/// <param name="connect">connect string</param>
2008-04-23 20:48:23 +00:00
public void Initialise ( string connect )
{
2010-02-04 21:19:30 +00:00
m_connectionString = connect ;
2008-06-12 15:47:33 +00:00
// This actually does the roll forward assembly stuff
Assembly assem = GetType ( ) . Assembly ;
2010-02-04 21:19:30 +00:00
using ( MySqlConnection dbcon = new MySqlConnection ( m_connectionString ) )
{
dbcon . Open ( ) ;
Migration m = new Migration ( dbcon , assem , "InventoryStore" ) ;
m . Update ( ) ;
}
2007-07-16 15:40:11 +00:00
}
2007-10-08 10:30:15 +00:00
2007-07-16 15:40:11 +00:00
/// <summary>
/// The name of this DB provider
/// </summary>
/// <returns>Name of DB provider</returns>
2008-07-31 09:24:28 +00:00
public string Name
2007-07-16 15:40:11 +00:00
{
2008-07-31 09:24:28 +00:00
get { return "MySQL Inventory Data Interface" ; }
2007-07-16 15:40:11 +00:00
}
/// <summary>
/// Closes this DB provider
/// </summary>
2008-06-26 01:12:28 +00:00
/// <remarks>do nothing</remarks>
2008-07-31 09:24:28 +00:00
public void Dispose ( )
2007-07-16 15:40:11 +00:00
{
// Do nothing.
}
/// <summary>
/// Returns a list of items in a specified folder
/// </summary>
/// <param name="folderID">The folder to search</param>
/// <returns>A list containing inventory items</returns>
2008-09-06 07:52:41 +00:00
public List < InventoryItemBase > getInventoryInFolder ( UUID folderID )
2007-07-16 15:40:11 +00:00
{
try
{
2010-02-04 21:19:30 +00:00
lock ( m_dbLock )
2007-07-16 15:40:11 +00:00
{
2007-10-08 10:30:15 +00:00
List < InventoryItemBase > items = new List < InventoryItemBase > ( ) ;
2007-07-16 15:40:11 +00:00
2010-02-04 21:19:30 +00:00
using ( MySqlConnection dbcon = new MySqlConnection ( m_connectionString ) )
2008-11-13 22:53:49 +00:00
{
2010-02-04 21:19:30 +00:00
dbcon . Open ( ) ;
2007-07-16 15:40:11 +00:00
2010-02-04 21:19:30 +00:00
using ( MySqlCommand result = new MySqlCommand ( "SELECT * FROM inventoryitems WHERE parentFolderID = ?uuid" , dbcon ) )
{
result . Parameters . AddWithValue ( "?uuid" , folderID . ToString ( ) ) ;
using ( MySqlDataReader reader = result . ExecuteReader ( ) )
{
while ( reader . Read ( ) )
{
// A null item (because something went wrong) breaks everything in the folder
InventoryItemBase item = readInventoryItem ( reader ) ;
if ( item ! = null )
items . Add ( item ) ;
}
2007-07-16 15:40:11 +00:00
2010-02-04 21:19:30 +00:00
return items ;
}
}
}
2007-07-16 15:40:11 +00:00
}
}
catch ( Exception e )
{
2010-02-04 21:19:30 +00:00
m_log . Error ( e . Message , e ) ;
2007-07-16 15:40:11 +00:00
return null ;
}
}
/// <summary>
/// Returns a list of the root folders within a users inventory
/// </summary>
2010-04-27 07:05:17 +00:00
/// <param name="user">The user whose inventory is to be searched</param>
2007-07-16 15:40:11 +00:00
/// <returns>A list of folder objects</returns>
2008-09-06 07:52:41 +00:00
public List < InventoryFolderBase > getUserRootFolders ( UUID user )
2007-07-16 15:40:11 +00:00
{
try
{
2010-02-04 21:19:30 +00:00
lock ( m_dbLock )
2007-07-16 15:40:11 +00:00
{
2010-02-04 21:19:30 +00:00
using ( MySqlConnection dbcon = new MySqlConnection ( m_connectionString ) )
{
dbcon . Open ( ) ;
2007-07-16 15:40:11 +00:00
2010-02-04 21:19:30 +00:00
using ( MySqlCommand result = new MySqlCommand (
"SELECT * FROM inventoryfolders WHERE parentFolderID = ?zero AND agentID = ?uuid" , dbcon ) )
{
result . Parameters . AddWithValue ( "?uuid" , user . ToString ( ) ) ;
result . Parameters . AddWithValue ( "?zero" , UUID . Zero . ToString ( ) ) ;
2009-11-02 19:19:55 +00:00
2010-02-04 21:19:30 +00:00
using ( MySqlDataReader reader = result . ExecuteReader ( ) )
{
List < InventoryFolderBase > items = new List < InventoryFolderBase > ( ) ;
while ( reader . Read ( ) )
items . Add ( readInventoryFolder ( reader ) ) ;
2009-11-02 19:19:55 +00:00
2010-02-04 21:19:30 +00:00
return items ;
}
}
}
2007-07-16 15:40:11 +00:00
}
}
catch ( Exception e )
{
2010-02-04 21:19:30 +00:00
m_log . Error ( e . Message , e ) ;
2007-07-16 15:40:11 +00:00
return null ;
2007-07-22 11:44:36 +00:00
}
}
2008-08-18 00:39:10 +00:00
2008-06-26 01:12:28 +00:00
/// <summary>
2008-06-26 12:38:03 +00:00
/// see <see cref="InventoryItemBase.getUserRootFolder"/>
2008-06-26 01:12:28 +00:00
/// </summary>
2008-06-26 12:38:03 +00:00
/// <param name="user">The user UUID</param>
2008-06-26 01:12:28 +00:00
/// <returns></returns>
2008-09-06 07:52:41 +00:00
public InventoryFolderBase getUserRootFolder ( UUID user )
2007-09-27 14:57:43 +00:00
{
try
{
2010-02-04 21:19:30 +00:00
lock ( m_dbLock )
2007-09-27 14:57:43 +00:00
{
2010-02-04 21:19:30 +00:00
using ( MySqlConnection dbcon = new MySqlConnection ( m_connectionString ) )
{
dbcon . Open ( ) ;
2008-07-03 22:30:16 +00:00
2010-02-04 21:19:30 +00:00
using ( MySqlCommand result = new MySqlCommand (
"SELECT * FROM inventoryfolders WHERE parentFolderID = ?zero AND agentID = ?uuid" , dbcon ) )
{
result . Parameters . AddWithValue ( "?uuid" , user . ToString ( ) ) ;
result . Parameters . AddWithValue ( "?zero" , UUID . Zero . ToString ( ) ) ;
2007-10-08 10:30:15 +00:00
2010-02-04 21:19:30 +00:00
using ( MySqlDataReader reader = result . ExecuteReader ( ) )
{
List < InventoryFolderBase > items = new List < InventoryFolderBase > ( ) ;
while ( reader . Read ( ) )
items . Add ( readInventoryFolder ( reader ) ) ;
2007-10-08 10:30:15 +00:00
2010-02-04 21:19:30 +00:00
InventoryFolderBase rootFolder = null ;
2007-12-27 21:41:48 +00:00
2010-02-04 21:19:30 +00:00
// 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 ] ;
2007-12-08 14:27:12 +00:00
2010-02-04 21:19:30 +00:00
return rootFolder ;
}
}
2007-12-08 14:27:12 +00:00
}
2007-09-27 14:57:43 +00:00
}
}
catch ( Exception e )
{
2010-02-04 21:19:30 +00:00
m_log . Error ( e . Message , e ) ;
return null ;
2007-09-27 14:57:43 +00:00
}
}
2007-07-16 15:40:11 +00:00
/// <summary>
2007-12-08 14:27:12 +00:00
/// Return a list of folders in a users inventory contained within the specified folder.
/// This method is only used in tests - in normal operation the user always have one,
/// and only one, root folder.
2007-07-16 15:40:11 +00:00
/// </summary>
/// <param name="parentID">The folder to search</param>
/// <returns>A list of inventory folders</returns>
2008-09-06 07:52:41 +00:00
public List < InventoryFolderBase > getInventoryFolders ( UUID parentID )
2007-07-16 15:40:11 +00:00
{
try
{
2010-02-04 21:19:30 +00:00
lock ( m_dbLock )
2007-07-16 15:40:11 +00:00
{
2010-02-04 21:19:30 +00:00
using ( MySqlConnection dbcon = new MySqlConnection ( m_connectionString ) )
{
dbcon . Open ( ) ;
2007-07-16 15:40:11 +00:00
2010-02-04 21:19:30 +00:00
using ( MySqlCommand result = new MySqlCommand ( "SELECT * FROM inventoryfolders WHERE parentFolderID = ?uuid" , dbcon ) )
{
result . Parameters . AddWithValue ( "?uuid" , parentID . ToString ( ) ) ;
using ( MySqlDataReader reader = result . ExecuteReader ( ) )
{
List < InventoryFolderBase > items = new List < InventoryFolderBase > ( ) ;
2007-07-16 15:40:11 +00:00
2010-02-04 21:19:30 +00:00
while ( reader . Read ( ) )
items . Add ( readInventoryFolder ( reader ) ) ;
2009-11-02 19:19:55 +00:00
2010-02-04 21:19:30 +00:00
return items ;
}
}
}
2007-07-16 15:40:11 +00:00
}
}
catch ( Exception e )
{
2010-02-04 21:19:30 +00:00
m_log . Error ( e . Message , e ) ;
2007-07-16 15:40:11 +00:00
return null ;
}
}
2007-10-08 10:30:15 +00:00
/// <summary>
/// Reads a one item from an SQL result
/// </summary>
/// <param name="reader">The SQL Result</param>
/// <returns>the item read</returns>
2008-05-01 16:03:53 +00:00
private static InventoryItemBase readInventoryItem ( MySqlDataReader reader )
2007-10-08 10:30:15 +00:00
{
try
{
InventoryItemBase item = new InventoryItemBase ( ) ;
2009-05-08 12:28:22 +00:00
2010-04-27 07:05:17 +00:00
// TODO: this is to handle a case where NULLs creep in there, which we are not sure is endemic to the system, or legacy. It would be nice to live fix these.
2010-09-12 17:43:49 +00:00
// (DBGuid.FromDB() reads db NULLs as well, returns UUID.Zero)
2010-05-18 23:28:19 +00:00
item . CreatorId = reader [ "creatorID" ] . ToString ( ) ;
2009-04-08 17:50:57 +00:00
2008-11-13 22:53:49 +00:00
// Be a bit safer in parsing these because the
// database doesn't enforce them to be not null, and
// the inventory still works if these are weird in the
// db
2010-05-18 11:28:12 +00:00
// (Empty is Ok, but "weird" will throw!)
item . Owner = DBGuid . FromDB ( reader [ "avatarID" ] ) ;
item . GroupID = DBGuid . FromDB ( reader [ "groupID" ] ) ;
2008-11-13 22:53:49 +00:00
2009-09-30 16:00:09 +00:00
// Rest of the parsing. If these UUID's fail, we're dead anyway
2010-05-18 11:28:12 +00:00
item . ID = DBGuid . FromDB ( reader [ "inventoryID" ] ) ;
item . AssetID = DBGuid . FromDB ( reader [ "assetID" ] ) ;
2008-04-07 23:15:35 +00:00
item . AssetType = ( int ) reader [ "assetType" ] ;
2010-05-18 11:28:12 +00:00
item . Folder = DBGuid . FromDB ( reader [ "parentFolderID" ] ) ;
2010-01-18 23:50:33 +00:00
item . Name = ( string ) ( reader [ "inventoryName" ] ? ? String . Empty ) ;
item . Description = ( string ) ( reader [ "inventoryDescription" ] ? ? String . Empty ) ;
2008-04-07 23:15:35 +00:00
item . NextPermissions = ( uint ) reader [ "inventoryNextPermissions" ] ;
item . CurrentPermissions = ( uint ) reader [ "inventoryCurrentPermissions" ] ;
item . InvType = ( int ) reader [ "invType" ] ;
item . BasePermissions = ( uint ) reader [ "inventoryBasePermissions" ] ;
2008-05-16 01:22:11 +00:00
item . EveryOnePermissions = ( uint ) reader [ "inventoryEveryOnePermissions" ] ;
2008-11-14 18:54:38 +00:00
item . GroupPermissions = ( uint ) reader [ "inventoryGroupPermissions" ] ;
2008-05-06 22:41:38 +00:00
item . SalePrice = ( int ) reader [ "salePrice" ] ;
2009-08-09 07:01:21 +00:00
item . SaleType = unchecked ( ( byte ) ( Convert . ToSByte ( reader [ "saleType" ] ) ) ) ;
2008-05-01 20:47:33 +00:00
item . CreationDate = ( int ) reader [ "creationDate" ] ;
item . GroupOwned = Convert . ToBoolean ( reader [ "groupOwned" ] ) ;
2008-05-16 01:22:11 +00:00
item . Flags = ( uint ) reader [ "flags" ] ;
2008-04-30 16:08:24 +00:00
2007-10-08 10:30:15 +00:00
return item ;
}
catch ( MySqlException e )
{
2008-02-05 19:44:27 +00:00
m_log . Error ( e . ToString ( ) ) ;
2007-10-08 10:30:15 +00:00
}
return null ;
}
2007-07-16 15:40:11 +00:00
/// <summary>
/// Returns a specified inventory item
/// </summary>
/// <param name="item">The item to return</param>
/// <returns>An inventory item</returns>
2008-09-06 07:52:41 +00:00
public InventoryItemBase getInventoryItem ( UUID itemID )
2007-07-16 15:40:11 +00:00
{
try
{
2010-02-04 21:19:30 +00:00
lock ( m_dbLock )
2007-07-16 15:40:11 +00:00
{
2010-02-04 21:19:30 +00:00
using ( MySqlConnection dbcon = new MySqlConnection ( m_connectionString ) )
{
dbcon . Open ( ) ;
2007-07-16 15:40:11 +00:00
2010-02-04 21:19:30 +00:00
using ( MySqlCommand result = new MySqlCommand ( "SELECT * FROM inventoryitems WHERE inventoryID = ?uuid" , dbcon ) )
{
result . Parameters . AddWithValue ( "?uuid" , itemID . ToString ( ) ) ;
2007-07-16 15:40:11 +00:00
2010-02-04 21:19:30 +00:00
using ( MySqlDataReader reader = result . ExecuteReader ( ) )
{
InventoryItemBase item = null ;
if ( reader . Read ( ) )
item = readInventoryItem ( reader ) ;
2009-11-02 19:19:55 +00:00
2010-02-04 21:19:30 +00:00
return item ;
}
}
}
2007-07-16 15:40:11 +00:00
}
}
catch ( Exception e )
{
2010-02-04 21:19:30 +00:00
m_log . Error ( e . Message , e ) ;
2007-07-16 15:40:11 +00:00
}
2007-10-08 10:30:15 +00:00
return null ;
2007-07-16 15:40:11 +00:00
}
2007-10-08 10:30:15 +00:00
/// <summary>
/// Reads a list of inventory folders returned by a query.
/// </summary>
/// <param name="reader">A MySQL Data Reader</param>
/// <returns>A List containing inventory folders</returns>
2008-05-01 16:03:53 +00:00
protected static InventoryFolderBase readInventoryFolder ( MySqlDataReader reader )
2007-10-08 10:30:15 +00:00
{
try
{
InventoryFolderBase folder = new InventoryFolderBase ( ) ;
2010-05-18 11:28:12 +00:00
folder . Owner = DBGuid . FromDB ( reader [ "agentID" ] ) ;
folder . ParentID = DBGuid . FromDB ( reader [ "parentFolderID" ] ) ;
folder . ID = DBGuid . FromDB ( reader [ "folderID" ] ) ;
2008-04-07 23:27:05 +00:00
folder . Name = ( string ) reader [ "folderName" ] ;
folder . Type = ( short ) reader [ "type" ] ;
folder . Version = ( ushort ) ( ( int ) reader [ "version" ] ) ;
2007-10-08 10:30:15 +00:00
return folder ;
}
catch ( Exception e )
{
2010-02-04 21:19:30 +00:00
m_log . Error ( e . Message , e ) ;
2007-10-08 10:30:15 +00:00
}
return null ;
}
2007-07-16 15:40:11 +00:00
/// <summary>
/// Returns a specified inventory folder
/// </summary>
2009-08-09 07:01:21 +00:00
/// <param name="folderID">The folder to return</param>
2007-07-16 15:40:11 +00:00
/// <returns>A folder class</returns>
2008-09-06 07:52:41 +00:00
public InventoryFolderBase getInventoryFolder ( UUID folderID )
2007-07-16 15:40:11 +00:00
{
try
{
2010-02-04 21:19:30 +00:00
lock ( m_dbLock )
2007-07-16 15:40:11 +00:00
{
2010-02-04 21:19:30 +00:00
using ( MySqlConnection dbcon = new MySqlConnection ( m_connectionString ) )
{
dbcon . Open ( ) ;
2008-07-03 22:30:16 +00:00
2010-02-04 21:19:30 +00:00
using ( MySqlCommand result = new MySqlCommand ( "SELECT * FROM inventoryfolders WHERE folderID = ?uuid" , dbcon ) )
{
result . Parameters . AddWithValue ( "?uuid" , folderID . ToString ( ) ) ;
2007-07-16 15:40:11 +00:00
2010-02-04 21:19:30 +00:00
using ( MySqlDataReader reader = result . ExecuteReader ( ) )
{
InventoryFolderBase folder = null ;
if ( reader . Read ( ) )
folder = readInventoryFolder ( reader ) ;
2007-07-16 15:40:11 +00:00
2010-02-04 21:19:30 +00:00
return folder ;
}
}
}
2007-07-16 15:40:11 +00:00
}
}
catch ( Exception e )
{
2010-02-04 21:19:30 +00:00
m_log . Error ( e . Message , e ) ;
2007-07-16 15:40:11 +00:00
return null ;
}
}
/// <summary>
/// Adds a specified item to the database
/// </summary>
/// <param name="item">The inventory item</param>
public void addInventoryItem ( InventoryItemBase item )
{
2007-10-30 09:05:31 +00:00
string sql =
2008-04-30 19:28:36 +00:00
"REPLACE INTO inventoryitems (inventoryID, assetID, assetType, parentFolderID, avatarID, inventoryName"
+ ", inventoryDescription, inventoryNextPermissions, inventoryCurrentPermissions, invType"
2008-11-14 18:54:38 +00:00
+ ", creatorID, inventoryBasePermissions, inventoryEveryOnePermissions, inventoryGroupPermissions, salePrice, saleType"
2008-04-30 19:28:36 +00:00
+ ", creationDate, groupID, groupOwned, flags) VALUES " ;
2007-10-30 09:05:31 +00:00
sql + =
2008-04-30 19:28:36 +00:00
"(?inventoryID, ?assetID, ?assetType, ?parentFolderID, ?avatarID, ?inventoryName, ?inventoryDescription"
+ ", ?inventoryNextPermissions, ?inventoryCurrentPermissions, ?invType, ?creatorID"
2008-11-14 18:54:38 +00:00
+ ", ?inventoryBasePermissions, ?inventoryEveryOnePermissions, ?inventoryGroupPermissions, ?salePrice, ?saleType, ?creationDate"
2008-04-30 19:28:36 +00:00
+ ", ?groupID, ?groupOwned, ?flags)" ;
2007-10-08 10:30:15 +00:00
2009-09-30 16:00:09 +00:00
string itemName = item . Name ;
2009-07-24 20:01:17 +00:00
if ( item . Name . Length > 64 )
{
itemName = item . Name . Substring ( 0 , 64 ) ;
m_log . Warn ( "[INVENTORY DB]: Name field truncated from " + item . Name . Length + " to " + itemName . Length + " characters on add item" ) ;
}
string itemDesc = item . Description ;
if ( item . Description . Length > 128 )
{
itemDesc = item . Description . Substring ( 0 , 128 ) ;
m_log . Warn ( "[INVENTORY DB]: Description field truncated from " + item . Description . Length + " to " + itemDesc . Length + " characters on add item" ) ;
2009-09-30 16:00:09 +00:00
}
2009-07-24 20:01:17 +00:00
2007-10-08 10:30:15 +00:00
try
2007-07-16 15:40:11 +00:00
{
2010-02-04 21:19:30 +00:00
using ( MySqlConnection dbcon = new MySqlConnection ( m_connectionString ) )
2008-04-18 22:46:03 +00:00
{
2010-02-04 21:19:30 +00:00
dbcon . Open ( ) ;
MySqlCommand result = new MySqlCommand ( sql , dbcon ) ;
result . Parameters . AddWithValue ( "?inventoryID" , item . ID . ToString ( ) ) ;
result . Parameters . AddWithValue ( "?assetID" , item . AssetID . ToString ( ) ) ;
result . Parameters . AddWithValue ( "?assetType" , item . AssetType . ToString ( ) ) ;
result . Parameters . AddWithValue ( "?parentFolderID" , item . Folder . ToString ( ) ) ;
result . Parameters . AddWithValue ( "?avatarID" , item . Owner . ToString ( ) ) ;
result . Parameters . AddWithValue ( "?inventoryName" , itemName ) ;
result . Parameters . AddWithValue ( "?inventoryDescription" , itemDesc ) ;
result . Parameters . AddWithValue ( "?inventoryNextPermissions" , item . NextPermissions . ToString ( ) ) ;
result . Parameters . AddWithValue ( "?inventoryCurrentPermissions" ,
item . CurrentPermissions . ToString ( ) ) ;
result . Parameters . AddWithValue ( "?invType" , item . InvType ) ;
result . Parameters . AddWithValue ( "?creatorID" , item . CreatorId ) ;
result . Parameters . AddWithValue ( "?inventoryBasePermissions" , item . BasePermissions ) ;
result . Parameters . AddWithValue ( "?inventoryEveryOnePermissions" , item . EveryOnePermissions ) ;
result . Parameters . AddWithValue ( "?inventoryGroupPermissions" , item . GroupPermissions ) ;
result . Parameters . AddWithValue ( "?salePrice" , item . SalePrice ) ;
result . Parameters . AddWithValue ( "?saleType" , unchecked ( ( sbyte ) item . SaleType ) ) ;
result . Parameters . AddWithValue ( "?creationDate" , item . CreationDate ) ;
result . Parameters . AddWithValue ( "?groupID" , item . GroupID ) ;
result . Parameters . AddWithValue ( "?groupOwned" , item . GroupOwned ) ;
result . Parameters . AddWithValue ( "?flags" , item . Flags ) ;
lock ( m_dbLock )
{
result . ExecuteNonQuery ( ) ;
}
2008-05-16 01:22:11 +00:00
2010-02-04 21:19:30 +00:00
result . Dispose ( ) ;
2009-03-22 16:12:48 +00:00
2010-02-04 21:19:30 +00:00
result = new MySqlCommand ( "update inventoryfolders set version=version+1 where folderID = ?folderID" , dbcon ) ;
result . Parameters . AddWithValue ( "?folderID" , item . Folder . ToString ( ) ) ;
lock ( m_dbLock )
{
result . ExecuteNonQuery ( ) ;
}
result . Dispose ( ) ;
2009-03-22 16:12:48 +00:00
}
2007-10-08 10:30:15 +00:00
}
catch ( MySqlException e )
{
2008-02-05 19:44:27 +00:00
m_log . Error ( e . ToString ( ) ) ;
2007-07-16 15:40:11 +00:00
}
}
/// <summary>
/// Updates the specified inventory item
/// </summary>
/// <param name="item">Inventory item to update</param>
public void updateInventoryItem ( InventoryItemBase item )
{
addInventoryItem ( item ) ;
}
2007-08-16 16:31:32 +00:00
/// <summary>
2008-06-26 12:38:03 +00:00
/// Detele the specified inventory item
2007-08-16 16:31:32 +00:00
/// </summary>
2008-06-26 12:38:03 +00:00
/// <param name="item">The inventory item UUID to delete</param>
2008-09-06 07:52:41 +00:00
public void deleteInventoryItem ( UUID itemID )
2007-08-16 16:31:32 +00:00
{
2007-10-08 10:30:15 +00:00
try
{
2010-02-04 21:19:30 +00:00
using ( MySqlConnection dbcon = new MySqlConnection ( m_connectionString ) )
{
dbcon . Open ( ) ;
2008-07-03 22:30:16 +00:00
2010-02-04 21:19:30 +00:00
MySqlCommand cmd = new MySqlCommand ( "DELETE FROM inventoryitems WHERE inventoryID=?uuid" , dbcon ) ;
cmd . Parameters . AddWithValue ( "?uuid" , itemID . ToString ( ) ) ;
2008-05-16 01:22:11 +00:00
2010-02-04 21:19:30 +00:00
lock ( m_dbLock )
{
cmd . ExecuteNonQuery ( ) ;
}
2008-04-18 22:46:03 +00:00
}
2007-10-08 10:30:15 +00:00
}
catch ( MySqlException e )
{
2010-02-04 21:19:30 +00:00
m_log . Error ( e . Message , e ) ;
2007-10-08 10:30:15 +00:00
}
2007-08-16 16:31:32 +00:00
}
2009-03-21 17:46:58 +00:00
public InventoryItemBase queryInventoryItem ( UUID itemID )
{
return getInventoryItem ( itemID ) ;
}
2009-03-23 00:11:34 +00:00
public InventoryFolderBase queryInventoryFolder ( UUID folderID )
{
return getInventoryFolder ( folderID ) ;
}
2007-07-16 15:40:11 +00:00
/// <summary>
/// Creates a new inventory folder
/// </summary>
/// <param name="folder">Folder to create</param>
public void addInventoryFolder ( InventoryFolderBase folder )
{
2007-10-30 09:05:31 +00:00
string sql =
"REPLACE INTO inventoryfolders (folderID, agentID, parentFolderID, folderName, type, version) VALUES " ;
2007-10-08 10:30:15 +00:00
sql + = "(?folderID, ?agentID, ?parentFolderID, ?folderName, ?type, ?version)" ;
2009-09-30 16:00:09 +00:00
string folderName = folder . Name ;
2009-07-24 20:01:17 +00:00
if ( folderName . Length > 64 )
{
folderName = folderName . Substring ( 0 , 64 ) ;
m_log . Warn ( "[INVENTORY DB]: Name field truncated from " + folder . Name . Length + " to " + folderName . Length + " characters on add folder" ) ;
2009-09-30 16:00:09 +00:00
}
2009-07-24 20:01:17 +00:00
2010-02-04 21:19:30 +00:00
using ( MySqlConnection dbcon = new MySqlConnection ( m_connectionString ) )
{
dbcon . Open ( ) ;
2008-07-03 22:30:16 +00:00
2010-02-04 21:19:30 +00:00
MySqlCommand cmd = new MySqlCommand ( sql , dbcon ) ;
cmd . Parameters . AddWithValue ( "?folderID" , folder . ID . ToString ( ) ) ;
cmd . Parameters . AddWithValue ( "?agentID" , folder . Owner . ToString ( ) ) ;
cmd . Parameters . AddWithValue ( "?parentFolderID" , folder . ParentID . ToString ( ) ) ;
cmd . Parameters . AddWithValue ( "?folderName" , folderName ) ;
cmd . Parameters . AddWithValue ( "?type" , folder . Type ) ;
cmd . Parameters . AddWithValue ( "?version" , folder . Version ) ;
2007-10-30 09:05:31 +00:00
2010-02-04 21:19:30 +00:00
try
2008-02-12 22:24:12 +00:00
{
2010-02-04 21:19:30 +00:00
lock ( m_dbLock )
{
cmd . ExecuteNonQuery ( ) ;
}
}
catch ( Exception e )
{
m_log . Error ( e . ToString ( ) ) ;
2008-02-12 22:24:12 +00:00
}
2007-07-16 15:40:11 +00:00
}
}
/// <summary>
/// Updates an inventory folder
/// </summary>
/// <param name="folder">Folder to update</param>
public void updateInventoryFolder ( InventoryFolderBase folder )
{
addInventoryFolder ( folder ) ;
}
2007-10-06 08:23:51 +00:00
2008-06-26 01:12:28 +00:00
/// <summary>
2008-06-26 12:38:03 +00:00
/// Move an inventory folder
2007-12-15 04:57:14 +00:00
/// </summary>
2008-06-26 12:38:03 +00:00
/// <param name="folder">Folder to move</param>
/// <remarks>UPDATE inventoryfolders SET parentFolderID=?parentFolderID WHERE folderID=?folderID</remarks>
2007-12-15 04:57:14 +00:00
public void moveInventoryFolder ( InventoryFolderBase folder )
{
string sql =
"UPDATE inventoryfolders SET parentFolderID=?parentFolderID WHERE folderID=?folderID" ;
2010-02-04 21:19:30 +00:00
using ( MySqlConnection dbcon = new MySqlConnection ( m_connectionString ) )
{
dbcon . Open ( ) ;
2008-07-03 22:30:16 +00:00
2010-02-04 21:19:30 +00:00
MySqlCommand cmd = new MySqlCommand ( sql , dbcon ) ;
cmd . Parameters . AddWithValue ( "?folderID" , folder . ID . ToString ( ) ) ;
cmd . Parameters . AddWithValue ( "?parentFolderID" , folder . ParentID . ToString ( ) ) ;
2007-12-15 04:57:14 +00:00
2010-02-04 21:19:30 +00:00
try
2008-02-12 22:24:12 +00:00
{
2010-02-04 21:19:30 +00:00
lock ( m_dbLock )
{
cmd . ExecuteNonQuery ( ) ;
}
}
catch ( Exception e )
{
m_log . Error ( e . ToString ( ) ) ;
2008-02-12 22:24:12 +00:00
}
2007-12-15 04:57:14 +00:00
}
}
2007-10-06 08:23:51 +00:00
2007-10-08 10:30:15 +00:00
/// <summary>
2008-05-16 01:22:11 +00:00
/// Append a list of all the child folders of a parent folder
2007-10-08 10:30:15 +00:00
/// </summary>
/// <param name="folders">list where folders will be appended</param>
/// <param name="parentID">ID of parent</param>
2008-09-06 07:52:41 +00:00
protected void getInventoryFolders ( ref List < InventoryFolderBase > folders , UUID parentID )
2007-10-08 10:30:15 +00:00
{
List < InventoryFolderBase > subfolderList = getInventoryFolders ( parentID ) ;
foreach ( InventoryFolderBase f in subfolderList )
folders . Add ( f ) ;
}
2007-10-30 09:05:31 +00:00
2008-06-26 01:12:28 +00:00
/// <summary>
2008-07-31 09:24:28 +00:00
/// See IInventoryDataPlugin
2008-06-26 01:12:28 +00:00
/// </summary>
/// <param name="parentID"></param>
/// <returns></returns>
2008-09-06 07:52:41 +00:00
public List < InventoryFolderBase > getFolderHierarchy ( UUID parentID )
2007-10-08 10:30:15 +00:00
{
2008-08-10 16:44:25 +00:00
/ * Note : There are subtle changes between this implementation of getFolderHierarchy and the previous one
* - We will only need to hit the database twice instead of n times .
* - We assume the database is well - formed - no stranded / dangling folders , all folders in heirarchy owned
* by the same person , each user only has 1 inventory heirarchy
2008-08-18 00:39:10 +00:00
* - The returned list is not ordered , instead of breadth - first ordered
2008-08-10 16:44:25 +00:00
There are basically 2 usage cases for getFolderHeirarchy :
1 ) Getting the user ' s entire inventory heirarchy when they log in
2008-08-18 00:39:10 +00:00
2 ) Finding a subfolder heirarchy to delete when emptying the trash .
2008-08-10 16:44:25 +00:00
This implementation will pull all inventory folders from the database , and then prune away any folder that
is not part of the requested sub - heirarchy . The theory is that it is cheaper to make 1 request from the
database than to make n requests . This pays off only if requested heirarchy is large .
By making this choice , we are making the worst case better at the cost of making the best case worse .
This way is generally better because we don ' t have to rebuild the connection / sql query per subfolder ,
even if we end up getting more data from the SQL server than we need .
- Francis
* /
try
{
List < InventoryFolderBase > folders = new List < InventoryFolderBase > ( ) ;
2010-02-04 21:19:30 +00:00
Dictionary < UUID , List < InventoryFolderBase > > hashtable = new Dictionary < UUID , List < InventoryFolderBase > > ( ) ; ;
2008-08-10 16:44:25 +00:00
List < InventoryFolderBase > parentFolder = new List < InventoryFolderBase > ( ) ;
2010-02-04 21:19:30 +00:00
bool buildResultsFromHashTable = false ;
2007-10-08 10:30:15 +00:00
2010-02-04 21:19:30 +00:00
lock ( m_dbLock )
{
using ( MySqlConnection dbcon = new MySqlConnection ( m_connectionString ) )
2008-08-10 16:44:25 +00:00
{
2010-02-04 21:19:30 +00:00
dbcon . Open ( ) ;
/ * Fetch the parent folder from the database to determine the agent ID , and if
* we ' re querying the root of the inventory folder tree * /
using ( MySqlCommand result = new MySqlCommand ( "SELECT * FROM inventoryfolders WHERE folderID = ?uuid" , dbcon ) )
2008-08-10 16:44:25 +00:00
{
2010-02-04 21:19:30 +00:00
result . Parameters . AddWithValue ( "?uuid" , parentID . ToString ( ) ) ;
using ( MySqlDataReader reader = result . ExecuteReader ( ) )
2008-08-10 16:44:25 +00:00
{
2010-02-04 21:19:30 +00:00
// Should be at most 1 result
while ( reader . Read ( ) )
parentFolder . Add ( readInventoryFolder ( reader ) ) ;
2008-08-10 16:44:25 +00:00
}
2010-02-04 21:19:30 +00:00
}
if ( parentFolder . Count > = 1 ) // No result means parent folder does not exist
2008-08-10 16:44:25 +00:00
{
2010-02-04 21:19:30 +00:00
if ( parentFolder [ 0 ] . ParentID = = UUID . Zero ) // We are querying the root folder
2008-08-10 16:44:25 +00:00
{
2010-02-04 21:19:30 +00:00
/* Get all of the agent's folders from the database, put them in a list and return it */
using ( MySqlCommand result = new MySqlCommand ( "SELECT * FROM inventoryfolders WHERE agentID = ?uuid" , dbcon ) )
2008-08-10 16:44:25 +00:00
{
2010-02-04 21:19:30 +00:00
result . Parameters . AddWithValue ( "?uuid" , parentFolder [ 0 ] . Owner . ToString ( ) ) ;
using ( MySqlDataReader reader = result . ExecuteReader ( ) )
{
while ( reader . Read ( ) )
{
InventoryFolderBase curFolder = readInventoryFolder ( reader ) ;
if ( curFolder . ID ! = parentID ) // Do not need to add the root node of the tree to the list
folders . Add ( curFolder ) ;
}
}
}
} // if we are querying the root folder
else // else we are querying a subtree of the inventory folder tree
{
/ * Get all of the agent ' s folders from the database , put them all in a hash table
* indexed by their parent ID * /
using ( MySqlCommand result = new MySqlCommand ( "SELECT * FROM inventoryfolders WHERE agentID = ?uuid" , dbcon ) )
{
result . Parameters . AddWithValue ( "?uuid" , parentFolder [ 0 ] . Owner . ToString ( ) ) ;
using ( MySqlDataReader reader = result . ExecuteReader ( ) )
{
while ( reader . Read ( ) )
{
InventoryFolderBase curFolder = readInventoryFolder ( reader ) ;
if ( hashtable . ContainsKey ( curFolder . ParentID ) ) // Current folder already has a sibling
hashtable [ curFolder . ParentID ] . Add ( curFolder ) ; // append to sibling list
else // else current folder has no known (yet) siblings
{
List < InventoryFolderBase > siblingList = new List < InventoryFolderBase > ( ) ;
siblingList . Add ( curFolder ) ;
// Current folder has no known (yet) siblings
hashtable . Add ( curFolder . ParentID , siblingList ) ;
}
} // while more items to read from the database
}
2008-08-10 16:44:25 +00:00
}
2010-02-04 21:19:30 +00:00
// Set flag so we know we need to build the results from the hash table after
// we unlock the database
buildResultsFromHashTable = true ;
2008-08-10 16:44:25 +00:00
2010-02-04 21:19:30 +00:00
} // else we are querying a subtree of the inventory folder tree
} // if folder parentID exists
2008-08-10 16:44:25 +00:00
2010-02-04 21:19:30 +00:00
if ( buildResultsFromHashTable )
{
/ * We have all of the user ' s folders stored in a hash table indexed by their parent ID
* and we need to return the requested subtree . We will build the requested subtree
* by performing a breadth - first - search on the hash table * /
if ( hashtable . ContainsKey ( parentID ) )
folders . AddRange ( hashtable [ parentID ] ) ;
for ( int i = 0 ; i < folders . Count ; i + + ) // **Note: folders.Count is *not* static
if ( hashtable . ContainsKey ( folders [ i ] . ID ) )
folders . AddRange ( hashtable [ folders [ i ] . ID ] ) ;
}
2008-08-10 16:44:25 +00:00
}
2008-08-12 00:08:41 +00:00
} // lock (database)
2010-02-04 21:19:30 +00:00
2008-08-10 16:44:25 +00:00
return folders ;
}
catch ( Exception e )
{
2010-02-04 21:19:30 +00:00
m_log . Error ( e . Message , e ) ;
2008-08-10 16:44:25 +00:00
return null ;
}
2007-10-08 10:30:15 +00:00
}
2008-06-26 01:12:28 +00:00
/// <summary>
/// Delete a folder from database
/// </summary>
/// <param name="folderID">the folder UUID</param>
2008-09-06 07:52:41 +00:00
protected void deleteOneFolder ( UUID folderID )
2007-10-08 10:30:15 +00:00
{
try
2008-05-16 01:22:11 +00:00
{
2010-02-04 21:19:30 +00:00
using ( MySqlConnection dbcon = new MySqlConnection ( m_connectionString ) )
{
dbcon . Open ( ) ;
2008-07-03 22:30:16 +00:00
2011-10-31 09:18:25 +00:00
// System folders can never be deleted. Period.
using ( MySqlCommand cmd = new MySqlCommand ( "DELETE FROM inventoryfolders WHERE folderID=?uuid and type=-1" , dbcon ) )
2010-02-04 21:19:30 +00:00
{
cmd . Parameters . AddWithValue ( "?uuid" , folderID . ToString ( ) ) ;
2009-10-04 20:57:51 +00:00
2010-02-04 21:19:30 +00:00
lock ( m_dbLock )
cmd . ExecuteNonQuery ( ) ;
}
2008-02-12 22:24:12 +00:00
}
2007-10-08 10:30:15 +00:00
}
catch ( MySqlException e )
{
2010-02-04 21:19:30 +00:00
m_log . Error ( e . Message , e ) ;
2007-10-08 10:30:15 +00:00
}
}
2008-06-26 01:12:28 +00:00
/// <summary>
/// Delete all item in a folder
/// </summary>
/// <param name="folderID">the folder UUID</param>
2008-09-06 07:52:41 +00:00
protected void deleteItemsInFolder ( UUID folderID )
2007-10-08 10:30:15 +00:00
{
try
{
2010-02-04 21:19:30 +00:00
using ( MySqlConnection dbcon = new MySqlConnection ( m_connectionString ) )
{
dbcon . Open ( ) ;
2008-07-03 22:30:16 +00:00
2010-02-04 21:19:30 +00:00
using ( MySqlCommand cmd = new MySqlCommand ( "DELETE FROM inventoryitems WHERE parentFolderID=?uuid" , dbcon ) )
{
cmd . Parameters . AddWithValue ( "?uuid" , folderID . ToString ( ) ) ;
2009-10-04 20:57:51 +00:00
2010-02-04 21:19:30 +00:00
lock ( m_dbLock )
cmd . ExecuteNonQuery ( ) ;
}
2008-02-12 22:24:12 +00:00
}
2007-10-08 10:30:15 +00:00
}
catch ( MySqlException e )
{
2008-02-05 19:44:27 +00:00
m_log . Error ( e . ToString ( ) ) ;
2007-10-08 10:30:15 +00:00
}
}
2007-10-06 08:23:51 +00:00
/// <summary>
2008-04-23 17:04:15 +00:00
/// Deletes an inventory folder
2007-10-06 08:23:51 +00:00
/// </summary>
/// <param name="folderId">Id of folder to delete</param>
2008-09-06 07:52:41 +00:00
public void deleteInventoryFolder ( UUID folderID )
2007-10-06 08:23:51 +00:00
{
2008-02-12 22:24:12 +00:00
List < InventoryFolderBase > subFolders = getFolderHierarchy ( folderID ) ;
2007-10-08 10:30:15 +00:00
2010-02-04 21:19:30 +00:00
//Delete all sub-folders
foreach ( InventoryFolderBase f in subFolders )
2008-02-12 22:24:12 +00:00
{
2010-02-04 21:19:30 +00:00
deleteOneFolder ( f . ID ) ;
deleteItemsInFolder ( f . ID ) ;
2007-10-08 10:30:15 +00:00
}
2008-02-12 22:24:12 +00:00
//Delete the actual row
deleteOneFolder ( folderID ) ;
2010-02-04 21:19:30 +00:00
deleteItemsInFolder ( folderID ) ;
2007-10-06 08:23:51 +00:00
}
2008-09-24 21:12:21 +00:00
public List < InventoryItemBase > fetchActiveGestures ( UUID avatarID )
{
2010-02-04 21:19:30 +00:00
lock ( m_dbLock )
2008-09-24 21:12:21 +00:00
{
try
{
2010-02-04 21:19:30 +00:00
using ( MySqlConnection dbcon = new MySqlConnection ( m_connectionString ) )
2009-11-02 19:19:55 +00:00
{
2010-02-04 21:19:30 +00:00
dbcon . Open ( ) ;
using ( MySqlCommand sqlCmd = new MySqlCommand (
2011-01-17 23:55:08 +00:00
"SELECT * FROM inventoryitems WHERE avatarId = ?uuid AND assetType = ?type and flags & 1" , dbcon ) )
2010-02-04 21:19:30 +00:00
{
sqlCmd . Parameters . AddWithValue ( "?uuid" , avatarID . ToString ( ) ) ;
sqlCmd . Parameters . AddWithValue ( "?type" , ( int ) AssetType . Gesture ) ;
using ( MySqlDataReader result = sqlCmd . ExecuteReader ( ) )
{
List < InventoryItemBase > list = new List < InventoryItemBase > ( ) ;
while ( result . Read ( ) )
{
InventoryItemBase item = readInventoryItem ( result ) ;
if ( item ! = null )
list . Add ( item ) ;
}
return list ;
}
}
2008-11-13 22:53:49 +00:00
}
2008-09-24 21:12:21 +00:00
}
catch ( Exception e )
{
2010-02-04 21:19:30 +00:00
m_log . Error ( e . Message , e ) ;
2008-09-24 21:12:21 +00:00
return null ;
}
}
}
2007-07-16 15:40:11 +00:00
}
2008-03-18 05:16:43 +00:00
}