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