SQLiteInventoryStore.cs 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749
  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 OpenSim 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.Reflection;
  31. using libsecondlife;
  32. using log4net;
  33. using Mono.Data.SqliteClient;
  34. using OpenSim.Framework;
  35. namespace OpenSim.Data.SQLite
  36. {
  37. public class SQLiteInventoryStore : SQLiteUtil, IInventoryData
  38. {
  39. private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
  40. private const string invItemsSelect = "select * from inventoryitems";
  41. private const string invFoldersSelect = "select * from inventoryfolders";
  42. private DataSet ds;
  43. private SqliteDataAdapter invItemsDa;
  44. private SqliteDataAdapter invFoldersDa;
  45. /// <summary>
  46. /// Initialises the interface
  47. /// </summary>
  48. public void Initialise(string dbconnect)
  49. {
  50. if (dbconnect == string.Empty) {
  51. dbconnect = "URI=file:inventoryStore.db,version=3";
  52. }
  53. m_log.Info("[INVENTORY DB]: Sqlite - connecting: " + dbconnect);
  54. SqliteConnection conn = new SqliteConnection(dbconnect);
  55. conn.Open();
  56. TestTables(conn);
  57. SqliteCommand itemsSelectCmd = new SqliteCommand(invItemsSelect, conn);
  58. invItemsDa = new SqliteDataAdapter(itemsSelectCmd);
  59. // SqliteCommandBuilder primCb = new SqliteCommandBuilder(primDa);
  60. SqliteCommand foldersSelectCmd = new SqliteCommand(invFoldersSelect, conn);
  61. invFoldersDa = new SqliteDataAdapter(foldersSelectCmd);
  62. ds = new DataSet();
  63. ds.Tables.Add(createInventoryFoldersTable());
  64. invFoldersDa.Fill(ds.Tables["inventoryfolders"]);
  65. setupFoldersCommands(invFoldersDa, conn);
  66. m_log.Info("[INVENTORY DB]: Populated Inventory Folders Definitions");
  67. ds.Tables.Add(createInventoryItemsTable());
  68. invItemsDa.Fill(ds.Tables["inventoryitems"]);
  69. setupItemsCommands(invItemsDa, conn);
  70. m_log.Info("[INVENTORY DB]: Populated Inventory Items Definitions");
  71. ds.AcceptChanges();
  72. }
  73. public InventoryItemBase buildItem(DataRow row)
  74. {
  75. InventoryItemBase item = new InventoryItemBase();
  76. item.ID = new LLUUID((string) row["UUID"]);
  77. item.AssetID = new LLUUID((string) row["assetID"]);
  78. item.AssetType = Convert.ToInt32(row["assetType"]);
  79. item.InvType = Convert.ToInt32(row["invType"]);
  80. item.Folder = new LLUUID((string) row["parentFolderID"]);
  81. item.Owner = new LLUUID((string) row["avatarID"]);
  82. item.Creator = new LLUUID((string) row["creatorsID"]);
  83. item.Name = (string) row["inventoryName"];
  84. item.Description = (string) row["inventoryDescription"];
  85. item.NextPermissions = Convert.ToUInt32(row["inventoryNextPermissions"]);
  86. item.CurrentPermissions = Convert.ToUInt32(row["inventoryCurrentPermissions"]);
  87. item.BasePermissions = Convert.ToUInt32(row["inventoryBasePermissions"]);
  88. item.EveryOnePermissions = Convert.ToUInt32(row["inventoryEveryOnePermissions"]);
  89. // new fields
  90. if (!Convert.IsDBNull(row["salePrice"]))
  91. item.SalePrice = Convert.ToInt32(row["salePrice"]);
  92. if (!Convert.IsDBNull(row["saleType"]))
  93. item.SaleType = Convert.ToByte(row["saleType"]);
  94. if (!Convert.IsDBNull(row["creationDate"]))
  95. item.CreationDate = Convert.ToInt32(row["creationDate"]);
  96. if (!Convert.IsDBNull(row["groupID"]))
  97. item.GroupID = new LLUUID((string)row["groupID"]);
  98. if (!Convert.IsDBNull(row["groupOwned"]))
  99. item.GroupOwned = Convert.ToBoolean(row["groupOwned"]);
  100. if (!Convert.IsDBNull(row["Flags"]))
  101. item.Flags = Convert.ToUInt32(row["Flags"]);
  102. return item;
  103. }
  104. private static void fillItemRow(DataRow row, InventoryItemBase item)
  105. {
  106. row["UUID"] = Util.ToRawUuidString(item.ID);
  107. row["assetID"] = Util.ToRawUuidString(item.AssetID);
  108. row["assetType"] = item.AssetType;
  109. row["invType"] = item.InvType;
  110. row["parentFolderID"] = Util.ToRawUuidString(item.Folder);
  111. row["avatarID"] = Util.ToRawUuidString(item.Owner);
  112. row["creatorsID"] = Util.ToRawUuidString(item.Creator);
  113. row["inventoryName"] = item.Name;
  114. row["inventoryDescription"] = item.Description;
  115. row["inventoryNextPermissions"] = item.NextPermissions;
  116. row["inventoryCurrentPermissions"] = item.CurrentPermissions;
  117. row["inventoryBasePermissions"] = item.BasePermissions;
  118. row["inventoryEveryOnePermissions"] = item.EveryOnePermissions;
  119. // new fields
  120. row["salePrice"] = item.SalePrice;
  121. row["saleType"] = item.SaleType;
  122. row["creationDate"] = item.CreationDate;
  123. row["groupID"] = item.GroupID;
  124. row["groupOwned"] = item.GroupOwned;
  125. row["flags"] = item.Flags;
  126. }
  127. private void addFolder(InventoryFolderBase folder, bool add)
  128. {
  129. lock (ds)
  130. {
  131. DataTable inventoryFolderTable = ds.Tables["inventoryfolders"];
  132. DataRow inventoryRow = inventoryFolderTable.Rows.Find(Util.ToRawUuidString(folder.ID));
  133. if (inventoryRow == null)
  134. {
  135. if (! add)
  136. m_log.ErrorFormat("Interface Misuse: Attempting to Update non-existant inventory folder: {0}", folder.ID);
  137. inventoryRow = inventoryFolderTable.NewRow();
  138. fillFolderRow(inventoryRow, folder);
  139. inventoryFolderTable.Rows.Add(inventoryRow);
  140. }
  141. else
  142. {
  143. if (add)
  144. m_log.ErrorFormat("Interface Misuse: Attempting to Add inventory folder that already exists: {0}", folder.ID);
  145. fillFolderRow(inventoryRow, folder);
  146. }
  147. invFoldersDa.Update(ds, "inventoryfolders");
  148. }
  149. }
  150. private void moveFolder(InventoryFolderBase folder)
  151. {
  152. lock (ds)
  153. {
  154. DataTable inventoryFolderTable = ds.Tables["inventoryfolders"];
  155. DataRow inventoryRow = inventoryFolderTable.Rows.Find(Util.ToRawUuidString(folder.ID));
  156. if (inventoryRow == null)
  157. {
  158. inventoryRow = inventoryFolderTable.NewRow();
  159. fillFolderRow(inventoryRow, folder);
  160. inventoryFolderTable.Rows.Add(inventoryRow);
  161. }
  162. else
  163. {
  164. moveFolderRow(inventoryRow, folder);
  165. }
  166. invFoldersDa.Update(ds, "inventoryfolders");
  167. }
  168. }
  169. private void addItem(InventoryItemBase item, bool add)
  170. {
  171. lock (ds)
  172. {
  173. DataTable inventoryItemTable = ds.Tables["inventoryitems"];
  174. DataRow inventoryRow = inventoryItemTable.Rows.Find(Util.ToRawUuidString(item.ID));
  175. if (inventoryRow == null)
  176. {
  177. if (! add)
  178. m_log.ErrorFormat("[INVENTORY DB]: Interface Misuse: Attempting to Update non-existant inventory item: {0}", item.ID);
  179. inventoryRow = inventoryItemTable.NewRow();
  180. fillItemRow(inventoryRow, item);
  181. inventoryItemTable.Rows.Add(inventoryRow);
  182. }
  183. else
  184. {
  185. if (add)
  186. m_log.ErrorFormat("[INVENTORY DB]: Interface Misuse: Attempting to Add inventory item that already exists: {0}", item.ID);
  187. fillItemRow(inventoryRow, item);
  188. }
  189. invItemsDa.Update(ds, "inventoryitems");
  190. }
  191. }
  192. public void Shutdown()
  193. {
  194. // TODO: DataSet commit
  195. }
  196. /// <summary>
  197. /// Closes the interface
  198. /// </summary>
  199. public void Close()
  200. {
  201. }
  202. /// <summary>
  203. /// The plugin being loaded
  204. /// </summary>
  205. /// <returns>A string containing the plugin name</returns>
  206. public string getName()
  207. {
  208. return "SQLite Inventory Data Interface";
  209. }
  210. /// <summary>
  211. /// The plugins version
  212. /// </summary>
  213. /// <returns>A string containing the plugin version</returns>
  214. public string getVersion()
  215. {
  216. Module module = GetType().Module;
  217. string dllName = module.Assembly.ManifestModule.Name;
  218. Version dllVersion = module.Assembly.GetName().Version;
  219. return
  220. string.Format("{0}.{1}.{2}.{3}", dllVersion.Major, dllVersion.Minor, dllVersion.Build,
  221. dllVersion.Revision);
  222. }
  223. /// <summary>
  224. /// Returns a list of inventory items contained within the specified folder
  225. /// </summary>
  226. /// <param name="folderID">The UUID of the target folder</param>
  227. /// <returns>A List of InventoryItemBase items</returns>
  228. public List<InventoryItemBase> getInventoryInFolder(LLUUID folderID)
  229. {
  230. lock (ds)
  231. {
  232. List<InventoryItemBase> retval = new List<InventoryItemBase>();
  233. DataTable inventoryItemTable = ds.Tables["inventoryitems"];
  234. string selectExp = "parentFolderID = '" + Util.ToRawUuidString(folderID) + "'";
  235. DataRow[] rows = inventoryItemTable.Select(selectExp);
  236. foreach (DataRow row in rows)
  237. {
  238. retval.Add(buildItem(row));
  239. }
  240. return retval;
  241. }
  242. }
  243. /// <summary>
  244. /// Returns a list of the root folders within a users inventory
  245. /// </summary>
  246. /// <param name="user">The user whos inventory is to be searched</param>
  247. /// <returns>A list of folder objects</returns>
  248. public List<InventoryFolderBase> getUserRootFolders(LLUUID user)
  249. {
  250. return new List<InventoryFolderBase>();
  251. }
  252. // see InventoryItemBase.getUserRootFolder
  253. public InventoryFolderBase getUserRootFolder(LLUUID user)
  254. {
  255. lock (ds)
  256. {
  257. List<InventoryFolderBase> folders = new List<InventoryFolderBase>();
  258. DataTable inventoryFolderTable = ds.Tables["inventoryfolders"];
  259. string selectExp = "agentID = '" + Util.ToRawUuidString(user) + "' AND parentID = '" +
  260. Util.ToRawUuidString(LLUUID.Zero) + "'";
  261. DataRow[] rows = inventoryFolderTable.Select(selectExp);
  262. foreach (DataRow row in rows)
  263. {
  264. folders.Add(buildFolder(row));
  265. }
  266. // There should only ever be one root folder for a user. However, if there's more
  267. // than one we'll simply use the first one rather than failing. It would be even
  268. // nicer to print some message to this effect, but this feels like it's too low a
  269. // to put such a message out, and it's too minor right now to spare the time to
  270. // suitably refactor.
  271. if (folders.Count > 0)
  272. {
  273. return folders[0];
  274. }
  275. return null;
  276. }
  277. }
  278. /// <summary>
  279. /// Append a list of all the child folders of a parent folder
  280. /// </summary>
  281. /// <param name="folders">list where folders will be appended</param>
  282. /// <param name="parentID">ID of parent</param>
  283. protected void getInventoryFolders(ref List<InventoryFolderBase> folders, LLUUID parentID)
  284. {
  285. lock (ds)
  286. {
  287. DataTable inventoryFolderTable = ds.Tables["inventoryfolders"];
  288. string selectExp = "parentID = '" + Util.ToRawUuidString(parentID) + "'";
  289. DataRow[] rows = inventoryFolderTable.Select(selectExp);
  290. foreach (DataRow row in rows)
  291. {
  292. folders.Add(buildFolder(row));
  293. }
  294. }
  295. }
  296. /// <summary>
  297. /// Returns a list of inventory folders contained in the folder 'parentID'
  298. /// </summary>
  299. /// <param name="parentID">The folder to get subfolders for</param>
  300. /// <returns>A list of inventory folders</returns>
  301. public List<InventoryFolderBase> getInventoryFolders(LLUUID parentID)
  302. {
  303. List<InventoryFolderBase> folders = new List<InventoryFolderBase>();
  304. getInventoryFolders(ref folders, Util.ToRawUuidString(parentID));
  305. return folders;
  306. }
  307. // See IInventoryData
  308. public List<InventoryFolderBase> getFolderHierarchy(LLUUID parentID)
  309. {
  310. List<InventoryFolderBase> folders = new List<InventoryFolderBase>();
  311. getInventoryFolders(ref folders, Util.ToRawUuidString(parentID));
  312. for (int i = 0; i < folders.Count; i++)
  313. getInventoryFolders(ref folders, Util.ToRawUuidString(folders[i].ID));
  314. return folders;
  315. }
  316. /// <summary>
  317. /// Returns an inventory item by its UUID
  318. /// </summary>
  319. /// <param name="item">The UUID of the item to be returned</param>
  320. /// <returns>A class containing item information</returns>
  321. public InventoryItemBase getInventoryItem(LLUUID item)
  322. {
  323. lock (ds)
  324. {
  325. DataRow row = ds.Tables["inventoryitems"].Rows.Find(Util.ToRawUuidString(item));
  326. if (row != null)
  327. {
  328. return buildItem(row);
  329. }
  330. else
  331. {
  332. return null;
  333. }
  334. }
  335. }
  336. /// <summary>
  337. /// Returns a specified inventory folder by its UUID
  338. /// </summary>
  339. /// <param name="folder">The UUID of the folder to be returned</param>
  340. /// <returns>A class containing folder information</returns>
  341. public InventoryFolderBase getInventoryFolder(LLUUID folder)
  342. {
  343. // TODO: Deep voodoo here. If you enable this code then
  344. // multi region breaks. No idea why, but I figured it was
  345. // better to leave multi region at this point. It does mean
  346. // that you don't get to see system textures why creating
  347. // clothes and the like. :(
  348. lock (ds)
  349. {
  350. DataRow row = ds.Tables["inventoryfolders"].Rows.Find(Util.ToRawUuidString(folder));
  351. if (row != null)
  352. {
  353. return buildFolder(row);
  354. }
  355. else
  356. {
  357. return null;
  358. }
  359. }
  360. }
  361. /// <summary>
  362. /// Creates a new inventory item based on item
  363. /// </summary>
  364. /// <param name="item">The item to be created</param>
  365. public void addInventoryItem(InventoryItemBase item)
  366. {
  367. addItem(item, true);
  368. }
  369. /// <summary>
  370. /// Updates an inventory item with item (updates based on ID)
  371. /// </summary>
  372. /// <param name="item">The updated item</param>
  373. public void updateInventoryItem(InventoryItemBase item)
  374. {
  375. addItem(item, false);
  376. }
  377. /// <summary>
  378. ///
  379. /// </summary>
  380. /// <param name="item"></param>
  381. public void deleteInventoryItem(LLUUID itemID)
  382. {
  383. lock (ds)
  384. {
  385. DataTable inventoryItemTable = ds.Tables["inventoryitems"];
  386. DataRow inventoryRow = inventoryItemTable.Rows.Find(Util.ToRawUuidString(itemID));
  387. if (inventoryRow != null)
  388. {
  389. inventoryRow.Delete();
  390. }
  391. invItemsDa.Update(ds, "inventoryitems");
  392. }
  393. }
  394. /// <summary>
  395. /// Delete all items in the specified folder
  396. /// </summary>
  397. /// <param name="folderId">id of the folder, whose item content should be deleted</param>
  398. //!TODO, this is horribly inefficient, but I don't want to ruin the overall structure of this implementation
  399. private void deleteItemsInFolder(LLUUID folderId)
  400. {
  401. List<InventoryItemBase> items = getInventoryInFolder(Util.ToRawUuidString(folderId));
  402. foreach (InventoryItemBase i in items)
  403. deleteInventoryItem(Util.ToRawUuidString(i.ID));
  404. }
  405. /// <summary>
  406. /// Adds a new folder specified by folder
  407. /// </summary>
  408. /// <param name="folder">The inventory folder</param>
  409. public void addInventoryFolder(InventoryFolderBase folder)
  410. {
  411. addFolder(folder, true);
  412. }
  413. /// <summary>
  414. /// Updates a folder based on its ID with folder
  415. /// </summary>
  416. /// <param name="folder">The inventory folder</param>
  417. public void updateInventoryFolder(InventoryFolderBase folder)
  418. {
  419. addFolder(folder, false);
  420. }
  421. /// <summary>
  422. /// Moves a folder based on its ID with folder
  423. /// </summary>
  424. /// <param name="folder">The inventory folder</param>
  425. public void moveInventoryFolder(InventoryFolderBase folder)
  426. {
  427. moveFolder(folder);
  428. }
  429. /// <summary>
  430. /// Delete a folder
  431. /// </summary>
  432. /// <remarks>
  433. /// This will clean-up any child folders and child items as well
  434. /// </remarks>
  435. /// <param name="item"></param>
  436. public void deleteInventoryFolder(LLUUID folderID)
  437. {
  438. lock (ds)
  439. {
  440. List<InventoryFolderBase> subFolders = getFolderHierarchy(Util.ToRawUuidString(folderID));
  441. DataTable inventoryFolderTable = ds.Tables["inventoryfolders"];
  442. DataRow inventoryRow;
  443. //Delete all sub-folders
  444. foreach (InventoryFolderBase f in subFolders)
  445. {
  446. inventoryRow = inventoryFolderTable.Rows.Find(Util.ToRawUuidString(f.ID));
  447. if (inventoryRow != null)
  448. {
  449. deleteItemsInFolder(Util.ToRawUuidString(f.ID));
  450. inventoryRow.Delete();
  451. }
  452. }
  453. //Delete the actual row
  454. inventoryRow = inventoryFolderTable.Rows.Find(Util.ToRawUuidString(folderID));
  455. if (inventoryRow != null)
  456. {
  457. deleteItemsInFolder(Util.ToRawUuidString(folderID));
  458. inventoryRow.Delete();
  459. }
  460. invFoldersDa.Update(ds, "inventoryfolders");
  461. }
  462. }
  463. /***********************************************************************
  464. *
  465. * Data Table definitions
  466. *
  467. **********************************************************************/
  468. private static DataTable createInventoryItemsTable()
  469. {
  470. DataTable inv = new DataTable("inventoryitems");
  471. createCol(inv, "UUID", typeof (String)); //inventoryID
  472. createCol(inv, "assetID", typeof (String));
  473. createCol(inv, "assetType", typeof (Int32));
  474. createCol(inv, "invType", typeof (Int32));
  475. createCol(inv, "parentFolderID", typeof (String));
  476. createCol(inv, "avatarID", typeof (String));
  477. createCol(inv, "creatorsID", typeof (String));
  478. createCol(inv, "inventoryName", typeof (String));
  479. createCol(inv, "inventoryDescription", typeof (String));
  480. // permissions
  481. createCol(inv, "inventoryNextPermissions", typeof (Int32));
  482. createCol(inv, "inventoryCurrentPermissions", typeof (Int32));
  483. createCol(inv, "inventoryBasePermissions", typeof (Int32));
  484. createCol(inv, "inventoryEveryOnePermissions", typeof (Int32));
  485. // sale info
  486. createCol(inv, "salePrice", typeof(Int32));
  487. createCol(inv, "saleType", typeof(Byte));
  488. // creation date
  489. createCol(inv, "creationDate", typeof(Int32));
  490. // group info
  491. createCol(inv, "groupID", typeof(String));
  492. createCol(inv, "groupOwned", typeof(Boolean));
  493. // Flags
  494. createCol(inv, "flags", typeof(UInt32));
  495. inv.PrimaryKey = new DataColumn[] { inv.Columns["UUID"] };
  496. return inv;
  497. }
  498. private static DataTable createInventoryFoldersTable()
  499. {
  500. DataTable fol = new DataTable("inventoryfolders");
  501. createCol(fol, "UUID", typeof (String)); //folderID
  502. createCol(fol, "name", typeof (String));
  503. createCol(fol, "agentID", typeof (String));
  504. createCol(fol, "parentID", typeof (String));
  505. createCol(fol, "type", typeof (Int32));
  506. createCol(fol, "version", typeof (Int32));
  507. fol.PrimaryKey = new DataColumn[] {fol.Columns["UUID"]};
  508. return fol;
  509. }
  510. private void setupItemsCommands(SqliteDataAdapter da, SqliteConnection conn)
  511. {
  512. lock (ds)
  513. {
  514. da.InsertCommand = createInsertCommand("inventoryitems", ds.Tables["inventoryitems"]);
  515. da.InsertCommand.Connection = conn;
  516. da.UpdateCommand = createUpdateCommand("inventoryitems", "UUID=:UUID", ds.Tables["inventoryitems"]);
  517. da.UpdateCommand.Connection = conn;
  518. SqliteCommand delete = new SqliteCommand("delete from inventoryitems where UUID = :UUID");
  519. delete.Parameters.Add(createSqliteParameter("UUID", typeof(String)));
  520. delete.Connection = conn;
  521. da.DeleteCommand = delete;
  522. }
  523. }
  524. private void setupFoldersCommands(SqliteDataAdapter da, SqliteConnection conn)
  525. {
  526. lock (ds)
  527. {
  528. da.InsertCommand = createInsertCommand("inventoryfolders", ds.Tables["inventoryfolders"]);
  529. da.InsertCommand.Connection = conn;
  530. da.UpdateCommand = createUpdateCommand("inventoryfolders", "UUID=:UUID", ds.Tables["inventoryfolders"]);
  531. da.UpdateCommand.Connection = conn;
  532. SqliteCommand delete = new SqliteCommand("delete from inventoryfolders where UUID = :UUID");
  533. delete.Parameters.Add(createSqliteParameter("UUID", typeof(String)));
  534. delete.Connection = conn;
  535. da.DeleteCommand = delete;
  536. }
  537. }
  538. private static InventoryFolderBase buildFolder(DataRow row)
  539. {
  540. InventoryFolderBase folder = new InventoryFolderBase();
  541. folder.ID = new LLUUID((string) row["UUID"]);
  542. folder.Name = (string) row["name"];
  543. folder.Owner = new LLUUID((string) row["agentID"]);
  544. folder.ParentID = new LLUUID((string) row["parentID"]);
  545. folder.Type = Convert.ToInt16(row["type"]);
  546. folder.Version = Convert.ToUInt16(row["version"]);
  547. return folder;
  548. }
  549. private static void fillFolderRow(DataRow row, InventoryFolderBase folder)
  550. {
  551. row["UUID"] = Util.ToRawUuidString(folder.ID);
  552. row["name"] = folder.Name;
  553. row["agentID"] = Util.ToRawUuidString(folder.Owner);
  554. row["parentID"] = Util.ToRawUuidString(folder.ParentID);
  555. row["type"] = folder.Type;
  556. row["version"] = folder.Version;
  557. }
  558. private static void moveFolderRow(DataRow row, InventoryFolderBase folder)
  559. {
  560. row["UUID"] = Util.ToRawUuidString(folder.ID);
  561. row["parentID"] = Util.ToRawUuidString(folder.ParentID);
  562. }
  563. /***********************************************************************
  564. *
  565. * Test and Initialization code
  566. *
  567. **********************************************************************/
  568. private static void InitDB(SqliteConnection conn)
  569. {
  570. string createInventoryItems = defineTable(createInventoryItemsTable());
  571. string createInventoryFolders = defineTable(createInventoryFoldersTable());
  572. SqliteCommand pcmd = new SqliteCommand(createInventoryItems, conn);
  573. SqliteCommand scmd = new SqliteCommand(createInventoryFolders, conn);
  574. pcmd.ExecuteNonQuery();
  575. scmd.ExecuteNonQuery();
  576. }
  577. private static bool TestTables(SqliteConnection conn)
  578. {
  579. SqliteCommand invItemsSelectCmd = new SqliteCommand(invItemsSelect, conn);
  580. SqliteDataAdapter pDa = new SqliteDataAdapter(invItemsSelectCmd);
  581. SqliteCommand invFoldersSelectCmd = new SqliteCommand(invFoldersSelect, conn);
  582. SqliteDataAdapter sDa = new SqliteDataAdapter(invFoldersSelectCmd);
  583. DataSet tmpDS = new DataSet();
  584. try
  585. {
  586. pDa.Fill(tmpDS, "inventoryitems");
  587. sDa.Fill(tmpDS, "inventoryfolders");
  588. }
  589. catch (SqliteSyntaxException)
  590. {
  591. m_log.Info("[INVENTORY DB]: SQLite Database doesn't exist... creating");
  592. InitDB(conn);
  593. }
  594. pDa.Fill(tmpDS, "inventoryitems");
  595. sDa.Fill(tmpDS, "inventoryfolders");
  596. // Very clumsy way of checking whether we need to upgrade the database table version and then updating. Only
  597. // putting up with this because this code should be blown away soon by nhibernate...
  598. conn.Open();
  599. SqliteCommand cmd;
  600. try
  601. {
  602. cmd = new SqliteCommand("select salePrice from inventoryitems limit 1;", conn);
  603. cmd.ExecuteNonQuery();
  604. }
  605. catch (SqliteSyntaxException)
  606. {
  607. m_log.Info("[INVENTORY DB]: Upgrading sqlite inventory database to version 2");
  608. cmd = new SqliteCommand("alter table inventoryitems add column salePrice integer default 99;", conn);
  609. cmd.ExecuteNonQuery();
  610. cmd = new SqliteCommand("alter table inventoryitems add column saleType integer default 0;", conn);
  611. cmd.ExecuteNonQuery();
  612. cmd = new SqliteCommand("alter table inventoryitems add column creationDate integer default 2000;", conn);
  613. cmd.ExecuteNonQuery();
  614. cmd = new SqliteCommand("alter table inventoryitems add column groupID varchar(255) default '00000000-0000-0000-0000-000000000000';", conn);
  615. cmd.ExecuteNonQuery();
  616. cmd = new SqliteCommand("alter table inventoryitems add column groupOwned integer default 0;", conn);
  617. cmd.ExecuteNonQuery();
  618. cmd = new SqliteCommand("alter table inventoryitems add column flags integer default 0;", conn);
  619. cmd.ExecuteNonQuery();
  620. pDa.Fill(tmpDS, "inventoryitems");
  621. }
  622. finally
  623. {
  624. conn.Close();
  625. }
  626. foreach (DataColumn col in createInventoryItemsTable().Columns)
  627. {
  628. if (! tmpDS.Tables["inventoryitems"].Columns.Contains(col.ColumnName))
  629. {
  630. m_log.Info("[INVENTORY DB]: Missing required column:" + col.ColumnName);
  631. return false;
  632. }
  633. }
  634. foreach (DataColumn col in createInventoryFoldersTable().Columns)
  635. {
  636. if (! tmpDS.Tables["inventoryfolders"].Columns.Contains(col.ColumnName))
  637. {
  638. m_log.Info("[INVENTORY DB]: Missing required column:" + col.ColumnName);
  639. return false;
  640. }
  641. }
  642. return true;
  643. }
  644. }
  645. }