MSSQLInventoryData.cs 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818
  1. /*
  2. * Copyright (c) Contributors, http://opensimulator.org/
  3. * See CONTRIBUTORS.TXT for a full list of copyright holders.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. * * Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * * Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. * * Neither the name of the OpenSimulator Project nor the
  13. * names of its contributors may be used to endorse or promote products
  14. * derived from this software without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
  17. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  18. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  19. * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
  20. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  21. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  22. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  23. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  25. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. using System;
  28. using System.Collections.Generic;
  29. using System.Data;
  30. using System.Data.SqlClient;
  31. using System.Reflection;
  32. using log4net;
  33. using OpenMetaverse;
  34. using OpenSim.Framework;
  35. namespace OpenSim.Data.MSSQL
  36. {
  37. /// <summary>
  38. /// A MSSQL interface for the inventory server
  39. /// </summary>
  40. public class MSSQLInventoryData : IInventoryDataPlugin
  41. {
  42. private const string _migrationStore = "InventoryStore";
  43. private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
  44. /// <summary>
  45. /// The database manager
  46. /// </summary>
  47. private MSSQLManager database;
  48. #region IPlugin members
  49. [Obsolete("Cannot be default-initialized!")]
  50. public void Initialise()
  51. {
  52. m_log.Info("[MSSQLInventoryData]: " + Name + " cannot be default-initialized!");
  53. throw new PluginNotInitialisedException(Name);
  54. }
  55. /// <summary>
  56. /// Loads and initialises the MSSQL inventory storage interface
  57. /// </summary>
  58. /// <param name="connectionString">connect string</param>
  59. /// <remarks>use mssql_connection.ini</remarks>
  60. public void Initialise(string connectionString)
  61. {
  62. if (!string.IsNullOrEmpty(connectionString))
  63. {
  64. database = new MSSQLManager(connectionString);
  65. }
  66. else
  67. {
  68. IniFile gridDataMSSqlFile = new IniFile("mssql_connection.ini");
  69. string settingDataSource = gridDataMSSqlFile.ParseFileReadValue("data_source");
  70. string settingInitialCatalog = gridDataMSSqlFile.ParseFileReadValue("initial_catalog");
  71. string settingPersistSecurityInfo = gridDataMSSqlFile.ParseFileReadValue("persist_security_info");
  72. string settingUserId = gridDataMSSqlFile.ParseFileReadValue("user_id");
  73. string settingPassword = gridDataMSSqlFile.ParseFileReadValue("password");
  74. database =
  75. new MSSQLManager(settingDataSource, settingInitialCatalog, settingPersistSecurityInfo, settingUserId,
  76. settingPassword);
  77. }
  78. //New migrations check of store
  79. database.CheckMigration(_migrationStore);
  80. }
  81. /// <summary>
  82. /// The name of this DB provider
  83. /// </summary>
  84. /// <returns>A string containing the name of the DB provider</returns>
  85. public string Name
  86. {
  87. get { return "MSSQL Inventory Data Interface"; }
  88. }
  89. /// <summary>
  90. /// Closes this DB provider
  91. /// </summary>
  92. public void Dispose()
  93. {
  94. database = null;
  95. }
  96. /// <summary>
  97. /// Returns the version of this DB provider
  98. /// </summary>
  99. /// <returns>A string containing the DB provider</returns>
  100. public string Version
  101. {
  102. get { return database.getVersion(); }
  103. }
  104. #endregion
  105. #region Folder methods
  106. /// <summary>
  107. /// Returns a list of the root folders within a users inventory
  108. /// </summary>
  109. /// <param name="user">The user whos inventory is to be searched</param>
  110. /// <returns>A list of folder objects</returns>
  111. public List<InventoryFolderBase> getUserRootFolders(UUID user)
  112. {
  113. return getInventoryFolders(UUID.Zero, user);
  114. }
  115. /// <summary>
  116. /// see InventoryItemBase.getUserRootFolder
  117. /// </summary>
  118. /// <param name="user">the User UUID</param>
  119. /// <returns></returns>
  120. public InventoryFolderBase getUserRootFolder(UUID user)
  121. {
  122. List<InventoryFolderBase> items = getUserRootFolders(user);
  123. InventoryFolderBase rootFolder = null;
  124. // There should only ever be one root folder for a user. However, if there's more
  125. // than one we'll simply use the first one rather than failing. It would be even
  126. // nicer to print some message to this effect, but this feels like it's too low a
  127. // to put such a message out, and it's too minor right now to spare the time to
  128. // suitably refactor.
  129. if (items.Count > 0)
  130. {
  131. rootFolder = items[0];
  132. }
  133. return rootFolder;
  134. }
  135. /// <summary>
  136. /// Returns a list of folders in a users inventory contained within the specified folder
  137. /// </summary>
  138. /// <param name="parentID">The folder to search</param>
  139. /// <returns>A list of inventory folders</returns>
  140. public List<InventoryFolderBase> getInventoryFolders(UUID parentID)
  141. {
  142. return getInventoryFolders(parentID, UUID.Zero);
  143. }
  144. /// <summary>
  145. /// Returns a specified inventory folder
  146. /// </summary>
  147. /// <param name="folderID">The folder to return</param>
  148. /// <returns>A folder class</returns>
  149. public InventoryFolderBase getInventoryFolder(UUID folderID)
  150. {
  151. using (AutoClosingSqlCommand command = database.Query("SELECT * FROM inventoryfolders WHERE folderID = @folderID"))
  152. {
  153. command.Parameters.Add(database.CreateParameter("folderID", folderID));
  154. using (IDataReader reader = command.ExecuteReader())
  155. {
  156. if (reader.Read())
  157. {
  158. return readInventoryFolder(reader);
  159. }
  160. }
  161. }
  162. m_log.InfoFormat("[INVENTORY DB] : Found no inventory folder with ID : {0}", folderID);
  163. return null;
  164. }
  165. /// <summary>
  166. /// Returns all child folders in the hierarchy from the parent folder and down.
  167. /// Does not return the parent folder itself.
  168. /// </summary>
  169. /// <param name="parentID">The folder to get subfolders for</param>
  170. /// <returns>A list of inventory folders</returns>
  171. public List<InventoryFolderBase> getFolderHierarchy(UUID parentID)
  172. {
  173. //Note maybe change this to use a Dataset that loading in all folders of a user and then go throw it that way.
  174. //Note this is changed so it opens only one connection to the database and not everytime it wants to get data.
  175. List<InventoryFolderBase> folders = new List<InventoryFolderBase>();
  176. using (AutoClosingSqlCommand command = database.Query("SELECT * FROM inventoryfolders WHERE parentFolderID = @parentID"))
  177. {
  178. command.Parameters.Add(database.CreateParameter("@parentID", parentID));
  179. folders.AddRange(getInventoryFolders(command));
  180. List<InventoryFolderBase> tempFolders = new List<InventoryFolderBase>();
  181. foreach (InventoryFolderBase folderBase in folders)
  182. {
  183. tempFolders.AddRange(getFolderHierarchy(folderBase.ID, command));
  184. }
  185. if (tempFolders.Count > 0)
  186. {
  187. folders.AddRange(tempFolders);
  188. }
  189. }
  190. return folders;
  191. }
  192. /// <summary>
  193. /// Creates a new inventory folder
  194. /// </summary>
  195. /// <param name="folder">Folder to create</param>
  196. public void addInventoryFolder(InventoryFolderBase folder)
  197. {
  198. string sql = @"INSERT INTO inventoryfolders ([folderID], [agentID], [parentFolderID], [folderName], [type], [version])
  199. VALUES (@folderID, @agentID, @parentFolderID, @folderName, @type, @version);";
  200. string folderName = folder.Name;
  201. if (folderName.Length > 64)
  202. {
  203. folderName = folderName.Substring(0, 64);
  204. m_log.Warn("[INVENTORY DB]: Name field truncated from " + folder.Name.Length.ToString() + " to " + folderName.Length + " characters on add");
  205. }
  206. using (AutoClosingSqlCommand command = database.Query(sql))
  207. {
  208. command.Parameters.Add(database.CreateParameter("folderID", folder.ID));
  209. command.Parameters.Add(database.CreateParameter("agentID", folder.Owner));
  210. command.Parameters.Add(database.CreateParameter("parentFolderID", folder.ParentID));
  211. command.Parameters.Add(database.CreateParameter("folderName", folderName));
  212. command.Parameters.Add(database.CreateParameter("type", folder.Type));
  213. command.Parameters.Add(database.CreateParameter("version", folder.Version));
  214. try
  215. {
  216. //IDbCommand result = database.Query(sql, param);
  217. command.ExecuteNonQuery();
  218. }
  219. catch (Exception e)
  220. {
  221. m_log.ErrorFormat("[INVENTORY DB]: Error : {0}", e.Message);
  222. }
  223. }
  224. }
  225. /// <summary>
  226. /// Updates an inventory folder
  227. /// </summary>
  228. /// <param name="folder">Folder to update</param>
  229. public void updateInventoryFolder(InventoryFolderBase folder)
  230. {
  231. string sql = @"UPDATE inventoryfolders SET folderID = @folderID,
  232. agentID = @agentID,
  233. parentFolderID = @parentFolderID,
  234. folderName = @folderName,
  235. type = @type,
  236. version = @version
  237. WHERE folderID = @keyFolderID";
  238. string folderName = folder.Name;
  239. if (folderName.Length > 64)
  240. {
  241. folderName = folderName.Substring(0, 64);
  242. m_log.Warn("[INVENTORY DB]: Name field truncated from " + folder.Name.Length.ToString() + " to " + folderName.Length + " characters on update");
  243. }
  244. using (AutoClosingSqlCommand command = database.Query(sql))
  245. {
  246. command.Parameters.Add(database.CreateParameter("folderID", folder.ID));
  247. command.Parameters.Add(database.CreateParameter("agentID", folder.Owner));
  248. command.Parameters.Add(database.CreateParameter("parentFolderID", folder.ParentID));
  249. command.Parameters.Add(database.CreateParameter("folderName", folderName));
  250. command.Parameters.Add(database.CreateParameter("type", folder.Type));
  251. command.Parameters.Add(database.CreateParameter("version", folder.Version));
  252. command.Parameters.Add(database.CreateParameter("@keyFolderID", folder.ID));
  253. try
  254. {
  255. command.ExecuteNonQuery();
  256. }
  257. catch (Exception e)
  258. {
  259. m_log.ErrorFormat("[INVENTORY DB]: Error : {0}", e.Message);
  260. }
  261. }
  262. }
  263. /// <summary>
  264. /// Updates an inventory folder
  265. /// </summary>
  266. /// <param name="folder">Folder to update</param>
  267. public void moveInventoryFolder(InventoryFolderBase folder)
  268. {
  269. string sql = @"UPDATE inventoryfolders SET parentFolderID = @parentFolderID WHERE folderID = @folderID";
  270. using (IDbCommand command = database.Query(sql))
  271. {
  272. command.Parameters.Add(database.CreateParameter("parentFolderID", folder.ParentID));
  273. command.Parameters.Add(database.CreateParameter("@folderID", folder.ID));
  274. try
  275. {
  276. command.ExecuteNonQuery();
  277. }
  278. catch (Exception e)
  279. {
  280. m_log.ErrorFormat("[INVENTORY DB]: Error : {0}", e.Message);
  281. }
  282. }
  283. }
  284. /// <summary>
  285. /// Delete an inventory folder
  286. /// </summary>
  287. /// <param name="folderID">Id of folder to delete</param>
  288. public void deleteInventoryFolder(UUID folderID)
  289. {
  290. using (SqlConnection connection = database.DatabaseConnection())
  291. {
  292. List<InventoryFolderBase> subFolders;
  293. using (SqlCommand command = new SqlCommand("SELECT * FROM inventoryfolders WHERE parentFolderID = @parentID", connection))
  294. {
  295. command.Parameters.Add(database.CreateParameter("@parentID", UUID.Zero));
  296. AutoClosingSqlCommand autoCommand = new AutoClosingSqlCommand(command);
  297. subFolders = getFolderHierarchy(folderID, autoCommand);
  298. }
  299. //Delete all sub-folders
  300. foreach (InventoryFolderBase f in subFolders)
  301. {
  302. DeleteOneFolder(f.ID, connection);
  303. DeleteItemsInFolder(f.ID, connection);
  304. }
  305. //Delete the actual row
  306. DeleteOneFolder(folderID, connection);
  307. DeleteItemsInFolder(folderID, connection);
  308. connection.Close();
  309. }
  310. }
  311. #endregion
  312. #region Item Methods
  313. /// <summary>
  314. /// Returns a list of items in a specified folder
  315. /// </summary>
  316. /// <param name="folderID">The folder to search</param>
  317. /// <returns>A list containing inventory items</returns>
  318. public List<InventoryItemBase> getInventoryInFolder(UUID folderID)
  319. {
  320. using (AutoClosingSqlCommand command = database.Query("SELECT * FROM inventoryitems WHERE parentFolderID = @parentFolderID"))
  321. {
  322. command.Parameters.Add(database.CreateParameter("parentFolderID", folderID));
  323. List<InventoryItemBase> items = new List<InventoryItemBase>();
  324. using (SqlDataReader reader = command.ExecuteReader())
  325. {
  326. while (reader.Read())
  327. {
  328. items.Add(readInventoryItem(reader));
  329. }
  330. }
  331. return items;
  332. }
  333. }
  334. /// <summary>
  335. /// Returns a specified inventory item
  336. /// </summary>
  337. /// <param name="itemID">The item ID</param>
  338. /// <returns>An inventory item</returns>
  339. public InventoryItemBase getInventoryItem(UUID itemID)
  340. {
  341. using (AutoClosingSqlCommand result = database.Query("SELECT * FROM inventoryitems WHERE inventoryID = @inventoryID"))
  342. {
  343. result.Parameters.Add(database.CreateParameter("inventoryID", itemID));
  344. using (IDataReader reader = result.ExecuteReader())
  345. {
  346. if (reader.Read())
  347. {
  348. return readInventoryItem(reader);
  349. }
  350. }
  351. }
  352. m_log.InfoFormat("[INVENTORY DB]: Found no inventory item with ID : {0}", itemID);
  353. return null;
  354. }
  355. /// <summary>
  356. /// Adds a specified item to the database
  357. /// </summary>
  358. /// <param name="item">The inventory item</param>
  359. public void addInventoryItem(InventoryItemBase item)
  360. {
  361. if (getInventoryItem(item.ID) != null)
  362. {
  363. updateInventoryItem(item);
  364. return;
  365. }
  366. string sql = @"INSERT INTO inventoryitems
  367. ([inventoryID], [assetID], [assetType], [parentFolderID], [avatarID], [inventoryName],
  368. [inventoryDescription], [inventoryNextPermissions], [inventoryCurrentPermissions],
  369. [invType], [creatorID], [inventoryBasePermissions], [inventoryEveryOnePermissions], [inventoryGroupPermissions],
  370. [salePrice], [saleType], [creationDate], [groupID], [groupOwned], [flags])
  371. VALUES
  372. (@inventoryID, @assetID, @assetType, @parentFolderID, @avatarID, @inventoryName, @inventoryDescription,
  373. @inventoryNextPermissions, @inventoryCurrentPermissions, @invType, @creatorID,
  374. @inventoryBasePermissions, @inventoryEveryOnePermissions, @inventoryGroupPermissions, @salePrice, @saleType,
  375. @creationDate, @groupID, @groupOwned, @flags)";
  376. string itemName = item.Name;
  377. if (item.Name.Length > 64)
  378. {
  379. itemName = item.Name.Substring(0, 64);
  380. m_log.Warn("[INVENTORY DB]: Name field truncated from " + item.Name.Length.ToString() + " to " + itemName.Length.ToString() + " characters");
  381. }
  382. string itemDesc = item.Description;
  383. if (item.Description.Length > 128)
  384. {
  385. itemDesc = item.Description.Substring(0, 128);
  386. m_log.Warn("[INVENTORY DB]: Description field truncated from " + item.Description.Length.ToString() + " to " + itemDesc.Length.ToString() + " characters");
  387. }
  388. using (AutoClosingSqlCommand command = database.Query(sql))
  389. {
  390. command.Parameters.Add(database.CreateParameter("inventoryID", item.ID));
  391. command.Parameters.Add(database.CreateParameter("assetID", item.AssetID));
  392. command.Parameters.Add(database.CreateParameter("assetType", item.AssetType));
  393. command.Parameters.Add(database.CreateParameter("parentFolderID", item.Folder));
  394. command.Parameters.Add(database.CreateParameter("avatarID", item.Owner));
  395. command.Parameters.Add(database.CreateParameter("inventoryName", itemName));
  396. command.Parameters.Add(database.CreateParameter("inventoryDescription", itemDesc));
  397. command.Parameters.Add(database.CreateParameter("inventoryNextPermissions", item.NextPermissions));
  398. command.Parameters.Add(database.CreateParameter("inventoryCurrentPermissions", item.CurrentPermissions));
  399. command.Parameters.Add(database.CreateParameter("invType", item.InvType));
  400. command.Parameters.Add(database.CreateParameter("creatorID", item.CreatorId));
  401. command.Parameters.Add(database.CreateParameter("inventoryBasePermissions", item.BasePermissions));
  402. command.Parameters.Add(database.CreateParameter("inventoryEveryOnePermissions", item.EveryOnePermissions));
  403. command.Parameters.Add(database.CreateParameter("inventoryGroupPermissions", item.GroupPermissions));
  404. command.Parameters.Add(database.CreateParameter("salePrice", item.SalePrice));
  405. command.Parameters.Add(database.CreateParameter("saleType", item.SaleType));
  406. command.Parameters.Add(database.CreateParameter("creationDate", item.CreationDate));
  407. command.Parameters.Add(database.CreateParameter("groupID", item.GroupID));
  408. command.Parameters.Add(database.CreateParameter("groupOwned", item.GroupOwned));
  409. command.Parameters.Add(database.CreateParameter("flags", item.Flags));
  410. try
  411. {
  412. command.ExecuteNonQuery();
  413. }
  414. catch (Exception e)
  415. {
  416. m_log.Error("[INVENTORY DB]: Error inserting item :" + e.Message);
  417. }
  418. }
  419. sql = "UPDATE inventoryfolders SET version = version + 1 WHERE folderID = @folderID";
  420. using (AutoClosingSqlCommand command = database.Query(sql))
  421. {
  422. command.Parameters.Add(database.CreateParameter("folderID", item.Folder.ToString()));
  423. try
  424. {
  425. command.ExecuteNonQuery();
  426. }
  427. catch (Exception e)
  428. {
  429. m_log.Error("[INVENTORY DB] Error updating inventory folder for new item :" + e.Message);
  430. }
  431. }
  432. }
  433. /// <summary>
  434. /// Updates the specified inventory item
  435. /// </summary>
  436. /// <param name="item">Inventory item to update</param>
  437. public void updateInventoryItem(InventoryItemBase item)
  438. {
  439. string sql = @"UPDATE inventoryitems SET inventoryID = @inventoryID,
  440. assetID = @assetID,
  441. assetType = @assetType,
  442. parentFolderID = @parentFolderID,
  443. avatarID = @avatarID,
  444. inventoryName = @inventoryName,
  445. inventoryDescription = @inventoryDescription,
  446. inventoryNextPermissions = @inventoryNextPermissions,
  447. inventoryCurrentPermissions = @inventoryCurrentPermissions,
  448. invType = @invType,
  449. creatorID = @creatorID,
  450. inventoryBasePermissions = @inventoryBasePermissions,
  451. inventoryEveryOnePermissions = @inventoryEveryOnePermissions,
  452. salePrice = @salePrice,
  453. saleType = @saleType,
  454. creationDate = @creationDate,
  455. groupID = @groupID,
  456. groupOwned = @groupOwned,
  457. flags = @flags
  458. WHERE inventoryID = @keyInventoryID";
  459. string itemName = item.Name;
  460. if (item.Name.Length > 64)
  461. {
  462. itemName = item.Name.Substring(0, 64);
  463. m_log.Warn("[INVENTORY DB]: Name field truncated from " + item.Name.Length.ToString() + " to " + itemName.Length.ToString() + " characters on update");
  464. }
  465. string itemDesc = item.Description;
  466. if (item.Description.Length > 128)
  467. {
  468. itemDesc = item.Description.Substring(0, 128);
  469. m_log.Warn("[INVENTORY DB]: Description field truncated from " + item.Description.Length.ToString() + " to " + itemDesc.Length.ToString() + " characters on update");
  470. }
  471. using (AutoClosingSqlCommand command = database.Query(sql))
  472. {
  473. command.Parameters.Add(database.CreateParameter("inventoryID", item.ID));
  474. command.Parameters.Add(database.CreateParameter("assetID", item.AssetID));
  475. command.Parameters.Add(database.CreateParameter("assetType", item.AssetType));
  476. command.Parameters.Add(database.CreateParameter("parentFolderID", item.Folder));
  477. command.Parameters.Add(database.CreateParameter("avatarID", item.Owner));
  478. command.Parameters.Add(database.CreateParameter("inventoryName", itemName));
  479. command.Parameters.Add(database.CreateParameter("inventoryDescription", itemDesc));
  480. command.Parameters.Add(database.CreateParameter("inventoryNextPermissions", item.NextPermissions));
  481. command.Parameters.Add(database.CreateParameter("inventoryCurrentPermissions", item.CurrentPermissions));
  482. command.Parameters.Add(database.CreateParameter("invType", item.InvType));
  483. command.Parameters.Add(database.CreateParameter("creatorID", item.CreatorIdAsUuid));
  484. command.Parameters.Add(database.CreateParameter("inventoryBasePermissions", item.BasePermissions));
  485. command.Parameters.Add(database.CreateParameter("inventoryEveryOnePermissions", item.EveryOnePermissions));
  486. command.Parameters.Add(database.CreateParameter("salePrice", item.SalePrice));
  487. command.Parameters.Add(database.CreateParameter("saleType", item.SaleType));
  488. command.Parameters.Add(database.CreateParameter("creationDate", item.CreationDate));
  489. command.Parameters.Add(database.CreateParameter("groupID", item.GroupID));
  490. command.Parameters.Add(database.CreateParameter("groupOwned", item.GroupOwned));
  491. command.Parameters.Add(database.CreateParameter("flags", item.Flags));
  492. command.Parameters.Add(database.CreateParameter("@keyInventoryID", item.ID));
  493. try
  494. {
  495. command.ExecuteNonQuery();
  496. }
  497. catch (Exception e)
  498. {
  499. m_log.Error("[INVENTORY DB]: Error updating item :" + e.Message);
  500. }
  501. }
  502. }
  503. // See IInventoryDataPlugin
  504. /// <summary>
  505. /// Delete an item in inventory database
  506. /// </summary>
  507. /// <param name="itemID">the item UUID</param>
  508. public void deleteInventoryItem(UUID itemID)
  509. {
  510. using (AutoClosingSqlCommand command = database.Query("DELETE FROM inventoryitems WHERE inventoryID=@inventoryID"))
  511. {
  512. command.Parameters.Add(database.CreateParameter("inventoryID", itemID));
  513. try
  514. {
  515. command.ExecuteNonQuery();
  516. }
  517. catch (Exception e)
  518. {
  519. m_log.Error("[INVENTORY DB]: Error deleting item :" + e.Message);
  520. }
  521. }
  522. }
  523. public InventoryItemBase queryInventoryItem(UUID itemID)
  524. {
  525. return getInventoryItem(itemID);
  526. }
  527. public InventoryFolderBase queryInventoryFolder(UUID folderID)
  528. {
  529. return getInventoryFolder(folderID);
  530. }
  531. /// <summary>
  532. /// Returns all activated gesture-items in the inventory of the specified avatar.
  533. /// </summary>
  534. /// <param name="avatarID">The <see cref="UUID"/> of the avatar</param>
  535. /// <returns>
  536. /// The list of gestures (<see cref="InventoryItemBase"/>s)
  537. /// </returns>
  538. public List<InventoryItemBase> fetchActiveGestures(UUID avatarID)
  539. {
  540. using (AutoClosingSqlCommand command = database.Query("SELECT * FROM inventoryitems WHERE avatarId = @uuid AND assetType = @assetType and flags = 1"))
  541. {
  542. command.Parameters.Add(database.CreateParameter("uuid", avatarID));
  543. command.Parameters.Add(database.CreateParameter("assetType", (int)AssetType.Gesture));
  544. using (IDataReader reader = command.ExecuteReader())
  545. {
  546. List<InventoryItemBase> gestureList = new List<InventoryItemBase>();
  547. while (reader.Read())
  548. {
  549. gestureList.Add(readInventoryItem(reader));
  550. }
  551. return gestureList;
  552. }
  553. }
  554. }
  555. #endregion
  556. #region Private methods
  557. /// <summary>
  558. /// Delete an item in inventory database
  559. /// </summary>
  560. /// <param name="folderID">the item ID</param>
  561. /// <param name="connection">connection to the database</param>
  562. private void DeleteItemsInFolder(UUID folderID, SqlConnection connection)
  563. {
  564. using (SqlCommand command = new SqlCommand("DELETE FROM inventoryitems WHERE folderID=@folderID", connection))
  565. {
  566. command.Parameters.Add(database.CreateParameter("folderID", folderID));
  567. try
  568. {
  569. command.ExecuteNonQuery();
  570. }
  571. catch (Exception e)
  572. {
  573. m_log.Error("[INVENTORY DB] Error deleting item :" + e.Message);
  574. }
  575. }
  576. }
  577. /// <summary>
  578. /// Gets the folder hierarchy in a loop.
  579. /// </summary>
  580. /// <param name="parentID">parent ID.</param>
  581. /// <param name="command">SQL command/connection to database</param>
  582. /// <returns></returns>
  583. private static List<InventoryFolderBase> getFolderHierarchy(UUID parentID, AutoClosingSqlCommand command)
  584. {
  585. command.Parameters["@parentID"].Value = parentID.Guid; //.ToString();
  586. List<InventoryFolderBase> folders = getInventoryFolders(command);
  587. if (folders.Count > 0)
  588. {
  589. List<InventoryFolderBase> tempFolders = new List<InventoryFolderBase>();
  590. foreach (InventoryFolderBase folderBase in folders)
  591. {
  592. tempFolders.AddRange(getFolderHierarchy(folderBase.ID, command));
  593. }
  594. if (tempFolders.Count > 0)
  595. {
  596. folders.AddRange(tempFolders);
  597. }
  598. }
  599. return folders;
  600. }
  601. /// <summary>
  602. /// Gets the inventory folders.
  603. /// </summary>
  604. /// <param name="parentID">parentID, use UUID.Zero to get root</param>
  605. /// <param name="user">user id, use UUID.Zero, if you want all folders from a parentID.</param>
  606. /// <returns></returns>
  607. private List<InventoryFolderBase> getInventoryFolders(UUID parentID, UUID user)
  608. {
  609. using (AutoClosingSqlCommand command = database.Query("SELECT * FROM inventoryfolders WHERE parentFolderID = @parentID AND agentID LIKE @uuid"))
  610. {
  611. if (user == UUID.Zero)
  612. {
  613. command.Parameters.Add(database.CreateParameter("uuid", "%"));
  614. }
  615. else
  616. {
  617. command.Parameters.Add(database.CreateParameter("uuid", user));
  618. }
  619. command.Parameters.Add(database.CreateParameter("parentID", parentID));
  620. return getInventoryFolders(command);
  621. }
  622. }
  623. /// <summary>
  624. /// Gets the inventory folders.
  625. /// </summary>
  626. /// <param name="command">SQLcommand.</param>
  627. /// <returns></returns>
  628. private static List<InventoryFolderBase> getInventoryFolders(AutoClosingSqlCommand command)
  629. {
  630. using (IDataReader reader = command.ExecuteReader())
  631. {
  632. List<InventoryFolderBase> items = new List<InventoryFolderBase>();
  633. while (reader.Read())
  634. {
  635. items.Add(readInventoryFolder(reader));
  636. }
  637. return items;
  638. }
  639. }
  640. /// <summary>
  641. /// Reads a list of inventory folders returned by a query.
  642. /// </summary>
  643. /// <param name="reader">A MSSQL Data Reader</param>
  644. /// <returns>A List containing inventory folders</returns>
  645. protected static InventoryFolderBase readInventoryFolder(IDataReader reader)
  646. {
  647. try
  648. {
  649. InventoryFolderBase folder = new InventoryFolderBase();
  650. folder.Owner = new UUID((Guid)reader["agentID"]);
  651. folder.ParentID = new UUID((Guid)reader["parentFolderID"]);
  652. folder.ID = new UUID((Guid)reader["folderID"]);
  653. folder.Name = (string)reader["folderName"];
  654. folder.Type = (short)reader["type"];
  655. folder.Version = Convert.ToUInt16(reader["version"]);
  656. return folder;
  657. }
  658. catch (Exception e)
  659. {
  660. m_log.Error("[INVENTORY DB] Error reading inventory folder :" + e.Message);
  661. }
  662. return null;
  663. }
  664. /// <summary>
  665. /// Reads a one item from an SQL result
  666. /// </summary>
  667. /// <param name="reader">The SQL Result</param>
  668. /// <returns>the item read</returns>
  669. private static InventoryItemBase readInventoryItem(IDataRecord reader)
  670. {
  671. try
  672. {
  673. InventoryItemBase item = new InventoryItemBase();
  674. item.ID = new UUID((Guid)reader["inventoryID"]);
  675. item.AssetID = new UUID((Guid)reader["assetID"]);
  676. item.AssetType = Convert.ToInt32(reader["assetType"].ToString());
  677. item.Folder = new UUID((Guid)reader["parentFolderID"]);
  678. item.Owner = new UUID((Guid)reader["avatarID"]);
  679. item.Name = reader["inventoryName"].ToString();
  680. item.Description = reader["inventoryDescription"].ToString();
  681. item.NextPermissions = Convert.ToUInt32(reader["inventoryNextPermissions"]);
  682. item.CurrentPermissions = Convert.ToUInt32(reader["inventoryCurrentPermissions"]);
  683. item.InvType = Convert.ToInt32(reader["invType"].ToString());
  684. item.CreatorId = ((Guid)reader["creatorID"]).ToString();
  685. item.BasePermissions = Convert.ToUInt32(reader["inventoryBasePermissions"]);
  686. item.EveryOnePermissions = Convert.ToUInt32(reader["inventoryEveryOnePermissions"]);
  687. item.GroupPermissions = Convert.ToUInt32(reader["inventoryGroupPermissions"]);
  688. item.SalePrice = Convert.ToInt32(reader["salePrice"]);
  689. item.SaleType = Convert.ToByte(reader["saleType"]);
  690. item.CreationDate = Convert.ToInt32(reader["creationDate"]);
  691. item.GroupID = new UUID((Guid)reader["groupID"]);
  692. item.GroupOwned = Convert.ToBoolean(reader["groupOwned"]);
  693. item.Flags = Convert.ToUInt32(reader["flags"]);
  694. return item;
  695. }
  696. catch (SqlException e)
  697. {
  698. m_log.Error("[INVENTORY DB]: Error reading inventory item :" + e.Message);
  699. }
  700. return null;
  701. }
  702. /// <summary>
  703. /// Delete a folder in inventory databasae
  704. /// </summary>
  705. /// <param name="folderID">the folder UUID</param>
  706. /// <param name="connection">connection to database</param>
  707. private void DeleteOneFolder(UUID folderID, SqlConnection connection)
  708. {
  709. try
  710. {
  711. using (SqlCommand command = new SqlCommand("DELETE FROM inventoryfolders WHERE folderID=@folderID", connection))
  712. {
  713. command.Parameters.Add(database.CreateParameter("folderID", folderID));
  714. command.ExecuteNonQuery();
  715. }
  716. }
  717. catch (SqlException e)
  718. {
  719. m_log.Error("[INVENTORY DB]: Error deleting folder :" + e.Message);
  720. }
  721. }
  722. #endregion
  723. }
  724. }