aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Data/SQLite/SQLiteSimulationData.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Data/SQLite/SQLiteSimulationData.cs')
-rw-r--r--OpenSim/Data/SQLite/SQLiteSimulationData.cs2359
1 files changed, 2359 insertions, 0 deletions
diff --git a/OpenSim/Data/SQLite/SQLiteSimulationData.cs b/OpenSim/Data/SQLite/SQLiteSimulationData.cs
new file mode 100644
index 0000000..3e9bc3f
--- /dev/null
+++ b/OpenSim/Data/SQLite/SQLiteSimulationData.cs
@@ -0,0 +1,2359 @@
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
28using System;
29using System.Collections.Generic;
30using System.Data;
31using System.Drawing;
32using System.IO;
33using System.Reflection;
34using log4net;
35using Mono.Data.Sqlite;
36using OpenMetaverse;
37using OpenMetaverse.StructuredData;
38using OpenSim.Framework;
39using OpenSim.Region.Framework.Interfaces;
40using OpenSim.Region.Framework.Scenes;
41
42namespace OpenSim.Data.SQLite
43{
44 /// <summary>
45 /// A RegionData Interface to the SQLite database
46 /// </summary>
47 public class SQLiteSimulationData : ISimulationDataStore
48 {
49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
50
51 private const string primSelect = "select * from prims";
52 private const string shapeSelect = "select * from primshapes";
53 private const string itemsSelect = "select * from primitems";
54 private const string terrainSelect = "select * from terrain limit 1";
55 private const string landSelect = "select * from land";
56 private const string landAccessListSelect = "select distinct * from landaccesslist";
57 private const string regionbanListSelect = "select * from regionban";
58 private const string regionSettingsSelect = "select * from regionsettings";
59
60 private DataSet ds;
61 private SqliteDataAdapter primDa;
62 private SqliteDataAdapter shapeDa;
63 private SqliteDataAdapter itemsDa;
64 private SqliteDataAdapter terrainDa;
65 private SqliteDataAdapter landDa;
66 private SqliteDataAdapter landAccessListDa;
67 private SqliteDataAdapter regionSettingsDa;
68
69 private SqliteConnection m_conn;
70
71 private String m_connectionString;
72
73 public SQLiteSimulationData()
74 {
75 }
76
77 public SQLiteSimulationData(string connectionString)
78 {
79 Initialise(connectionString);
80 }
81
82 // Temporary attribute while this is experimental
83
84 /***********************************************************************
85 *
86 * Public Interface Functions
87 *
88 **********************************************************************/
89
90 /// <summary>
91 /// <list type="bullet">
92 /// <item>Initialises RegionData Interface</item>
93 /// <item>Loads and initialises a new SQLite connection and maintains it.</item>
94 /// </list>
95 /// </summary>
96 /// <param name="connectionString">the connection string</param>
97 public void Initialise(string connectionString)
98 {
99 try
100 {
101 m_connectionString = connectionString;
102
103 ds = new DataSet("Region");
104
105 m_log.Info("[SQLITE REGION DB]: Sqlite - connecting: " + connectionString);
106 m_conn = new SqliteConnection(m_connectionString);
107 m_conn.Open();
108
109 SqliteCommand primSelectCmd = new SqliteCommand(primSelect, m_conn);
110 primDa = new SqliteDataAdapter(primSelectCmd);
111
112 SqliteCommand shapeSelectCmd = new SqliteCommand(shapeSelect, m_conn);
113 shapeDa = new SqliteDataAdapter(shapeSelectCmd);
114 // SqliteCommandBuilder shapeCb = new SqliteCommandBuilder(shapeDa);
115
116 SqliteCommand itemsSelectCmd = new SqliteCommand(itemsSelect, m_conn);
117 itemsDa = new SqliteDataAdapter(itemsSelectCmd);
118
119 SqliteCommand terrainSelectCmd = new SqliteCommand(terrainSelect, m_conn);
120 terrainDa = new SqliteDataAdapter(terrainSelectCmd);
121
122 SqliteCommand landSelectCmd = new SqliteCommand(landSelect, m_conn);
123 landDa = new SqliteDataAdapter(landSelectCmd);
124
125 SqliteCommand landAccessListSelectCmd = new SqliteCommand(landAccessListSelect, m_conn);
126 landAccessListDa = new SqliteDataAdapter(landAccessListSelectCmd);
127
128 SqliteCommand regionSettingsSelectCmd = new SqliteCommand(regionSettingsSelect, m_conn);
129 regionSettingsDa = new SqliteDataAdapter(regionSettingsSelectCmd);
130 // This actually does the roll forward assembly stuff
131 Assembly assem = GetType().Assembly;
132 Migration m = new Migration(m_conn, assem, "RegionStore");
133 m.Update();
134
135 lock (ds)
136 {
137 ds.Tables.Add(createPrimTable());
138 setupPrimCommands(primDa, m_conn);
139
140 ds.Tables.Add(createShapeTable());
141 setupShapeCommands(shapeDa, m_conn);
142
143 ds.Tables.Add(createItemsTable());
144 setupItemsCommands(itemsDa, m_conn);
145
146 ds.Tables.Add(createTerrainTable());
147 setupTerrainCommands(terrainDa, m_conn);
148
149 ds.Tables.Add(createLandTable());
150 setupLandCommands(landDa, m_conn);
151
152 ds.Tables.Add(createLandAccessListTable());
153 setupLandAccessCommands(landAccessListDa, m_conn);
154
155 ds.Tables.Add(createRegionSettingsTable());
156 setupRegionSettingsCommands(regionSettingsDa, m_conn);
157
158 // WORKAROUND: This is a work around for sqlite on
159 // windows, which gets really unhappy with blob columns
160 // that have no sample data in them. At some point we
161 // need to actually find a proper way to handle this.
162 try
163 {
164 primDa.Fill(ds.Tables["prims"]);
165 }
166 catch (Exception)
167 {
168 m_log.Info("[SQLITE REGION DB]: Caught fill error on prims table");
169 }
170
171 try
172 {
173 shapeDa.Fill(ds.Tables["primshapes"]);
174 }
175 catch (Exception)
176 {
177 m_log.Info("[SQLITE REGION DB]: Caught fill error on primshapes table");
178 }
179
180 try
181 {
182 itemsDa.Fill(ds.Tables["primitems"]);
183 }
184 catch (Exception)
185 {
186 m_log.Info("[SQLITE REGION DB]: Caught fill error on primitems table");
187 }
188
189 try
190 {
191 terrainDa.Fill(ds.Tables["terrain"]);
192 }
193 catch (Exception)
194 {
195 m_log.Info("[SQLITE REGION DB]: Caught fill error on terrain table");
196 }
197
198 try
199 {
200 landDa.Fill(ds.Tables["land"]);
201 }
202 catch (Exception)
203 {
204 m_log.Info("[SQLITE REGION DB]: Caught fill error on land table");
205 }
206
207 try
208 {
209 landAccessListDa.Fill(ds.Tables["landaccesslist"]);
210 }
211 catch (Exception)
212 {
213 m_log.Info("[SQLITE REGION DB]: Caught fill error on landaccesslist table");
214 }
215
216 try
217 {
218 regionSettingsDa.Fill(ds.Tables["regionsettings"]);
219 }
220 catch (Exception)
221 {
222 m_log.Info("[SQLITE REGION DB]: Caught fill error on regionsettings table");
223 }
224
225 // We have to create a data set mapping for every table, otherwise the IDataAdaptor.Update() will not populate rows with values!
226 // Not sure exactly why this is - this kind of thing was not necessary before - justincc 20100409
227 // Possibly because we manually set up our own DataTables before connecting to the database
228 CreateDataSetMapping(primDa, "prims");
229 CreateDataSetMapping(shapeDa, "primshapes");
230 CreateDataSetMapping(itemsDa, "primitems");
231 CreateDataSetMapping(terrainDa, "terrain");
232 CreateDataSetMapping(landDa, "land");
233 CreateDataSetMapping(landAccessListDa, "landaccesslist");
234 CreateDataSetMapping(regionSettingsDa, "regionsettings");
235 }
236 }
237 catch (Exception e)
238 {
239 m_log.Error(e);
240 Environment.Exit(23);
241 }
242
243 return;
244 }
245
246 public void Dispose()
247 {
248 if (m_conn != null)
249 {
250 m_conn.Close();
251 m_conn = null;
252 }
253 if (ds != null)
254 {
255 ds.Dispose();
256 ds = null;
257 }
258 if (primDa != null)
259 {
260 primDa.Dispose();
261 primDa = null;
262 }
263 if (shapeDa != null)
264 {
265 shapeDa.Dispose();
266 shapeDa = null;
267 }
268 if (itemsDa != null)
269 {
270 itemsDa.Dispose();
271 itemsDa = null;
272 }
273 if (terrainDa != null)
274 {
275 terrainDa.Dispose();
276 terrainDa = null;
277 }
278 if (landDa != null)
279 {
280 landDa.Dispose();
281 landDa = null;
282 }
283 if (landAccessListDa != null)
284 {
285 landAccessListDa.Dispose();
286 landAccessListDa = null;
287 }
288 if (regionSettingsDa != null)
289 {
290 regionSettingsDa.Dispose();
291 regionSettingsDa = null;
292 }
293 }
294
295 public void StoreRegionSettings(RegionSettings rs)
296 {
297 lock (ds)
298 {
299 DataTable regionsettings = ds.Tables["regionsettings"];
300
301 DataRow settingsRow = regionsettings.Rows.Find(rs.RegionUUID.ToString());
302 if (settingsRow == null)
303 {
304 settingsRow = regionsettings.NewRow();
305 fillRegionSettingsRow(settingsRow, rs);
306 regionsettings.Rows.Add(settingsRow);
307 }
308 else
309 {
310 fillRegionSettingsRow(settingsRow, rs);
311 }
312
313 Commit();
314 }
315 }
316 public RegionLightShareData LoadRegionWindlightSettings(UUID regionUUID)
317 {
318 //This connector doesn't support the windlight module yet
319 //Return default LL windlight settings
320 return new RegionLightShareData();
321 }
322 public void StoreRegionWindlightSettings(RegionLightShareData wl)
323 {
324 //This connector doesn't support the windlight module yet
325 }
326 public RegionSettings LoadRegionSettings(UUID regionUUID)
327 {
328 lock (ds)
329 {
330 DataTable regionsettings = ds.Tables["regionsettings"];
331
332 string searchExp = "regionUUID = '" + regionUUID.ToString() + "'";
333 DataRow[] rawsettings = regionsettings.Select(searchExp);
334 if (rawsettings.Length == 0)
335 {
336 RegionSettings rs = new RegionSettings();
337 rs.RegionUUID = regionUUID;
338 rs.OnSave += StoreRegionSettings;
339
340 StoreRegionSettings(rs);
341
342 return rs;
343 }
344 DataRow row = rawsettings[0];
345
346 RegionSettings newSettings = buildRegionSettings(row);
347 newSettings.OnSave += StoreRegionSettings;
348
349 return newSettings;
350 }
351 }
352
353 /// <summary>
354 /// Adds an object into region storage
355 /// </summary>
356 /// <param name="obj">the object</param>
357 /// <param name="regionUUID">the region UUID</param>
358 public void StoreObject(SceneObjectGroup obj, UUID regionUUID)
359 {
360 uint flags = obj.RootPart.GetEffectiveObjectFlags();
361
362 // Eligibility check
363 //
364 if ((flags & (uint)PrimFlags.Temporary) != 0)
365 return;
366 if ((flags & (uint)PrimFlags.TemporaryOnRez) != 0)
367 return;
368
369 lock (ds)
370 {
371 foreach (SceneObjectPart prim in obj.Children.Values)
372 {
373// m_log.Info("[REGION DB]: Adding obj: " + obj.UUID + " to region: " + regionUUID);
374 addPrim(prim, obj.UUID, regionUUID);
375 }
376 }
377
378 Commit();
379 // m_log.Info("[Dump of prims]: " + ds.GetXml());
380 }
381
382 /// <summary>
383 /// Removes an object from region storage
384 /// </summary>
385 /// <param name="obj">the object</param>
386 /// <param name="regionUUID">the region UUID</param>
387 public void RemoveObject(UUID obj, UUID regionUUID)
388 {
389 // m_log.InfoFormat("[REGION DB]: Removing obj: {0} from region: {1}", obj.Guid, regionUUID);
390
391 DataTable prims = ds.Tables["prims"];
392 DataTable shapes = ds.Tables["primshapes"];
393
394 string selectExp = "SceneGroupID = '" + obj + "' and RegionUUID = '" + regionUUID + "'";
395 lock (ds)
396 {
397 DataRow[] primRows = prims.Select(selectExp);
398 foreach (DataRow row in primRows)
399 {
400 // Remove shape rows
401 UUID uuid = new UUID((string) row["UUID"]);
402 DataRow shapeRow = shapes.Rows.Find(uuid.ToString());
403 if (shapeRow != null)
404 {
405 shapeRow.Delete();
406 }
407
408 RemoveItems(uuid);
409
410 // Remove prim row
411 row.Delete();
412 }
413 }
414
415 Commit();
416 }
417
418 /// <summary>
419 /// Remove all persisted items of the given prim.
420 /// The caller must acquire the necessrary synchronization locks and commit or rollback changes.
421 /// </summary>
422 /// <param name="uuid">The item UUID</param>
423 private void RemoveItems(UUID uuid)
424 {
425 DataTable items = ds.Tables["primitems"];
426
427 String sql = String.Format("primID = '{0}'", uuid);
428 DataRow[] itemRows = items.Select(sql);
429
430 foreach (DataRow itemRow in itemRows)
431 {
432 itemRow.Delete();
433 }
434 }
435
436 /// <summary>
437 /// Load persisted objects from region storage.
438 /// </summary>
439 /// <param name="regionUUID">The region UUID</param>
440 /// <returns>List of loaded groups</returns>
441 public List<SceneObjectGroup> LoadObjects(UUID regionUUID)
442 {
443 Dictionary<UUID, SceneObjectGroup> createdObjects = new Dictionary<UUID, SceneObjectGroup>();
444
445 List<SceneObjectGroup> retvals = new List<SceneObjectGroup>();
446
447 DataTable prims = ds.Tables["prims"];
448 DataTable shapes = ds.Tables["primshapes"];
449
450 string byRegion = "RegionUUID = '" + regionUUID + "'";
451
452 lock (ds)
453 {
454 DataRow[] primsForRegion = prims.Select(byRegion);
455// m_log.Info("[SQLITE REGION DB]: Loaded " + primsForRegion.Length + " prims for region: " + regionUUID);
456
457 // First, create all groups
458 foreach (DataRow primRow in primsForRegion)
459 {
460 try
461 {
462 SceneObjectPart prim = null;
463
464 string uuid = (string) primRow["UUID"];
465 string objID = (string) primRow["SceneGroupID"];
466
467 if (uuid == objID) //is new SceneObjectGroup ?
468 {
469 prim = buildPrim(primRow);
470 DataRow shapeRow = shapes.Rows.Find(prim.UUID.ToString());
471 if (shapeRow != null)
472 {
473 prim.Shape = buildShape(shapeRow);
474 }
475 else
476 {
477 m_log.Warn(
478 "[SQLITE REGION DB]: No shape found for prim in storage, so setting default box shape");
479 prim.Shape = PrimitiveBaseShape.Default;
480 }
481
482 SceneObjectGroup group = new SceneObjectGroup(prim);
483 createdObjects.Add(group.UUID, group);
484 retvals.Add(group);
485 LoadItems(prim);
486 }
487 }
488 catch (Exception e)
489 {
490 m_log.Error("[SQLITE REGION DB]: Failed create prim object in new group, exception and data follows");
491 m_log.Error("[SQLITE REGION DB]: ", e);
492 foreach (DataColumn col in prims.Columns)
493 {
494 m_log.Error("[SQLITE REGION DB]: Col: " + col.ColumnName + " => " + primRow[col]);
495 }
496 }
497 }
498
499 // Now fill the groups with part data
500 foreach (DataRow primRow in primsForRegion)
501 {
502 try
503 {
504 SceneObjectPart prim = null;
505
506 string uuid = (string) primRow["UUID"];
507 string objID = (string) primRow["SceneGroupID"];
508 if (uuid != objID) //is new SceneObjectGroup ?
509 {
510 prim = buildPrim(primRow);
511 DataRow shapeRow = shapes.Rows.Find(prim.UUID.ToString());
512 if (shapeRow != null)
513 {
514 prim.Shape = buildShape(shapeRow);
515 }
516 else
517 {
518 m_log.Warn(
519 "[SQLITE REGION DB]: No shape found for prim in storage, so setting default box shape");
520 prim.Shape = PrimitiveBaseShape.Default;
521 }
522
523 createdObjects[new UUID(objID)].AddPart(prim);
524 LoadItems(prim);
525 }
526 }
527 catch (Exception e)
528 {
529 m_log.Error("[SQLITE REGION DB]: Failed create prim object in group, exception and data follows");
530 m_log.Error("[SQLITE REGION DB]: ", e);
531 foreach (DataColumn col in prims.Columns)
532 {
533 m_log.Error("[SQLITE REGION DB]: Col: " + col.ColumnName + " => " + primRow[col]);
534 }
535 }
536 }
537 }
538 return retvals;
539 }
540
541 /// <summary>
542 /// Load in a prim's persisted inventory.
543 /// </summary>
544 /// <param name="prim">the prim</param>
545 private void LoadItems(SceneObjectPart prim)
546 {
547// m_log.DebugFormat("[SQLITE REGION DB]: Loading inventory for {0} {1}", prim.Name, prim.UUID);
548
549 DataTable dbItems = ds.Tables["primitems"];
550 String sql = String.Format("primID = '{0}'", prim.UUID.ToString());
551 DataRow[] dbItemRows = dbItems.Select(sql);
552 IList<TaskInventoryItem> inventory = new List<TaskInventoryItem>();
553
554// m_log.DebugFormat(
555// "[SQLITE REGION DB]: Found {0} items for {1} {2}", dbItemRows.Length, prim.Name, prim.UUID);
556
557 foreach (DataRow row in dbItemRows)
558 {
559 TaskInventoryItem item = buildItem(row);
560 inventory.Add(item);
561
562// m_log.DebugFormat("[SQLITE REGION DB]: Restored item {0} {1}", item.Name, item.ItemID);
563 }
564
565 prim.Inventory.RestoreInventoryItems(inventory);
566 }
567
568 /// <summary>
569 /// Store a terrain revision in region storage
570 /// </summary>
571 /// <param name="ter">terrain heightfield</param>
572 /// <param name="regionID">region UUID</param>
573 public void StoreTerrain(double[,] ter, UUID regionID)
574 {
575 lock (ds)
576 {
577 int revision = Util.UnixTimeSinceEpoch();
578
579 // This is added to get rid of the infinitely growing
580 // terrain databases which negatively impact on SQLite
581 // over time. Before reenabling this feature there
582 // needs to be a limitter put on the number of
583 // revisions in the database, as this old
584 // implementation is a DOS attack waiting to happen.
585
586 using (
587 SqliteCommand cmd =
588 new SqliteCommand("delete from terrain where RegionUUID=:RegionUUID and Revision <= :Revision",
589 m_conn))
590 {
591 cmd.Parameters.Add(new SqliteParameter(":RegionUUID", regionID.ToString()));
592 cmd.Parameters.Add(new SqliteParameter(":Revision", revision));
593 cmd.ExecuteNonQuery();
594 }
595
596 // the following is an work around for .NET. The perf
597 // issues associated with it aren't as bad as you think.
598 m_log.Debug("[SQLITE REGION DB]: Storing terrain revision r" + revision.ToString());
599 String sql = "insert into terrain(RegionUUID, Revision, Heightfield)" +
600 " values(:RegionUUID, :Revision, :Heightfield)";
601
602 using (SqliteCommand cmd = new SqliteCommand(sql, m_conn))
603 {
604 cmd.Parameters.Add(new SqliteParameter(":RegionUUID", regionID.ToString()));
605 cmd.Parameters.Add(new SqliteParameter(":Revision", revision));
606 cmd.Parameters.Add(new SqliteParameter(":Heightfield", serializeTerrain(ter)));
607 cmd.ExecuteNonQuery();
608 }
609 }
610 }
611
612 /// <summary>
613 /// Load the latest terrain revision from region storage
614 /// </summary>
615 /// <param name="regionID">the region UUID</param>
616 /// <returns>Heightfield data</returns>
617 public double[,] LoadTerrain(UUID regionID)
618 {
619 lock (ds)
620 {
621 double[,] terret = new double[(int)Constants.RegionSize, (int)Constants.RegionSize];
622 terret.Initialize();
623
624 String sql = "select RegionUUID, Revision, Heightfield from terrain" +
625 " where RegionUUID=:RegionUUID order by Revision desc";
626
627 using (SqliteCommand cmd = new SqliteCommand(sql, m_conn))
628 {
629 cmd.Parameters.Add(new SqliteParameter(":RegionUUID", regionID.ToString()));
630
631 using (IDataReader row = cmd.ExecuteReader())
632 {
633 int rev = 0;
634 if (row.Read())
635 {
636 // TODO: put this into a function
637 using (MemoryStream str = new MemoryStream((byte[])row["Heightfield"]))
638 {
639 using (BinaryReader br = new BinaryReader(str))
640 {
641 for (int x = 0; x < (int)Constants.RegionSize; x++)
642 {
643 for (int y = 0; y < (int)Constants.RegionSize; y++)
644 {
645 terret[x, y] = br.ReadDouble();
646 }
647 }
648 }
649 }
650 rev = Convert.ToInt32(row["Revision"]);
651 }
652 else
653 {
654 m_log.Warn("[SQLITE REGION DB]: No terrain found for region");
655 return null;
656 }
657
658 m_log.Debug("[SQLITE REGION DB]: Loaded terrain revision r" + rev.ToString());
659 }
660 }
661 return terret;
662 }
663 }
664
665 /// <summary>
666 ///
667 /// </summary>
668 /// <param name="globalID"></param>
669 public void RemoveLandObject(UUID globalID)
670 {
671 lock (ds)
672 {
673 // Can't use blanket SQL statements when using SqlAdapters unless you re-read the data into the adapter
674 // after you're done.
675 // replaced below code with the SqliteAdapter version.
676 //using (SqliteCommand cmd = new SqliteCommand("delete from land where UUID=:UUID", m_conn))
677 //{
678 // cmd.Parameters.Add(new SqliteParameter(":UUID", globalID.ToString()));
679 // cmd.ExecuteNonQuery();
680 //}
681
682 //using (SqliteCommand cmd = new SqliteCommand("delete from landaccesslist where LandUUID=:UUID", m_conn))
683 //{
684 // cmd.Parameters.Add(new SqliteParameter(":UUID", globalID.ToString()));
685 // cmd.ExecuteNonQuery();
686 //}
687
688 DataTable land = ds.Tables["land"];
689 DataTable landaccesslist = ds.Tables["landaccesslist"];
690 DataRow landRow = land.Rows.Find(globalID.ToString());
691 if (landRow != null)
692 {
693 land.Rows.Remove(landRow);
694 }
695 List<DataRow> rowsToDelete = new List<DataRow>();
696 foreach (DataRow rowToCheck in landaccesslist.Rows)
697 {
698 if (rowToCheck["LandUUID"].ToString() == globalID.ToString())
699 rowsToDelete.Add(rowToCheck);
700 }
701 for (int iter = 0; iter < rowsToDelete.Count; iter++)
702 {
703 landaccesslist.Rows.Remove(rowsToDelete[iter]);
704 }
705 }
706 Commit();
707 }
708
709 /// <summary>
710 ///
711 /// </summary>
712 /// <param name="parcel"></param>
713 public void StoreLandObject(ILandObject parcel)
714 {
715 lock (ds)
716 {
717 DataTable land = ds.Tables["land"];
718 DataTable landaccesslist = ds.Tables["landaccesslist"];
719
720 DataRow landRow = land.Rows.Find(parcel.LandData.GlobalID.ToString());
721 if (landRow == null)
722 {
723 landRow = land.NewRow();
724 fillLandRow(landRow, parcel.LandData, parcel.RegionUUID);
725 land.Rows.Add(landRow);
726 }
727 else
728 {
729 fillLandRow(landRow, parcel.LandData, parcel.RegionUUID);
730 }
731
732 // I know this caused someone issues before, but OpenSim is unusable if we leave this stuff around
733 //using (SqliteCommand cmd = new SqliteCommand("delete from landaccesslist where LandUUID=:LandUUID", m_conn))
734 //{
735 // cmd.Parameters.Add(new SqliteParameter(":LandUUID", parcel.LandData.GlobalID.ToString()));
736 // cmd.ExecuteNonQuery();
737
738// }
739
740 // This is the slower.. but more appropriate thing to do
741
742 // We can't modify the table with direct queries before calling Commit() and re-filling them.
743 List<DataRow> rowsToDelete = new List<DataRow>();
744 foreach (DataRow rowToCheck in landaccesslist.Rows)
745 {
746 if (rowToCheck["LandUUID"].ToString() == parcel.LandData.GlobalID.ToString())
747 rowsToDelete.Add(rowToCheck);
748 }
749 for (int iter = 0; iter < rowsToDelete.Count; iter++)
750 {
751 landaccesslist.Rows.Remove(rowsToDelete[iter]);
752 }
753 rowsToDelete.Clear();
754 foreach (ParcelManager.ParcelAccessEntry entry in parcel.LandData.ParcelAccessList)
755 {
756 DataRow newAccessRow = landaccesslist.NewRow();
757 fillLandAccessRow(newAccessRow, entry, parcel.LandData.GlobalID);
758 landaccesslist.Rows.Add(newAccessRow);
759 }
760 }
761
762 Commit();
763 }
764
765 /// <summary>
766 ///
767 /// </summary>
768 /// <param name="regionUUID"></param>
769 /// <returns></returns>
770 public List<LandData> LoadLandObjects(UUID regionUUID)
771 {
772 List<LandData> landDataForRegion = new List<LandData>();
773 lock (ds)
774 {
775 DataTable land = ds.Tables["land"];
776 DataTable landaccesslist = ds.Tables["landaccesslist"];
777 string searchExp = "RegionUUID = '" + regionUUID + "'";
778 DataRow[] rawDataForRegion = land.Select(searchExp);
779 foreach (DataRow rawDataLand in rawDataForRegion)
780 {
781 LandData newLand = buildLandData(rawDataLand);
782 string accessListSearchExp = "LandUUID = '" + newLand.GlobalID + "'";
783 DataRow[] rawDataForLandAccessList = landaccesslist.Select(accessListSearchExp);
784 foreach (DataRow rawDataLandAccess in rawDataForLandAccessList)
785 {
786 newLand.ParcelAccessList.Add(buildLandAccessData(rawDataLandAccess));
787 }
788
789 landDataForRegion.Add(newLand);
790 }
791 }
792 return landDataForRegion;
793 }
794
795 /// <summary>
796 ///
797 /// </summary>
798 public void Commit()
799 {
800 //m_log.Debug("[SQLITE]: Starting commit");
801 lock (ds)
802 {
803 primDa.Update(ds, "prims");
804 shapeDa.Update(ds, "primshapes");
805
806 itemsDa.Update(ds, "primitems");
807
808 terrainDa.Update(ds, "terrain");
809 landDa.Update(ds, "land");
810 landAccessListDa.Update(ds, "landaccesslist");
811 try
812 {
813 regionSettingsDa.Update(ds, "regionsettings");
814 }
815 catch (SqliteException SqlEx)
816 {
817 throw new Exception(
818 "There was a SQL error or connection string configuration error when saving the region settings. This could be a bug, it could also happen if ConnectionString is defined in the [DatabaseService] section of StandaloneCommon.ini in the config_include folder. This could also happen if the config_include folder doesn't exist or if the OpenSim.ini [Architecture] section isn't set. If this is your first time running OpenSimulator, please restart the simulator and bug a developer to fix this!",
819 SqlEx);
820 }
821 ds.AcceptChanges();
822 }
823 }
824
825 /// <summary>
826 /// See <see cref="Commit"/>
827 /// </summary>
828 public void Shutdown()
829 {
830 Commit();
831 }
832
833 /***********************************************************************
834 *
835 * Database Definition Functions
836 *
837 * This should be db agnostic as we define them in ADO.NET terms
838 *
839 **********************************************************************/
840
841 protected void CreateDataSetMapping(IDataAdapter da, string tableName)
842 {
843 ITableMapping dbMapping = da.TableMappings.Add(tableName, tableName);
844 foreach (DataColumn col in ds.Tables[tableName].Columns)
845 {
846 dbMapping.ColumnMappings.Add(col.ColumnName, col.ColumnName);
847 }
848 }
849
850 /// <summary>
851 ///
852 /// </summary>
853 /// <param name="dt"></param>
854 /// <param name="name"></param>
855 /// <param name="type"></param>
856 private static void createCol(DataTable dt, string name, Type type)
857 {
858 DataColumn col = new DataColumn(name, type);
859 dt.Columns.Add(col);
860 }
861
862 /// <summary>
863 /// Creates the "terrain" table
864 /// </summary>
865 /// <returns>terrain table DataTable</returns>
866 private static DataTable createTerrainTable()
867 {
868 DataTable terrain = new DataTable("terrain");
869
870 createCol(terrain, "RegionUUID", typeof (String));
871 createCol(terrain, "Revision", typeof (Int32));
872 createCol(terrain, "Heightfield", typeof (Byte[]));
873
874 return terrain;
875 }
876
877 /// <summary>
878 /// Creates the "prims" table
879 /// </summary>
880 /// <returns>prim table DataTable</returns>
881 private static DataTable createPrimTable()
882 {
883 DataTable prims = new DataTable("prims");
884
885 createCol(prims, "UUID", typeof (String));
886 createCol(prims, "RegionUUID", typeof (String));
887 createCol(prims, "CreationDate", typeof (Int32));
888 createCol(prims, "Name", typeof (String));
889 createCol(prims, "SceneGroupID", typeof (String));
890 // various text fields
891 createCol(prims, "Text", typeof (String));
892 createCol(prims, "ColorR", typeof (Int32));
893 createCol(prims, "ColorG", typeof (Int32));
894 createCol(prims, "ColorB", typeof (Int32));
895 createCol(prims, "ColorA", typeof (Int32));
896 createCol(prims, "Description", typeof (String));
897 createCol(prims, "SitName", typeof (String));
898 createCol(prims, "TouchName", typeof (String));
899 // permissions
900 createCol(prims, "ObjectFlags", typeof (Int32));
901 createCol(prims, "CreatorID", typeof (String));
902 createCol(prims, "OwnerID", typeof (String));
903 createCol(prims, "GroupID", typeof (String));
904 createCol(prims, "LastOwnerID", typeof (String));
905 createCol(prims, "OwnerMask", typeof (Int32));
906 createCol(prims, "NextOwnerMask", typeof (Int32));
907 createCol(prims, "GroupMask", typeof (Int32));
908 createCol(prims, "EveryoneMask", typeof (Int32));
909 createCol(prims, "BaseMask", typeof (Int32));
910 // vectors
911 createCol(prims, "PositionX", typeof (Double));
912 createCol(prims, "PositionY", typeof (Double));
913 createCol(prims, "PositionZ", typeof (Double));
914 createCol(prims, "GroupPositionX", typeof (Double));
915 createCol(prims, "GroupPositionY", typeof (Double));
916 createCol(prims, "GroupPositionZ", typeof (Double));
917 createCol(prims, "VelocityX", typeof (Double));
918 createCol(prims, "VelocityY", typeof (Double));
919 createCol(prims, "VelocityZ", typeof (Double));
920 createCol(prims, "AngularVelocityX", typeof (Double));
921 createCol(prims, "AngularVelocityY", typeof (Double));
922 createCol(prims, "AngularVelocityZ", typeof (Double));
923 createCol(prims, "AccelerationX", typeof (Double));
924 createCol(prims, "AccelerationY", typeof (Double));
925 createCol(prims, "AccelerationZ", typeof (Double));
926 // quaternions
927 createCol(prims, "RotationX", typeof (Double));
928 createCol(prims, "RotationY", typeof (Double));
929 createCol(prims, "RotationZ", typeof (Double));
930 createCol(prims, "RotationW", typeof (Double));
931
932 // sit target
933 createCol(prims, "SitTargetOffsetX", typeof (Double));
934 createCol(prims, "SitTargetOffsetY", typeof (Double));
935 createCol(prims, "SitTargetOffsetZ", typeof (Double));
936
937 createCol(prims, "SitTargetOrientW", typeof (Double));
938 createCol(prims, "SitTargetOrientX", typeof (Double));
939 createCol(prims, "SitTargetOrientY", typeof (Double));
940 createCol(prims, "SitTargetOrientZ", typeof (Double));
941
942 createCol(prims, "PayPrice", typeof(Int32));
943 createCol(prims, "PayButton1", typeof(Int32));
944 createCol(prims, "PayButton2", typeof(Int32));
945 createCol(prims, "PayButton3", typeof(Int32));
946 createCol(prims, "PayButton4", typeof(Int32));
947
948 createCol(prims, "LoopedSound", typeof(String));
949 createCol(prims, "LoopedSoundGain", typeof(Double));
950 createCol(prims, "TextureAnimation", typeof(String));
951 createCol(prims, "ParticleSystem", typeof(String));
952
953 createCol(prims, "OmegaX", typeof(Double));
954 createCol(prims, "OmegaY", typeof(Double));
955 createCol(prims, "OmegaZ", typeof(Double));
956
957 createCol(prims, "CameraEyeOffsetX", typeof(Double));
958 createCol(prims, "CameraEyeOffsetY", typeof(Double));
959 createCol(prims, "CameraEyeOffsetZ", typeof(Double));
960
961 createCol(prims, "CameraAtOffsetX", typeof(Double));
962 createCol(prims, "CameraAtOffsetY", typeof(Double));
963 createCol(prims, "CameraAtOffsetZ", typeof(Double));
964
965 createCol(prims, "ForceMouselook", typeof(Int16));
966
967 createCol(prims, "ScriptAccessPin", typeof(Int32));
968
969 createCol(prims, "AllowedDrop", typeof(Int16));
970 createCol(prims, "DieAtEdge", typeof(Int16));
971
972 createCol(prims, "SalePrice", typeof(Int32));
973 createCol(prims, "SaleType", typeof(Int16));
974
975 // click action
976 createCol(prims, "ClickAction", typeof (Byte));
977
978 createCol(prims, "Material", typeof(Byte));
979
980 createCol(prims, "CollisionSound", typeof(String));
981 createCol(prims, "CollisionSoundVolume", typeof(Double));
982
983 createCol(prims, "VolumeDetect", typeof(Int16));
984
985 createCol(prims, "MediaURL", typeof(String));
986
987 // Add in contraints
988 prims.PrimaryKey = new DataColumn[] {prims.Columns["UUID"]};
989
990 return prims;
991 }
992
993 /// <summary>
994 /// Creates "primshapes" table
995 /// </summary>
996 /// <returns>shape table DataTable</returns>
997 private static DataTable createShapeTable()
998 {
999 DataTable shapes = new DataTable("primshapes");
1000 createCol(shapes, "UUID", typeof (String));
1001 // shape is an enum
1002 createCol(shapes, "Shape", typeof (Int32));
1003 // vectors
1004 createCol(shapes, "ScaleX", typeof (Double));
1005 createCol(shapes, "ScaleY", typeof (Double));
1006 createCol(shapes, "ScaleZ", typeof (Double));
1007 // paths
1008 createCol(shapes, "PCode", typeof (Int32));
1009 createCol(shapes, "PathBegin", typeof (Int32));
1010 createCol(shapes, "PathEnd", typeof (Int32));
1011 createCol(shapes, "PathScaleX", typeof (Int32));
1012 createCol(shapes, "PathScaleY", typeof (Int32));
1013 createCol(shapes, "PathShearX", typeof (Int32));
1014 createCol(shapes, "PathShearY", typeof (Int32));
1015 createCol(shapes, "PathSkew", typeof (Int32));
1016 createCol(shapes, "PathCurve", typeof (Int32));
1017 createCol(shapes, "PathRadiusOffset", typeof (Int32));
1018 createCol(shapes, "PathRevolutions", typeof (Int32));
1019 createCol(shapes, "PathTaperX", typeof (Int32));
1020 createCol(shapes, "PathTaperY", typeof (Int32));
1021 createCol(shapes, "PathTwist", typeof (Int32));
1022 createCol(shapes, "PathTwistBegin", typeof (Int32));
1023 // profile
1024 createCol(shapes, "ProfileBegin", typeof (Int32));
1025 createCol(shapes, "ProfileEnd", typeof (Int32));
1026 createCol(shapes, "ProfileCurve", typeof (Int32));
1027 createCol(shapes, "ProfileHollow", typeof (Int32));
1028 createCol(shapes, "State", typeof(Int32));
1029 // text TODO: this isn't right, but I'm not sure the right
1030 // way to specify this as a blob atm
1031 createCol(shapes, "Texture", typeof (Byte[]));
1032 createCol(shapes, "ExtraParams", typeof (Byte[]));
1033 createCol(shapes, "Media", typeof(String));
1034
1035 shapes.PrimaryKey = new DataColumn[] {shapes.Columns["UUID"]};
1036
1037 return shapes;
1038 }
1039
1040 /// <summary>
1041 /// creates "primitems" table
1042 /// </summary>
1043 /// <returns>item table DataTable</returns>
1044 private static DataTable createItemsTable()
1045 {
1046 DataTable items = new DataTable("primitems");
1047
1048 createCol(items, "itemID", typeof (String));
1049 createCol(items, "primID", typeof (String));
1050 createCol(items, "assetID", typeof (String));
1051 createCol(items, "parentFolderID", typeof (String));
1052
1053 createCol(items, "invType", typeof (Int32));
1054 createCol(items, "assetType", typeof (Int32));
1055
1056 createCol(items, "name", typeof (String));
1057 createCol(items, "description", typeof (String));
1058
1059 createCol(items, "creationDate", typeof (Int64));
1060 createCol(items, "creatorID", typeof (String));
1061 createCol(items, "ownerID", typeof (String));
1062 createCol(items, "lastOwnerID", typeof (String));
1063 createCol(items, "groupID", typeof (String));
1064
1065 createCol(items, "nextPermissions", typeof (UInt32));
1066 createCol(items, "currentPermissions", typeof (UInt32));
1067 createCol(items, "basePermissions", typeof (UInt32));
1068 createCol(items, "everyonePermissions", typeof (UInt32));
1069 createCol(items, "groupPermissions", typeof (UInt32));
1070 createCol(items, "flags", typeof (UInt32));
1071
1072 items.PrimaryKey = new DataColumn[] { items.Columns["itemID"] };
1073
1074 return items;
1075 }
1076
1077 /// <summary>
1078 /// Creates "land" table
1079 /// </summary>
1080 /// <returns>land table DataTable</returns>
1081 private static DataTable createLandTable()
1082 {
1083 DataTable land = new DataTable("land");
1084 createCol(land, "UUID", typeof (String));
1085 createCol(land, "RegionUUID", typeof (String));
1086 createCol(land, "LocalLandID", typeof (UInt32));
1087
1088 // Bitmap is a byte[512]
1089 createCol(land, "Bitmap", typeof (Byte[]));
1090
1091 createCol(land, "Name", typeof (String));
1092 createCol(land, "Desc", typeof (String));
1093 createCol(land, "OwnerUUID", typeof (String));
1094 createCol(land, "IsGroupOwned", typeof (Boolean));
1095 createCol(land, "Area", typeof (Int32));
1096 createCol(land, "AuctionID", typeof (Int32)); //Unemplemented
1097 createCol(land, "Category", typeof (Int32)); //Enum OpenMetaverse.Parcel.ParcelCategory
1098 createCol(land, "ClaimDate", typeof (Int32));
1099 createCol(land, "ClaimPrice", typeof (Int32));
1100 createCol(land, "GroupUUID", typeof (string));
1101 createCol(land, "SalePrice", typeof (Int32));
1102 createCol(land, "LandStatus", typeof (Int32)); //Enum. OpenMetaverse.Parcel.ParcelStatus
1103 createCol(land, "LandFlags", typeof (UInt32));
1104 createCol(land, "LandingType", typeof (Byte));
1105 createCol(land, "MediaAutoScale", typeof (Byte));
1106 createCol(land, "MediaTextureUUID", typeof (String));
1107 createCol(land, "MediaURL", typeof (String));
1108 createCol(land, "MusicURL", typeof (String));
1109 createCol(land, "PassHours", typeof (Double));
1110 createCol(land, "PassPrice", typeof (UInt32));
1111 createCol(land, "SnapshotUUID", typeof (String));
1112 createCol(land, "UserLocationX", typeof (Double));
1113 createCol(land, "UserLocationY", typeof (Double));
1114 createCol(land, "UserLocationZ", typeof (Double));
1115 createCol(land, "UserLookAtX", typeof (Double));
1116 createCol(land, "UserLookAtY", typeof (Double));
1117 createCol(land, "UserLookAtZ", typeof (Double));
1118 createCol(land, "AuthbuyerID", typeof(String));
1119 createCol(land, "OtherCleanTime", typeof(Int32));
1120
1121 land.PrimaryKey = new DataColumn[] {land.Columns["UUID"]};
1122
1123 return land;
1124 }
1125
1126 /// <summary>
1127 /// create "landaccesslist" table
1128 /// </summary>
1129 /// <returns>Landacceslist DataTable</returns>
1130 private static DataTable createLandAccessListTable()
1131 {
1132 DataTable landaccess = new DataTable("landaccesslist");
1133 createCol(landaccess, "LandUUID", typeof (String));
1134 createCol(landaccess, "AccessUUID", typeof (String));
1135 createCol(landaccess, "Flags", typeof (UInt32));
1136
1137 return landaccess;
1138 }
1139
1140 private static DataTable createRegionSettingsTable()
1141 {
1142 DataTable regionsettings = new DataTable("regionsettings");
1143 createCol(regionsettings, "regionUUID", typeof(String));
1144 createCol(regionsettings, "block_terraform", typeof (Int32));
1145 createCol(regionsettings, "block_fly", typeof (Int32));
1146 createCol(regionsettings, "allow_damage", typeof (Int32));
1147 createCol(regionsettings, "restrict_pushing", typeof (Int32));
1148 createCol(regionsettings, "allow_land_resell", typeof (Int32));
1149 createCol(regionsettings, "allow_land_join_divide", typeof (Int32));
1150 createCol(regionsettings, "block_show_in_search", typeof (Int32));
1151 createCol(regionsettings, "agent_limit", typeof (Int32));
1152 createCol(regionsettings, "object_bonus", typeof (Double));
1153 createCol(regionsettings, "maturity", typeof (Int32));
1154 createCol(regionsettings, "disable_scripts", typeof (Int32));
1155 createCol(regionsettings, "disable_collisions", typeof (Int32));
1156 createCol(regionsettings, "disable_physics", typeof (Int32));
1157 createCol(regionsettings, "terrain_texture_1", typeof(String));
1158 createCol(regionsettings, "terrain_texture_2", typeof(String));
1159 createCol(regionsettings, "terrain_texture_3", typeof(String));
1160 createCol(regionsettings, "terrain_texture_4", typeof(String));
1161 createCol(regionsettings, "elevation_1_nw", typeof (Double));
1162 createCol(regionsettings, "elevation_2_nw", typeof (Double));
1163 createCol(regionsettings, "elevation_1_ne", typeof (Double));
1164 createCol(regionsettings, "elevation_2_ne", typeof (Double));
1165 createCol(regionsettings, "elevation_1_se", typeof (Double));
1166 createCol(regionsettings, "elevation_2_se", typeof (Double));
1167 createCol(regionsettings, "elevation_1_sw", typeof (Double));
1168 createCol(regionsettings, "elevation_2_sw", typeof (Double));
1169 createCol(regionsettings, "water_height", typeof (Double));
1170 createCol(regionsettings, "terrain_raise_limit", typeof (Double));
1171 createCol(regionsettings, "terrain_lower_limit", typeof (Double));
1172 createCol(regionsettings, "use_estate_sun", typeof (Int32));
1173 createCol(regionsettings, "sandbox", typeof (Int32));
1174 createCol(regionsettings, "sunvectorx",typeof (Double));
1175 createCol(regionsettings, "sunvectory",typeof (Double));
1176 createCol(regionsettings, "sunvectorz",typeof (Double));
1177 createCol(regionsettings, "fixed_sun", typeof (Int32));
1178 createCol(regionsettings, "sun_position", typeof (Double));
1179 createCol(regionsettings, "covenant", typeof(String));
1180 createCol(regionsettings, "map_tile_ID", typeof(String));
1181 regionsettings.PrimaryKey = new DataColumn[] { regionsettings.Columns["regionUUID"] };
1182 return regionsettings;
1183 }
1184
1185 /***********************************************************************
1186 *
1187 * Convert between ADO.NET <=> OpenSim Objects
1188 *
1189 * These should be database independant
1190 *
1191 **********************************************************************/
1192
1193 /// <summary>
1194 ///
1195 /// </summary>
1196 /// <param name="row"></param>
1197 /// <returns></returns>
1198 private SceneObjectPart buildPrim(DataRow row)
1199 {
1200 // Code commented. Uncomment to test the unit test inline.
1201
1202 // The unit test mentions this commented code for the purposes
1203 // of debugging a unit test failure
1204
1205 // SceneObjectGroup sog = new SceneObjectGroup();
1206 // SceneObjectPart sop = new SceneObjectPart();
1207 // sop.LocalId = 1;
1208 // sop.Name = "object1";
1209 // sop.Description = "object1";
1210 // sop.Text = "";
1211 // sop.SitName = "";
1212 // sop.TouchName = "";
1213 // sop.UUID = UUID.Random();
1214 // sop.Shape = PrimitiveBaseShape.Default;
1215 // sog.SetRootPart(sop);
1216 // Add breakpoint in above line. Check sop fields.
1217
1218 // TODO: this doesn't work yet because something more
1219 // interesting has to be done to actually get these values
1220 // back out. Not enough time to figure it out yet.
1221
1222 SceneObjectPart prim = new SceneObjectPart();
1223 prim.UUID = new UUID((String) row["UUID"]);
1224 // explicit conversion of integers is required, which sort
1225 // of sucks. No idea if there is a shortcut here or not.
1226 prim.CreationDate = Convert.ToInt32(row["CreationDate"]);
1227 prim.Name = row["Name"] == DBNull.Value ? string.Empty : (string)row["Name"];
1228 // various text fields
1229 prim.Text = (String) row["Text"];
1230 prim.Color = Color.FromArgb(Convert.ToInt32(row["ColorA"]),
1231 Convert.ToInt32(row["ColorR"]),
1232 Convert.ToInt32(row["ColorG"]),
1233 Convert.ToInt32(row["ColorB"]));
1234 prim.Description = (String) row["Description"];
1235 prim.SitName = (String) row["SitName"];
1236 prim.TouchName = (String) row["TouchName"];
1237 // permissions
1238 prim.ObjectFlags = Convert.ToUInt32(row["ObjectFlags"]);
1239 prim.CreatorID = new UUID((String) row["CreatorID"]);
1240 prim.OwnerID = new UUID((String) row["OwnerID"]);
1241 prim.GroupID = new UUID((String) row["GroupID"]);
1242 prim.LastOwnerID = new UUID((String) row["LastOwnerID"]);
1243 prim.OwnerMask = Convert.ToUInt32(row["OwnerMask"]);
1244 prim.NextOwnerMask = Convert.ToUInt32(row["NextOwnerMask"]);
1245 prim.GroupMask = Convert.ToUInt32(row["GroupMask"]);
1246 prim.EveryoneMask = Convert.ToUInt32(row["EveryoneMask"]);
1247 prim.BaseMask = Convert.ToUInt32(row["BaseMask"]);
1248 // vectors
1249 prim.OffsetPosition = new Vector3(
1250 Convert.ToSingle(row["PositionX"]),
1251 Convert.ToSingle(row["PositionY"]),
1252 Convert.ToSingle(row["PositionZ"])
1253 );
1254 prim.GroupPosition = new Vector3(
1255 Convert.ToSingle(row["GroupPositionX"]),
1256 Convert.ToSingle(row["GroupPositionY"]),
1257 Convert.ToSingle(row["GroupPositionZ"])
1258 );
1259 prim.Velocity = new Vector3(
1260 Convert.ToSingle(row["VelocityX"]),
1261 Convert.ToSingle(row["VelocityY"]),
1262 Convert.ToSingle(row["VelocityZ"])
1263 );
1264 prim.AngularVelocity = new Vector3(
1265 Convert.ToSingle(row["AngularVelocityX"]),
1266 Convert.ToSingle(row["AngularVelocityY"]),
1267 Convert.ToSingle(row["AngularVelocityZ"])
1268 );
1269 prim.Acceleration = new Vector3(
1270 Convert.ToSingle(row["AccelerationX"]),
1271 Convert.ToSingle(row["AccelerationY"]),
1272 Convert.ToSingle(row["AccelerationZ"])
1273 );
1274 // quaternions
1275 prim.RotationOffset = new Quaternion(
1276 Convert.ToSingle(row["RotationX"]),
1277 Convert.ToSingle(row["RotationY"]),
1278 Convert.ToSingle(row["RotationZ"]),
1279 Convert.ToSingle(row["RotationW"])
1280 );
1281
1282 prim.SitTargetPositionLL = new Vector3(
1283 Convert.ToSingle(row["SitTargetOffsetX"]),
1284 Convert.ToSingle(row["SitTargetOffsetY"]),
1285 Convert.ToSingle(row["SitTargetOffsetZ"]));
1286 prim.SitTargetOrientationLL = new Quaternion(
1287 Convert.ToSingle(
1288 row["SitTargetOrientX"]),
1289 Convert.ToSingle(
1290 row["SitTargetOrientY"]),
1291 Convert.ToSingle(
1292 row["SitTargetOrientZ"]),
1293 Convert.ToSingle(
1294 row["SitTargetOrientW"]));
1295
1296 prim.ClickAction = Convert.ToByte(row["ClickAction"]);
1297 prim.PayPrice[0] = Convert.ToInt32(row["PayPrice"]);
1298 prim.PayPrice[1] = Convert.ToInt32(row["PayButton1"]);
1299 prim.PayPrice[2] = Convert.ToInt32(row["PayButton2"]);
1300 prim.PayPrice[3] = Convert.ToInt32(row["PayButton3"]);
1301 prim.PayPrice[4] = Convert.ToInt32(row["PayButton4"]);
1302
1303 prim.Sound = new UUID(row["LoopedSound"].ToString());
1304 prim.SoundGain = Convert.ToSingle(row["LoopedSoundGain"]);
1305 prim.SoundFlags = 1; // If it's persisted at all, it's looped
1306
1307 if (!row.IsNull("TextureAnimation"))
1308 prim.TextureAnimation = Convert.FromBase64String(row["TextureAnimation"].ToString());
1309 if (!row.IsNull("ParticleSystem"))
1310 prim.ParticleSystem = Convert.FromBase64String(row["ParticleSystem"].ToString());
1311
1312 prim.AngularVelocity = new Vector3(
1313 Convert.ToSingle(row["OmegaX"]),
1314 Convert.ToSingle(row["OmegaY"]),
1315 Convert.ToSingle(row["OmegaZ"])
1316 );
1317
1318 prim.SetCameraEyeOffset(new Vector3(
1319 Convert.ToSingle(row["CameraEyeOffsetX"]),
1320 Convert.ToSingle(row["CameraEyeOffsetY"]),
1321 Convert.ToSingle(row["CameraEyeOffsetZ"])
1322 ));
1323
1324 prim.SetCameraAtOffset(new Vector3(
1325 Convert.ToSingle(row["CameraAtOffsetX"]),
1326 Convert.ToSingle(row["CameraAtOffsetY"]),
1327 Convert.ToSingle(row["CameraAtOffsetZ"])
1328 ));
1329
1330 if (Convert.ToInt16(row["ForceMouselook"]) != 0)
1331 prim.SetForceMouselook(true);
1332
1333 prim.ScriptAccessPin = Convert.ToInt32(row["ScriptAccessPin"]);
1334
1335 if (Convert.ToInt16(row["AllowedDrop"]) != 0)
1336 prim.AllowedDrop = true;
1337
1338 if (Convert.ToInt16(row["DieAtEdge"]) != 0)
1339 prim.DIE_AT_EDGE = true;
1340
1341 prim.SalePrice = Convert.ToInt32(row["SalePrice"]);
1342 prim.ObjectSaleType = Convert.ToByte(row["SaleType"]);
1343
1344 prim.Material = Convert.ToByte(row["Material"]);
1345
1346 prim.CollisionSound = new UUID(row["CollisionSound"].ToString());
1347 prim.CollisionSoundVolume = Convert.ToSingle(row["CollisionSoundVolume"]);
1348
1349 if (Convert.ToInt16(row["VolumeDetect"]) != 0)
1350 prim.VolumeDetectActive = true;
1351
1352 if (!(row["MediaURL"] is System.DBNull))
1353 {
1354 //m_log.DebugFormat("[SQLITE]: MediaUrl type [{0}]", row["MediaURL"].GetType());
1355 prim.MediaUrl = (string)row["MediaURL"];
1356 }
1357
1358 return prim;
1359 }
1360
1361 /// <summary>
1362 /// Build a prim inventory item from the persisted data.
1363 /// </summary>
1364 /// <param name="row"></param>
1365 /// <returns></returns>
1366 private static TaskInventoryItem buildItem(DataRow row)
1367 {
1368 TaskInventoryItem taskItem = new TaskInventoryItem();
1369
1370 taskItem.ItemID = new UUID((String)row["itemID"]);
1371 taskItem.ParentPartID = new UUID((String)row["primID"]);
1372 taskItem.AssetID = new UUID((String)row["assetID"]);
1373 taskItem.ParentID = new UUID((String)row["parentFolderID"]);
1374
1375 taskItem.InvType = Convert.ToInt32(row["invType"]);
1376 taskItem.Type = Convert.ToInt32(row["assetType"]);
1377
1378 taskItem.Name = (String)row["name"];
1379 taskItem.Description = (String)row["description"];
1380 taskItem.CreationDate = Convert.ToUInt32(row["creationDate"]);
1381 taskItem.CreatorID = new UUID((String)row["creatorID"]);
1382 taskItem.OwnerID = new UUID((String)row["ownerID"]);
1383 taskItem.LastOwnerID = new UUID((String)row["lastOwnerID"]);
1384 taskItem.GroupID = new UUID((String)row["groupID"]);
1385
1386 taskItem.NextPermissions = Convert.ToUInt32(row["nextPermissions"]);
1387 taskItem.CurrentPermissions = Convert.ToUInt32(row["currentPermissions"]);
1388 taskItem.BasePermissions = Convert.ToUInt32(row["basePermissions"]);
1389 taskItem.EveryonePermissions = Convert.ToUInt32(row["everyonePermissions"]);
1390 taskItem.GroupPermissions = Convert.ToUInt32(row["groupPermissions"]);
1391 taskItem.Flags = Convert.ToUInt32(row["flags"]);
1392
1393 return taskItem;
1394 }
1395
1396 /// <summary>
1397 /// Build a Land Data from the persisted data.
1398 /// </summary>
1399 /// <param name="row"></param>
1400 /// <returns></returns>
1401 private LandData buildLandData(DataRow row)
1402 {
1403 LandData newData = new LandData();
1404
1405 newData.GlobalID = new UUID((String) row["UUID"]);
1406 newData.LocalID = Convert.ToInt32(row["LocalLandID"]);
1407
1408 // Bitmap is a byte[512]
1409 newData.Bitmap = (Byte[]) row["Bitmap"];
1410
1411 newData.Name = (String) row["Name"];
1412 newData.Description = (String) row["Desc"];
1413 newData.OwnerID = (UUID)(String) row["OwnerUUID"];
1414 newData.IsGroupOwned = (Boolean) row["IsGroupOwned"];
1415 newData.Area = Convert.ToInt32(row["Area"]);
1416 newData.AuctionID = Convert.ToUInt32(row["AuctionID"]); //Unemplemented
1417 newData.Category = (ParcelCategory) Convert.ToInt32(row["Category"]);
1418 //Enum OpenMetaverse.Parcel.ParcelCategory
1419 newData.ClaimDate = Convert.ToInt32(row["ClaimDate"]);
1420 newData.ClaimPrice = Convert.ToInt32(row["ClaimPrice"]);
1421 newData.GroupID = new UUID((String) row["GroupUUID"]);
1422 newData.SalePrice = Convert.ToInt32(row["SalePrice"]);
1423 newData.Status = (ParcelStatus) Convert.ToInt32(row["LandStatus"]);
1424 //Enum. OpenMetaverse.Parcel.ParcelStatus
1425 newData.Flags = Convert.ToUInt32(row["LandFlags"]);
1426 newData.LandingType = (Byte) row["LandingType"];
1427 newData.MediaAutoScale = (Byte) row["MediaAutoScale"];
1428 newData.MediaID = new UUID((String) row["MediaTextureUUID"]);
1429 newData.MediaURL = (String) row["MediaURL"];
1430 newData.MusicURL = (String) row["MusicURL"];
1431 newData.PassHours = Convert.ToSingle(row["PassHours"]);
1432 newData.PassPrice = Convert.ToInt32(row["PassPrice"]);
1433 newData.SnapshotID = (UUID)(String) row["SnapshotUUID"];
1434 try
1435 {
1436
1437 newData.UserLocation =
1438 new Vector3(Convert.ToSingle(row["UserLocationX"]), Convert.ToSingle(row["UserLocationY"]),
1439 Convert.ToSingle(row["UserLocationZ"]));
1440 newData.UserLookAt =
1441 new Vector3(Convert.ToSingle(row["UserLookAtX"]), Convert.ToSingle(row["UserLookAtY"]),
1442 Convert.ToSingle(row["UserLookAtZ"]));
1443
1444 }
1445 catch (InvalidCastException)
1446 {
1447 m_log.ErrorFormat("[SQLITE REGION DB]: unable to get parcel telehub settings for {1}", newData.Name);
1448 newData.UserLocation = Vector3.Zero;
1449 newData.UserLookAt = Vector3.Zero;
1450 }
1451 newData.ParcelAccessList = new List<ParcelManager.ParcelAccessEntry>();
1452 UUID authBuyerID = UUID.Zero;
1453
1454 UUID.TryParse((string)row["AuthbuyerID"], out authBuyerID);
1455
1456 newData.OtherCleanTime = Convert.ToInt32(row["OtherCleanTime"]);
1457
1458 return newData;
1459 }
1460
1461 private RegionSettings buildRegionSettings(DataRow row)
1462 {
1463 RegionSettings newSettings = new RegionSettings();
1464
1465 newSettings.RegionUUID = new UUID((string) row["regionUUID"]);
1466 newSettings.BlockTerraform = Convert.ToBoolean(row["block_terraform"]);
1467 newSettings.AllowDamage = Convert.ToBoolean(row["allow_damage"]);
1468 newSettings.BlockFly = Convert.ToBoolean(row["block_fly"]);
1469 newSettings.RestrictPushing = Convert.ToBoolean(row["restrict_pushing"]);
1470 newSettings.AllowLandResell = Convert.ToBoolean(row["allow_land_resell"]);
1471 newSettings.AllowLandJoinDivide = Convert.ToBoolean(row["allow_land_join_divide"]);
1472 newSettings.BlockShowInSearch = Convert.ToBoolean(row["block_show_in_search"]);
1473 newSettings.AgentLimit = Convert.ToInt32(row["agent_limit"]);
1474 newSettings.ObjectBonus = Convert.ToDouble(row["object_bonus"]);
1475 newSettings.Maturity = Convert.ToInt32(row["maturity"]);
1476 newSettings.DisableScripts = Convert.ToBoolean(row["disable_scripts"]);
1477 newSettings.DisableCollisions = Convert.ToBoolean(row["disable_collisions"]);
1478 newSettings.DisablePhysics = Convert.ToBoolean(row["disable_physics"]);
1479 newSettings.TerrainTexture1 = new UUID((String) row["terrain_texture_1"]);
1480 newSettings.TerrainTexture2 = new UUID((String) row["terrain_texture_2"]);
1481 newSettings.TerrainTexture3 = new UUID((String) row["terrain_texture_3"]);
1482 newSettings.TerrainTexture4 = new UUID((String) row["terrain_texture_4"]);
1483 newSettings.Elevation1NW = Convert.ToDouble(row["elevation_1_nw"]);
1484 newSettings.Elevation2NW = Convert.ToDouble(row["elevation_2_nw"]);
1485 newSettings.Elevation1NE = Convert.ToDouble(row["elevation_1_ne"]);
1486 newSettings.Elevation2NE = Convert.ToDouble(row["elevation_2_ne"]);
1487 newSettings.Elevation1SE = Convert.ToDouble(row["elevation_1_se"]);
1488 newSettings.Elevation2SE = Convert.ToDouble(row["elevation_2_se"]);
1489 newSettings.Elevation1SW = Convert.ToDouble(row["elevation_1_sw"]);
1490 newSettings.Elevation2SW = Convert.ToDouble(row["elevation_2_sw"]);
1491 newSettings.WaterHeight = Convert.ToDouble(row["water_height"]);
1492 newSettings.TerrainRaiseLimit = Convert.ToDouble(row["terrain_raise_limit"]);
1493 newSettings.TerrainLowerLimit = Convert.ToDouble(row["terrain_lower_limit"]);
1494 newSettings.UseEstateSun = Convert.ToBoolean(row["use_estate_sun"]);
1495 newSettings.Sandbox = Convert.ToBoolean(row["sandbox"]);
1496 newSettings.SunVector = new Vector3 (
1497 Convert.ToSingle(row["sunvectorx"]),
1498 Convert.ToSingle(row["sunvectory"]),
1499 Convert.ToSingle(row["sunvectorz"])
1500 );
1501 newSettings.FixedSun = Convert.ToBoolean(row["fixed_sun"]);
1502 newSettings.SunPosition = Convert.ToDouble(row["sun_position"]);
1503 newSettings.Covenant = new UUID((String) row["covenant"]);
1504 newSettings.TerrainImageID = new UUID((String)row["map_tile_ID"]);
1505
1506 return newSettings;
1507 }
1508
1509 /// <summary>
1510 /// Build a land access entry from the persisted data.
1511 /// </summary>
1512 /// <param name="row"></param>
1513 /// <returns></returns>
1514 private static ParcelManager.ParcelAccessEntry buildLandAccessData(DataRow row)
1515 {
1516 ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry();
1517 entry.AgentID = new UUID((string) row["AccessUUID"]);
1518 entry.Flags = (AccessList) row["Flags"];
1519 entry.Time = new DateTime();
1520 return entry;
1521 }
1522
1523 /// <summary>
1524 ///
1525 /// </summary>
1526 /// <param name="val"></param>
1527 /// <returns></returns>
1528 private static Array serializeTerrain(double[,] val)
1529 {
1530 MemoryStream str = new MemoryStream(((int)Constants.RegionSize * (int)Constants.RegionSize) *sizeof (double));
1531 BinaryWriter bw = new BinaryWriter(str);
1532
1533 // TODO: COMPATIBILITY - Add byte-order conversions
1534 for (int x = 0; x < (int)Constants.RegionSize; x++)
1535 for (int y = 0; y < (int)Constants.RegionSize; y++)
1536 bw.Write(val[x, y]);
1537
1538 return str.ToArray();
1539 }
1540
1541// private void fillTerrainRow(DataRow row, UUID regionUUID, int rev, double[,] val)
1542// {
1543// row["RegionUUID"] = regionUUID;
1544// row["Revision"] = rev;
1545
1546 // MemoryStream str = new MemoryStream(((int)Constants.RegionSize * (int)Constants.RegionSize)*sizeof (double));
1547// BinaryWriter bw = new BinaryWriter(str);
1548
1549// // TODO: COMPATIBILITY - Add byte-order conversions
1550 // for (int x = 0; x < (int)Constants.RegionSize; x++)
1551 // for (int y = 0; y < (int)Constants.RegionSize; y++)
1552// bw.Write(val[x, y]);
1553
1554// row["Heightfield"] = str.ToArray();
1555// }
1556
1557 /// <summary>
1558 ///
1559 /// </summary>
1560 /// <param name="row"></param>
1561 /// <param name="prim"></param>
1562 /// <param name="sceneGroupID"></param>
1563 /// <param name="regionUUID"></param>
1564 private static void fillPrimRow(DataRow row, SceneObjectPart prim, UUID sceneGroupID, UUID regionUUID)
1565 {
1566 row["UUID"] = prim.UUID.ToString();
1567 row["RegionUUID"] = regionUUID.ToString();
1568 row["CreationDate"] = prim.CreationDate;
1569 row["Name"] = prim.Name;
1570 row["SceneGroupID"] = sceneGroupID.ToString();
1571 // the UUID of the root part for this SceneObjectGroup
1572 // various text fields
1573 row["Text"] = prim.Text;
1574 row["Description"] = prim.Description;
1575 row["SitName"] = prim.SitName;
1576 row["TouchName"] = prim.TouchName;
1577 // permissions
1578 row["ObjectFlags"] = prim.ObjectFlags;
1579 row["CreatorID"] = prim.CreatorID.ToString();
1580 row["OwnerID"] = prim.OwnerID.ToString();
1581 row["GroupID"] = prim.GroupID.ToString();
1582 row["LastOwnerID"] = prim.LastOwnerID.ToString();
1583 row["OwnerMask"] = prim.OwnerMask;
1584 row["NextOwnerMask"] = prim.NextOwnerMask;
1585 row["GroupMask"] = prim.GroupMask;
1586 row["EveryoneMask"] = prim.EveryoneMask;
1587 row["BaseMask"] = prim.BaseMask;
1588 // vectors
1589 row["PositionX"] = prim.OffsetPosition.X;
1590 row["PositionY"] = prim.OffsetPosition.Y;
1591 row["PositionZ"] = prim.OffsetPosition.Z;
1592 row["GroupPositionX"] = prim.GroupPosition.X;
1593 row["GroupPositionY"] = prim.GroupPosition.Y;
1594 row["GroupPositionZ"] = prim.GroupPosition.Z;
1595 row["VelocityX"] = prim.Velocity.X;
1596 row["VelocityY"] = prim.Velocity.Y;
1597 row["VelocityZ"] = prim.Velocity.Z;
1598 row["AngularVelocityX"] = prim.AngularVelocity.X;
1599 row["AngularVelocityY"] = prim.AngularVelocity.Y;
1600 row["AngularVelocityZ"] = prim.AngularVelocity.Z;
1601 row["AccelerationX"] = prim.Acceleration.X;
1602 row["AccelerationY"] = prim.Acceleration.Y;
1603 row["AccelerationZ"] = prim.Acceleration.Z;
1604 // quaternions
1605 row["RotationX"] = prim.RotationOffset.X;
1606 row["RotationY"] = prim.RotationOffset.Y;
1607 row["RotationZ"] = prim.RotationOffset.Z;
1608 row["RotationW"] = prim.RotationOffset.W;
1609
1610 // Sit target
1611 Vector3 sitTargetPos = prim.SitTargetPositionLL;
1612 row["SitTargetOffsetX"] = sitTargetPos.X;
1613 row["SitTargetOffsetY"] = sitTargetPos.Y;
1614 row["SitTargetOffsetZ"] = sitTargetPos.Z;
1615
1616 Quaternion sitTargetOrient = prim.SitTargetOrientationLL;
1617 row["SitTargetOrientW"] = sitTargetOrient.W;
1618 row["SitTargetOrientX"] = sitTargetOrient.X;
1619 row["SitTargetOrientY"] = sitTargetOrient.Y;
1620 row["SitTargetOrientZ"] = sitTargetOrient.Z;
1621 row["ColorR"] = Convert.ToInt32(prim.Color.R);
1622 row["ColorG"] = Convert.ToInt32(prim.Color.G);
1623 row["ColorB"] = Convert.ToInt32(prim.Color.B);
1624 row["ColorA"] = Convert.ToInt32(prim.Color.A);
1625 row["PayPrice"] = prim.PayPrice[0];
1626 row["PayButton1"] = prim.PayPrice[1];
1627 row["PayButton2"] = prim.PayPrice[2];
1628 row["PayButton3"] = prim.PayPrice[3];
1629 row["PayButton4"] = prim.PayPrice[4];
1630
1631 row["TextureAnimation"] = Convert.ToBase64String(prim.TextureAnimation);
1632 row["ParticleSystem"] = Convert.ToBase64String(prim.ParticleSystem);
1633
1634 row["OmegaX"] = prim.AngularVelocity.X;
1635 row["OmegaY"] = prim.AngularVelocity.Y;
1636 row["OmegaZ"] = prim.AngularVelocity.Z;
1637
1638 row["CameraEyeOffsetX"] = prim.GetCameraEyeOffset().X;
1639 row["CameraEyeOffsetY"] = prim.GetCameraEyeOffset().Y;
1640 row["CameraEyeOffsetZ"] = prim.GetCameraEyeOffset().Z;
1641
1642 row["CameraAtOffsetX"] = prim.GetCameraAtOffset().X;
1643 row["CameraAtOffsetY"] = prim.GetCameraAtOffset().Y;
1644 row["CameraAtOffsetZ"] = prim.GetCameraAtOffset().Z;
1645
1646
1647 if ((prim.SoundFlags & 1) != 0) // Looped
1648 {
1649 row["LoopedSound"] = prim.Sound.ToString();
1650 row["LoopedSoundGain"] = prim.SoundGain;
1651 }
1652 else
1653 {
1654 row["LoopedSound"] = UUID.Zero.ToString();
1655 row["LoopedSoundGain"] = 0.0f;
1656 }
1657
1658 if (prim.GetForceMouselook())
1659 row["ForceMouselook"] = 1;
1660 else
1661 row["ForceMouselook"] = 0;
1662
1663 row["ScriptAccessPin"] = prim.ScriptAccessPin;
1664
1665 if (prim.AllowedDrop)
1666 row["AllowedDrop"] = 1;
1667 else
1668 row["AllowedDrop"] = 0;
1669
1670 if (prim.DIE_AT_EDGE)
1671 row["DieAtEdge"] = 1;
1672 else
1673 row["DieAtEdge"] = 0;
1674
1675 row["SalePrice"] = prim.SalePrice;
1676 row["SaleType"] = Convert.ToInt16(prim.ObjectSaleType);
1677
1678 // click action
1679 row["ClickAction"] = prim.ClickAction;
1680
1681 row["SalePrice"] = prim.SalePrice;
1682 row["Material"] = prim.Material;
1683
1684 row["CollisionSound"] = prim.CollisionSound.ToString();
1685 row["CollisionSoundVolume"] = prim.CollisionSoundVolume;
1686 if (prim.VolumeDetectActive)
1687 row["VolumeDetect"] = 1;
1688 else
1689 row["VolumeDetect"] = 0;
1690
1691 row["MediaURL"] = prim.MediaUrl;
1692 }
1693
1694 /// <summary>
1695 ///
1696 /// </summary>
1697 /// <param name="row"></param>
1698 /// <param name="taskItem"></param>
1699 private static void fillItemRow(DataRow row, TaskInventoryItem taskItem)
1700 {
1701 row["itemID"] = taskItem.ItemID.ToString();
1702 row["primID"] = taskItem.ParentPartID.ToString();
1703 row["assetID"] = taskItem.AssetID.ToString();
1704 row["parentFolderID"] = taskItem.ParentID.ToString();
1705
1706 row["invType"] = taskItem.InvType;
1707 row["assetType"] = taskItem.Type;
1708
1709 row["name"] = taskItem.Name;
1710 row["description"] = taskItem.Description;
1711 row["creationDate"] = taskItem.CreationDate;
1712 row["creatorID"] = taskItem.CreatorID.ToString();
1713 row["ownerID"] = taskItem.OwnerID.ToString();
1714 row["lastOwnerID"] = taskItem.LastOwnerID.ToString();
1715 row["groupID"] = taskItem.GroupID.ToString();
1716 row["nextPermissions"] = taskItem.NextPermissions;
1717 row["currentPermissions"] = taskItem.CurrentPermissions;
1718 row["basePermissions"] = taskItem.BasePermissions;
1719 row["everyonePermissions"] = taskItem.EveryonePermissions;
1720 row["groupPermissions"] = taskItem.GroupPermissions;
1721 row["flags"] = taskItem.Flags;
1722 }
1723
1724 /// <summary>
1725 ///
1726 /// </summary>
1727 /// <param name="row"></param>
1728 /// <param name="land"></param>
1729 /// <param name="regionUUID"></param>
1730 private static void fillLandRow(DataRow row, LandData land, UUID regionUUID)
1731 {
1732 row["UUID"] = land.GlobalID.ToString();
1733 row["RegionUUID"] = regionUUID.ToString();
1734 row["LocalLandID"] = land.LocalID;
1735
1736 // Bitmap is a byte[512]
1737 row["Bitmap"] = land.Bitmap;
1738
1739 row["Name"] = land.Name;
1740 row["Desc"] = land.Description;
1741 row["OwnerUUID"] = land.OwnerID.ToString();
1742 row["IsGroupOwned"] = land.IsGroupOwned;
1743 row["Area"] = land.Area;
1744 row["AuctionID"] = land.AuctionID; //Unemplemented
1745 row["Category"] = land.Category; //Enum OpenMetaverse.Parcel.ParcelCategory
1746 row["ClaimDate"] = land.ClaimDate;
1747 row["ClaimPrice"] = land.ClaimPrice;
1748 row["GroupUUID"] = land.GroupID.ToString();
1749 row["SalePrice"] = land.SalePrice;
1750 row["LandStatus"] = land.Status; //Enum. OpenMetaverse.Parcel.ParcelStatus
1751 row["LandFlags"] = land.Flags;
1752 row["LandingType"] = land.LandingType;
1753 row["MediaAutoScale"] = land.MediaAutoScale;
1754 row["MediaTextureUUID"] = land.MediaID.ToString();
1755 row["MediaURL"] = land.MediaURL;
1756 row["MusicURL"] = land.MusicURL;
1757 row["PassHours"] = land.PassHours;
1758 row["PassPrice"] = land.PassPrice;
1759 row["SnapshotUUID"] = land.SnapshotID.ToString();
1760 row["UserLocationX"] = land.UserLocation.X;
1761 row["UserLocationY"] = land.UserLocation.Y;
1762 row["UserLocationZ"] = land.UserLocation.Z;
1763 row["UserLookAtX"] = land.UserLookAt.X;
1764 row["UserLookAtY"] = land.UserLookAt.Y;
1765 row["UserLookAtZ"] = land.UserLookAt.Z;
1766 row["AuthbuyerID"] = land.AuthBuyerID.ToString();
1767 row["OtherCleanTime"] = land.OtherCleanTime;
1768 row["MediaType"] = land.MediaType;
1769 row["MediaDescription"] = land.MediaDescription;
1770 row["MediaSize"] = land.MediaWidth.ToString() + "," + land.MediaHeight.ToString();
1771 row["MediaLoop"] = land.MediaLoop.ToString();
1772 row["ObscureMusic"] = land.ObscureMusic.ToString();
1773 row["ObscureMedia"] = land.ObscureMedia.ToString();
1774 }
1775
1776 /// <summary>
1777 ///
1778 /// </summary>
1779 /// <param name="row"></param>
1780 /// <param name="entry"></param>
1781 /// <param name="parcelID"></param>
1782 private static void fillLandAccessRow(DataRow row, ParcelManager.ParcelAccessEntry entry, UUID parcelID)
1783 {
1784 row["LandUUID"] = parcelID.ToString();
1785 row["AccessUUID"] = entry.AgentID.ToString();
1786 row["Flags"] = entry.Flags;
1787 }
1788
1789 private static void fillRegionSettingsRow(DataRow row, RegionSettings settings)
1790 {
1791 row["regionUUID"] = settings.RegionUUID.ToString();
1792 row["block_terraform"] = settings.BlockTerraform;
1793 row["block_fly"] = settings.BlockFly;
1794 row["allow_damage"] = settings.AllowDamage;
1795 row["restrict_pushing"] = settings.RestrictPushing;
1796 row["allow_land_resell"] = settings.AllowLandResell;
1797 row["allow_land_join_divide"] = settings.AllowLandJoinDivide;
1798 row["block_show_in_search"] = settings.BlockShowInSearch;
1799 row["agent_limit"] = settings.AgentLimit;
1800 row["object_bonus"] = settings.ObjectBonus;
1801 row["maturity"] = settings.Maturity;
1802 row["disable_scripts"] = settings.DisableScripts;
1803 row["disable_collisions"] = settings.DisableCollisions;
1804 row["disable_physics"] = settings.DisablePhysics;
1805 row["terrain_texture_1"] = settings.TerrainTexture1.ToString();
1806 row["terrain_texture_2"] = settings.TerrainTexture2.ToString();
1807 row["terrain_texture_3"] = settings.TerrainTexture3.ToString();
1808 row["terrain_texture_4"] = settings.TerrainTexture4.ToString();
1809 row["elevation_1_nw"] = settings.Elevation1NW;
1810 row["elevation_2_nw"] = settings.Elevation2NW;
1811 row["elevation_1_ne"] = settings.Elevation1NE;
1812 row["elevation_2_ne"] = settings.Elevation2NE;
1813 row["elevation_1_se"] = settings.Elevation1SE;
1814 row["elevation_2_se"] = settings.Elevation2SE;
1815 row["elevation_1_sw"] = settings.Elevation1SW;
1816 row["elevation_2_sw"] = settings.Elevation2SW;
1817 row["water_height"] = settings.WaterHeight;
1818 row["terrain_raise_limit"] = settings.TerrainRaiseLimit;
1819 row["terrain_lower_limit"] = settings.TerrainLowerLimit;
1820 row["use_estate_sun"] = settings.UseEstateSun;
1821 row["Sandbox"] = settings.Sandbox; // database uses upper case S for sandbox
1822 row["sunvectorx"] = settings.SunVector.X;
1823 row["sunvectory"] = settings.SunVector.Y;
1824 row["sunvectorz"] = settings.SunVector.Z;
1825 row["fixed_sun"] = settings.FixedSun;
1826 row["sun_position"] = settings.SunPosition;
1827 row["covenant"] = settings.Covenant.ToString();
1828 row["map_tile_ID"] = settings.TerrainImageID.ToString();
1829 }
1830
1831 /// <summary>
1832 ///
1833 /// </summary>
1834 /// <param name="row"></param>
1835 /// <returns></returns>
1836 private PrimitiveBaseShape buildShape(DataRow row)
1837 {
1838 PrimitiveBaseShape s = new PrimitiveBaseShape();
1839 s.Scale = new Vector3(
1840 Convert.ToSingle(row["ScaleX"]),
1841 Convert.ToSingle(row["ScaleY"]),
1842 Convert.ToSingle(row["ScaleZ"])
1843 );
1844 // paths
1845 s.PCode = Convert.ToByte(row["PCode"]);
1846 s.PathBegin = Convert.ToUInt16(row["PathBegin"]);
1847 s.PathEnd = Convert.ToUInt16(row["PathEnd"]);
1848 s.PathScaleX = Convert.ToByte(row["PathScaleX"]);
1849 s.PathScaleY = Convert.ToByte(row["PathScaleY"]);
1850 s.PathShearX = Convert.ToByte(row["PathShearX"]);
1851 s.PathShearY = Convert.ToByte(row["PathShearY"]);
1852 s.PathSkew = Convert.ToSByte(row["PathSkew"]);
1853 s.PathCurve = Convert.ToByte(row["PathCurve"]);
1854 s.PathRadiusOffset = Convert.ToSByte(row["PathRadiusOffset"]);
1855 s.PathRevolutions = Convert.ToByte(row["PathRevolutions"]);
1856 s.PathTaperX = Convert.ToSByte(row["PathTaperX"]);
1857 s.PathTaperY = Convert.ToSByte(row["PathTaperY"]);
1858 s.PathTwist = Convert.ToSByte(row["PathTwist"]);
1859 s.PathTwistBegin = Convert.ToSByte(row["PathTwistBegin"]);
1860 // profile
1861 s.ProfileBegin = Convert.ToUInt16(row["ProfileBegin"]);
1862 s.ProfileEnd = Convert.ToUInt16(row["ProfileEnd"]);
1863 s.ProfileCurve = Convert.ToByte(row["ProfileCurve"]);
1864 s.ProfileHollow = Convert.ToUInt16(row["ProfileHollow"]);
1865 s.State = Convert.ToByte(row["State"]);
1866
1867 byte[] textureEntry = (byte[])row["Texture"];
1868 s.TextureEntry = textureEntry;
1869
1870 s.ExtraParams = (byte[]) row["ExtraParams"];
1871
1872 if (!(row["Media"] is System.DBNull))
1873 s.Media = PrimitiveBaseShape.MediaList.FromXml((string)row["Media"]);
1874
1875 return s;
1876 }
1877
1878 /// <summary>
1879 ///
1880 /// </summary>
1881 /// <param name="row"></param>
1882 /// <param name="prim"></param>
1883 private static void fillShapeRow(DataRow row, SceneObjectPart prim)
1884 {
1885 PrimitiveBaseShape s = prim.Shape;
1886 row["UUID"] = prim.UUID.ToString();
1887 // shape is an enum
1888 row["Shape"] = 0;
1889 // vectors
1890 row["ScaleX"] = s.Scale.X;
1891 row["ScaleY"] = s.Scale.Y;
1892 row["ScaleZ"] = s.Scale.Z;
1893 // paths
1894 row["PCode"] = s.PCode;
1895 row["PathBegin"] = s.PathBegin;
1896 row["PathEnd"] = s.PathEnd;
1897 row["PathScaleX"] = s.PathScaleX;
1898 row["PathScaleY"] = s.PathScaleY;
1899 row["PathShearX"] = s.PathShearX;
1900 row["PathShearY"] = s.PathShearY;
1901 row["PathSkew"] = s.PathSkew;
1902 row["PathCurve"] = s.PathCurve;
1903 row["PathRadiusOffset"] = s.PathRadiusOffset;
1904 row["PathRevolutions"] = s.PathRevolutions;
1905 row["PathTaperX"] = s.PathTaperX;
1906 row["PathTaperY"] = s.PathTaperY;
1907 row["PathTwist"] = s.PathTwist;
1908 row["PathTwistBegin"] = s.PathTwistBegin;
1909 // profile
1910 row["ProfileBegin"] = s.ProfileBegin;
1911 row["ProfileEnd"] = s.ProfileEnd;
1912 row["ProfileCurve"] = s.ProfileCurve;
1913 row["ProfileHollow"] = s.ProfileHollow;
1914 row["State"] = s.State;
1915
1916 row["Texture"] = s.TextureEntry;
1917 row["ExtraParams"] = s.ExtraParams;
1918
1919 if (s.Media != null)
1920 row["Media"] = s.Media.ToXml();
1921 }
1922
1923 /// <summary>
1924 /// Persistently store a prim.
1925 /// </summary>
1926 /// <param name="prim"></param>
1927 /// <param name="sceneGroupID"></param>
1928 /// <param name="regionUUID"></param>
1929 private void addPrim(SceneObjectPart prim, UUID sceneGroupID, UUID regionUUID)
1930 {
1931 DataTable prims = ds.Tables["prims"];
1932 DataTable shapes = ds.Tables["primshapes"];
1933
1934 DataRow primRow = prims.Rows.Find(prim.UUID.ToString());
1935 if (primRow == null)
1936 {
1937 primRow = prims.NewRow();
1938 fillPrimRow(primRow, prim, sceneGroupID, regionUUID);
1939 prims.Rows.Add(primRow);
1940 }
1941 else
1942 {
1943 fillPrimRow(primRow, prim, sceneGroupID, regionUUID);
1944 }
1945
1946 DataRow shapeRow = shapes.Rows.Find(prim.UUID.ToString());
1947 if (shapeRow == null)
1948 {
1949 shapeRow = shapes.NewRow();
1950 fillShapeRow(shapeRow, prim);
1951 shapes.Rows.Add(shapeRow);
1952 }
1953 else
1954 {
1955 fillShapeRow(shapeRow, prim);
1956 }
1957 }
1958
1959 /// <summary>
1960 /// </summary>
1961 /// <param name="primID"></param>
1962 /// <param name="items"></param>
1963 public void StorePrimInventory(UUID primID, ICollection<TaskInventoryItem> items)
1964 {
1965// m_log.DebugFormat("[SQLITE REGION DB]: Entered StorePrimInventory with prim ID {0}", primID);
1966
1967 DataTable dbItems = ds.Tables["primitems"];
1968
1969 // For now, we're just going to crudely remove all the previous inventory items
1970 // no matter whether they have changed or not, and replace them with the current set.
1971 lock (ds)
1972 {
1973 RemoveItems(primID);
1974
1975 // repalce with current inventory details
1976 foreach (TaskInventoryItem newItem in items)
1977 {
1978// m_log.InfoFormat(
1979// "[DATASTORE]: ",
1980// "Adding item {0}, {1} to prim ID {2}",
1981// newItem.Name, newItem.ItemID, newItem.ParentPartID);
1982
1983 DataRow newItemRow = dbItems.NewRow();
1984 fillItemRow(newItemRow, newItem);
1985 dbItems.Rows.Add(newItemRow);
1986 }
1987 }
1988
1989 Commit();
1990 }
1991
1992 /***********************************************************************
1993 *
1994 * SQL Statement Creation Functions
1995 *
1996 * These functions create SQL statements for update, insert, and create.
1997 * They can probably be factored later to have a db independant
1998 * portion and a db specific portion
1999 *
2000 **********************************************************************/
2001
2002 /// <summary>
2003 /// Create an insert command
2004 /// </summary>
2005 /// <param name="table">table name</param>
2006 /// <param name="dt">data table</param>
2007 /// <returns>the created command</returns>
2008 /// <remarks>
2009 /// This is subtle enough to deserve some commentary.
2010 /// Instead of doing *lots* and *lots of hardcoded strings
2011 /// for database definitions we'll use the fact that
2012 /// realistically all insert statements look like "insert
2013 /// into A(b, c) values(:b, :c) on the parameterized query
2014 /// front. If we just have a list of b, c, etc... we can
2015 /// generate these strings instead of typing them out.
2016 /// </remarks>
2017 private static SqliteCommand createInsertCommand(string table, DataTable dt)
2018 {
2019 string[] cols = new string[dt.Columns.Count];
2020 for (int i = 0; i < dt.Columns.Count; i++)
2021 {
2022 DataColumn col = dt.Columns[i];
2023 cols[i] = col.ColumnName;
2024 }
2025
2026 string sql = "insert into " + table + "(";
2027 sql += String.Join(", ", cols);
2028 // important, the first ':' needs to be here, the rest get added in the join
2029 sql += ") values (:";
2030 sql += String.Join(", :", cols);
2031 sql += ")";
2032 //m_log.DebugFormat("[SQLITE]: Created insert command {0}", sql);
2033 SqliteCommand cmd = new SqliteCommand(sql);
2034
2035 // this provides the binding for all our parameters, so
2036 // much less code than it used to be
2037 foreach (DataColumn col in dt.Columns)
2038 {
2039 cmd.Parameters.Add(createSqliteParameter(col.ColumnName, col.DataType));
2040 }
2041 return cmd;
2042 }
2043
2044
2045 /// <summary>
2046 /// create an update command
2047 /// </summary>
2048 /// <param name="table">table name</param>
2049 /// <param name="pk"></param>
2050 /// <param name="dt"></param>
2051 /// <returns>the created command</returns>
2052 private static SqliteCommand createUpdateCommand(string table, string pk, DataTable dt)
2053 {
2054 string sql = "update " + table + " set ";
2055 string subsql = String.Empty;
2056 foreach (DataColumn col in dt.Columns)
2057 {
2058 if (subsql.Length > 0)
2059 {
2060 // a map function would rock so much here
2061 subsql += ", ";
2062 }
2063 subsql += col.ColumnName + "= :" + col.ColumnName;
2064 }
2065 sql += subsql;
2066 sql += " where " + pk;
2067 SqliteCommand cmd = new SqliteCommand(sql);
2068
2069 // this provides the binding for all our parameters, so
2070 // much less code than it used to be
2071
2072 foreach (DataColumn col in dt.Columns)
2073 {
2074 cmd.Parameters.Add(createSqliteParameter(col.ColumnName, col.DataType));
2075 }
2076 return cmd;
2077 }
2078
2079 /// <summary>
2080 /// create an update command
2081 /// </summary>
2082 /// <param name="table">table name</param>
2083 /// <param name="pk"></param>
2084 /// <param name="dt"></param>
2085 /// <returns>the created command</returns>
2086 private static SqliteCommand createUpdateCommand(string table, string pk1, string pk2, DataTable dt)
2087 {
2088 string sql = "update " + table + " set ";
2089 string subsql = String.Empty;
2090 foreach (DataColumn col in dt.Columns)
2091 {
2092 if (subsql.Length > 0)
2093 {
2094 // a map function would rock so much here
2095 subsql += ", ";
2096 }
2097 subsql += col.ColumnName + "= :" + col.ColumnName;
2098 }
2099 sql += subsql;
2100 sql += " where " + pk1 + " and " + pk2;
2101 SqliteCommand cmd = new SqliteCommand(sql);
2102
2103 // this provides the binding for all our parameters, so
2104 // much less code than it used to be
2105
2106 foreach (DataColumn col in dt.Columns)
2107 {
2108 cmd.Parameters.Add(createSqliteParameter(col.ColumnName, col.DataType));
2109 }
2110 return cmd;
2111 }
2112
2113 /// <summary>
2114 ///
2115 /// </summary>
2116 /// <param name="dt">Data Table</param>
2117 /// <returns></returns>
2118 // private static string defineTable(DataTable dt)
2119 // {
2120 // string sql = "create table " + dt.TableName + "(";
2121 // string subsql = String.Empty;
2122 // foreach (DataColumn col in dt.Columns)
2123 // {
2124 // if (subsql.Length > 0)
2125 // {
2126 // // a map function would rock so much here
2127 // subsql += ",\n";
2128 // }
2129 // subsql += col.ColumnName + " " + sqliteType(col.DataType);
2130 // if (dt.PrimaryKey.Length > 0 && col == dt.PrimaryKey[0])
2131 // {
2132 // subsql += " primary key";
2133 // }
2134 // }
2135 // sql += subsql;
2136 // sql += ")";
2137 // return sql;
2138 // }
2139
2140 /***********************************************************************
2141 *
2142 * Database Binding functions
2143 *
2144 * These will be db specific due to typing, and minor differences
2145 * in databases.
2146 *
2147 **********************************************************************/
2148
2149 ///<summary>
2150 /// This is a convenience function that collapses 5 repetitive
2151 /// lines for defining SqliteParameters to 2 parameters:
2152 /// column name and database type.
2153 ///
2154 /// It assumes certain conventions like :param as the param
2155 /// name to replace in parametrized queries, and that source
2156 /// version is always current version, both of which are fine
2157 /// for us.
2158 ///</summary>
2159 ///<returns>a built sqlite parameter</returns>
2160 private static SqliteParameter createSqliteParameter(string name, Type type)
2161 {
2162 SqliteParameter param = new SqliteParameter();
2163 param.ParameterName = ":" + name;
2164 param.DbType = dbtypeFromType(type);
2165 param.SourceColumn = name;
2166 param.SourceVersion = DataRowVersion.Current;
2167 return param;
2168 }
2169
2170 /// <summary>
2171 ///
2172 /// </summary>
2173 /// <param name="da"></param>
2174 /// <param name="conn"></param>
2175 private void setupPrimCommands(SqliteDataAdapter da, SqliteConnection conn)
2176 {
2177 da.InsertCommand = createInsertCommand("prims", ds.Tables["prims"]);
2178 da.InsertCommand.Connection = conn;
2179
2180 da.UpdateCommand = createUpdateCommand("prims", "UUID=:UUID", ds.Tables["prims"]);
2181 da.UpdateCommand.Connection = conn;
2182
2183 SqliteCommand delete = new SqliteCommand("delete from prims where UUID = :UUID");
2184 delete.Parameters.Add(createSqliteParameter("UUID", typeof (String)));
2185 delete.Connection = conn;
2186 da.DeleteCommand = delete;
2187 }
2188
2189 /// <summary>
2190 ///
2191 /// </summary>
2192 /// <param name="da"></param>
2193 /// <param name="conn"></param>
2194 private void setupItemsCommands(SqliteDataAdapter da, SqliteConnection conn)
2195 {
2196 da.InsertCommand = createInsertCommand("primitems", ds.Tables["primitems"]);
2197 da.InsertCommand.Connection = conn;
2198
2199 da.UpdateCommand = createUpdateCommand("primitems", "itemID = :itemID", ds.Tables["primitems"]);
2200 da.UpdateCommand.Connection = conn;
2201
2202 SqliteCommand delete = new SqliteCommand("delete from primitems where itemID = :itemID");
2203 delete.Parameters.Add(createSqliteParameter("itemID", typeof (String)));
2204 delete.Connection = conn;
2205 da.DeleteCommand = delete;
2206 }
2207
2208 /// <summary>
2209 ///
2210 /// </summary>
2211 /// <param name="da"></param>
2212 /// <param name="conn"></param>
2213 private void setupTerrainCommands(SqliteDataAdapter da, SqliteConnection conn)
2214 {
2215 da.InsertCommand = createInsertCommand("terrain", ds.Tables["terrain"]);
2216 da.InsertCommand.Connection = conn;
2217 }
2218
2219 /// <summary>
2220 ///
2221 /// </summary>
2222 /// <param name="da"></param>
2223 /// <param name="conn"></param>
2224 private void setupLandCommands(SqliteDataAdapter da, SqliteConnection conn)
2225 {
2226 da.InsertCommand = createInsertCommand("land", ds.Tables["land"]);
2227 da.InsertCommand.Connection = conn;
2228
2229 da.UpdateCommand = createUpdateCommand("land", "UUID=:UUID", ds.Tables["land"]);
2230 da.UpdateCommand.Connection = conn;
2231
2232 SqliteCommand delete = new SqliteCommand("delete from land where UUID=:UUID");
2233 delete.Parameters.Add(createSqliteParameter("UUID", typeof(String)));
2234 da.DeleteCommand = delete;
2235 da.DeleteCommand.Connection = conn;
2236 }
2237
2238 /// <summary>
2239 ///
2240 /// </summary>
2241 /// <param name="da"></param>
2242 /// <param name="conn"></param>
2243 private void setupLandAccessCommands(SqliteDataAdapter da, SqliteConnection conn)
2244 {
2245 da.InsertCommand = createInsertCommand("landaccesslist", ds.Tables["landaccesslist"]);
2246 da.InsertCommand.Connection = conn;
2247
2248 da.UpdateCommand = createUpdateCommand("landaccesslist", "LandUUID=:landUUID", "AccessUUID=:AccessUUID", ds.Tables["landaccesslist"]);
2249 da.UpdateCommand.Connection = conn;
2250
2251 SqliteCommand delete = new SqliteCommand("delete from landaccesslist where LandUUID= :LandUUID and AccessUUID= :AccessUUID");
2252 delete.Parameters.Add(createSqliteParameter("LandUUID", typeof(String)));
2253 delete.Parameters.Add(createSqliteParameter("AccessUUID", typeof(String)));
2254 da.DeleteCommand = delete;
2255 da.DeleteCommand.Connection = conn;
2256 }
2257
2258 private void setupRegionSettingsCommands(SqliteDataAdapter da, SqliteConnection conn)
2259 {
2260 da.InsertCommand = createInsertCommand("regionsettings", ds.Tables["regionsettings"]);
2261 da.InsertCommand.Connection = conn;
2262 da.UpdateCommand = createUpdateCommand("regionsettings", "regionUUID=:regionUUID", ds.Tables["regionsettings"]);
2263 da.UpdateCommand.Connection = conn;
2264 }
2265
2266 /// <summary>
2267 ///
2268 /// </summary>
2269 /// <param name="da"></param>
2270 /// <param name="conn"></param>
2271 private void setupShapeCommands(SqliteDataAdapter da, SqliteConnection conn)
2272 {
2273 da.InsertCommand = createInsertCommand("primshapes", ds.Tables["primshapes"]);
2274 da.InsertCommand.Connection = conn;
2275
2276 da.UpdateCommand = createUpdateCommand("primshapes", "UUID=:UUID", ds.Tables["primshapes"]);
2277 da.UpdateCommand.Connection = conn;
2278
2279 SqliteCommand delete = new SqliteCommand("delete from primshapes where UUID = :UUID");
2280 delete.Parameters.Add(createSqliteParameter("UUID", typeof (String)));
2281 delete.Connection = conn;
2282 da.DeleteCommand = delete;
2283 }
2284
2285 /***********************************************************************
2286 *
2287 * Type conversion functions
2288 *
2289 **********************************************************************/
2290
2291 /// <summary>
2292 /// Type conversion function
2293 /// </summary>
2294 /// <param name="type"></param>
2295 /// <returns></returns>
2296 private static DbType dbtypeFromType(Type type)
2297 {
2298 if (type == typeof (String))
2299 {
2300 return DbType.String;
2301 }
2302 else if (type == typeof (Int32))
2303 {
2304 return DbType.Int32;
2305 }
2306 else if (type == typeof (Double))
2307 {
2308 return DbType.Double;
2309 }
2310 else if (type == typeof (Byte))
2311 {
2312 return DbType.Byte;
2313 }
2314 else if (type == typeof (Double))
2315 {
2316 return DbType.Double;
2317 }
2318 else if (type == typeof (Byte[]))
2319 {
2320 return DbType.Binary;
2321 }
2322 else
2323 {
2324 return DbType.String;
2325 }
2326 }
2327
2328 static void PrintDataSet(DataSet ds)
2329 {
2330 // Print out any name and extended properties.
2331 Console.WriteLine("DataSet is named: {0}", ds.DataSetName);
2332 foreach (System.Collections.DictionaryEntry de in ds.ExtendedProperties)
2333 {
2334 Console.WriteLine("Key = {0}, Value = {1}", de.Key, de.Value);
2335 }
2336 Console.WriteLine();
2337 foreach (DataTable dt in ds.Tables)
2338 {
2339 Console.WriteLine("=> {0} Table:", dt.TableName);
2340 // Print out the column names.
2341 for (int curCol = 0; curCol < dt.Columns.Count; curCol++)
2342 {
2343 Console.Write(dt.Columns[curCol].ColumnName + "\t");
2344 }
2345 Console.WriteLine("\n----------------------------------");
2346 // Print the DataTable.
2347 for (int curRow = 0; curRow < dt.Rows.Count; curRow++)
2348 {
2349 for (int curCol = 0; curCol < dt.Columns.Count; curCol++)
2350 {
2351 Console.Write(dt.Rows[curRow][curCol].ToString() + "\t");
2352 }
2353 Console.WriteLine();
2354 }
2355 }
2356 }
2357
2358 }
2359}