aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Storage
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Storage')
-rw-r--r--OpenSim/Region/Storage/OpenSim.DataStore.DB4o/DB4oDataStore.cs132
-rw-r--r--OpenSim/Region/Storage/OpenSim.DataStore.DB4o/Properties/AssemblyInfo.cs62
-rw-r--r--OpenSim/Region/Storage/OpenSim.DataStore.MSSQL/MSSQLDataStore.cs1094
3 files changed, 0 insertions, 1288 deletions
diff --git a/OpenSim/Region/Storage/OpenSim.DataStore.DB4o/DB4oDataStore.cs b/OpenSim/Region/Storage/OpenSim.DataStore.DB4o/DB4oDataStore.cs
deleted file mode 100644
index 5380e7b..0000000
--- a/OpenSim/Region/Storage/OpenSim.DataStore.DB4o/DB4oDataStore.cs
+++ /dev/null
@@ -1,132 +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 OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Text;
31
32using OpenSim.Region.Environment.Scenes;
33using OpenSim.Region.Environment.LandManagement;
34using OpenSim.Region.Environment;
35using OpenSim.Region.Interfaces;
36using OpenSim.Framework.Console;
37using libsecondlife;
38
39using Db4objects.Db4o;
40using Db4objects.Db4o.Query;
41
42namespace OpenSim.DataStore.DB4oStorage
43{
44 public class SceneObjectQuery : Predicate
45 {
46 private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
47
48 private LLUUID globalIDSearch;
49
50 public SceneObjectQuery(LLUUID find)
51 {
52 globalIDSearch = find;
53 }
54
55 public bool Match(SceneObjectGroup obj)
56 {
57 return obj.UUID == globalIDSearch;
58 }
59 }
60
61 public class DB4oDataStore : IRegionDataStore
62 {
63 private IObjectContainer db;
64
65 public void Initialise(string dbfile, string dbname)
66 {
67 m_log.Info("[DATASTORE]: DB4O - Opening " + dbfile);
68 db = Db4oFactory.OpenFile(dbfile);
69 }
70
71 public void StoreObject(SceneObjectGroup obj, LLUUID regionUUID)
72 {
73 db.Set(obj);
74 }
75
76 public void RemoveObject(LLUUID obj, LLUUID regionUUID)
77 {
78 IObjectSet result = db.Query(new SceneObjectQuery(obj));
79 if (result.Count > 0)
80 {
81 SceneObjectGroup item = (SceneObjectGroup)result.Next();
82 db.Delete(item);
83 }
84 }
85
86 public List<SceneObjectGroup> LoadObjects(LLUUID regionUUID)
87 {
88 IObjectSet result = db.Get(typeof(SceneObjectGroup));
89 List<SceneObjectGroup> retvals = new List<SceneObjectGroup>();
90
91 m_log.Info("[DATASTORE]: DB4O - LoadObjects found " + result.Count.ToString() + " objects");
92
93 foreach (Object obj in result)
94 {
95 retvals.Add((SceneObjectGroup)obj);
96 }
97
98 return retvals;
99 }
100
101 public void StoreTerrain(double[,] ter)
102 {
103 }
104
105 public double[,] LoadTerrain()
106 {
107 return null;
108 }
109
110 public void RemoveLandObject(uint id)
111 {
112 }
113
114 public void StoreParcel(Land parcel)
115 {
116 }
117
118 public List<Land> LoadLandObjects()
119 {
120 return new List<Land>();
121 }
122
123 public void Shutdown()
124 {
125 if (db != null)
126 {
127 db.Commit();
128 db.Close();
129 }
130 }
131 }
132}
diff --git a/OpenSim/Region/Storage/OpenSim.DataStore.DB4o/Properties/AssemblyInfo.cs b/OpenSim/Region/Storage/OpenSim.DataStore.DB4o/Properties/AssemblyInfo.cs
deleted file mode 100644
index 0416779..0000000
--- a/OpenSim/Region/Storage/OpenSim.DataStore.DB4o/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,62 +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 OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System.Reflection;
29using System.Runtime.CompilerServices;
30using System.Runtime.InteropServices;
31
32// General information about an assembly is controlled through the following
33// set of attributes. Change these attribute values to modify the information
34// associated with an assembly.
35[assembly: AssemblyTitle("OpenSim.DataStore.DB4o")]
36[assembly: AssemblyDescription("")]
37[assembly: AssemblyConfiguration("")]
38[assembly: AssemblyCompany("")]
39[assembly: AssemblyProduct("OpenSim.DataStore.DB4o")]
40[assembly: AssemblyCopyright("Copyright (c) 2007")]
41[assembly: AssemblyTrademark("")]
42[assembly: AssemblyCulture("")]
43
44// Setting ComVisible to false makes the types in this assembly not visible
45// to COM components. If you need to access a type in this assembly from
46// COM, set the ComVisible attribute to true on that type.
47[assembly: ComVisible(false)]
48
49// The following GUID is for the ID of the typelib if this project is exposed to COM
50[assembly: Guid("7a12de8b-fdd1-48f5-89a9-8dc2dafbeebc")]
51
52// Version information for an assembly consists of the following four values:
53//
54// Major Version
55// Minor Version
56// Build Number
57// Revision
58//
59// You can specify all the values or you can default the Revision and Build Numbers
60// by using the '*' as shown below:
61[assembly: AssemblyVersion("1.0.0.0")]
62[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Region/Storage/OpenSim.DataStore.MSSQL/MSSQLDataStore.cs b/OpenSim/Region/Storage/OpenSim.DataStore.MSSQL/MSSQLDataStore.cs
deleted file mode 100644
index edbb1b7..0000000
--- a/OpenSim/Region/Storage/OpenSim.DataStore.MSSQL/MSSQLDataStore.cs
+++ /dev/null
@@ -1,1094 +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 OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Data;
31using System.Data.SqlClient;
32using System.IO;
33using System.Reflection;
34using libsecondlife;
35using log4net;
36using OpenSim.Data;
37using OpenSim.Framework;
38using OpenSim.Region.Environment.Interfaces;
39using OpenSim.Region.Environment.Scenes;
40
41namespace OpenSim.DataStore.MSSQL
42{
43 public class MSSQLDataStore : IRegionDataStore
44 {
45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46
47 private const string primSelect = "select * from prims";
48 private const string shapeSelect = "select * from primshapes";
49 private const string terrainSelect = "select * from terrain";
50
51 private DataSet ds;
52 private SqlDataAdapter primDa;
53 private SqlDataAdapter shapeDa;
54 private SqlDataAdapter terrainDa;
55
56 // see IRegionDataStore
57 public void Initialise(string dbfile, bool persistPrimInventories)
58 {
59 IniFile GridDataMySqlFile = new IniFile("mssql_connection.ini");
60 string settingDataSource = GridDataMySqlFile.ParseFileReadValue("data_source");
61 string settingInitialCatalog = GridDataMySqlFile.ParseFileReadValue("initial_catalog");
62 string settingPersistSecurityInfo = GridDataMySqlFile.ParseFileReadValue("persist_security_info");
63 string settingUserId = GridDataMySqlFile.ParseFileReadValue("user_id");
64 string settingPassword = GridDataMySqlFile.ParseFileReadValue("password");
65
66 string connectionString = "Data Source=" + settingDataSource + ";Initial Catalog=" + settingInitialCatalog +
67 ";Persist Security Info=" + settingPersistSecurityInfo + ";User ID=" +
68 settingUserId + ";Password=" + settingPassword + ";";
69
70 ds = new DataSet();
71
72 m_log.Info("[DATASTORE]: MSSQL - connecting: " + settingInitialCatalog);
73 SqlConnection conn = new SqlConnection(connectionString);
74 SqlCommand primSelectCmd = new SqlCommand(primSelect, conn);
75 primDa = new SqlDataAdapter(primSelectCmd);
76 // SqlCommandBuilder primCb = new SqlCommandBuilder(primDa);
77
78 SqlCommand shapeSelectCmd = new SqlCommand(shapeSelect, conn);
79 shapeDa = new SqlDataAdapter(shapeSelectCmd);
80 // SqlCommandBuilder shapeCb = new SqlCommandBuilder(shapeDa);
81
82 SqlCommand terrainSelectCmd = new SqlCommand(terrainSelect, conn);
83 terrainDa = new SqlDataAdapter(terrainSelectCmd);
84
85
86 // We fill the data set, now we've got copies in memory for the information
87 // TODO: see if the linkage actually holds.
88 // primDa.FillSchema(ds, SchemaType.Source, "PrimSchema");
89 TestTables(conn);
90
91 lock (ds)
92 {
93 ds.Tables.Add(createPrimTable());
94 setupPrimCommands(primDa, conn);
95 primDa.Fill(ds.Tables["prims"]);
96
97 ds.Tables.Add(createShapeTable());
98 setupShapeCommands(shapeDa, conn);
99
100 ds.Tables.Add(createTerrainTable());
101 setupTerrainCommands(terrainDa, conn);
102
103 // WORKAROUND: This is a work around for Sql on
104 // windows, which gets really unhappy with blob columns
105 // that have no sample data in them. At some point we
106 // need to actually find a proper way to handle this.
107 try
108 {
109 shapeDa.Fill(ds.Tables["primshapes"]);
110 }
111 catch (Exception)
112 {
113 m_log.Info("[DATASTORE]: Caught fill error on primshapes table");
114 }
115 try
116 {
117 terrainDa.Fill(ds.Tables["terrain"]);
118 }
119 catch (Exception)
120 {
121 m_log.Info("[DATASTORE]: Caught fill error on terrain table");
122 }
123 return;
124 }
125 }
126
127 public void StoreRegionSettings(RegionSettings rs)
128 {
129 }
130
131 public RegionSettings LoadRegionSettings(LLUUID regionUUID)
132 {
133 return null;
134 }
135
136 public void StoreObject(SceneObjectGroup obj, LLUUID regionUUID)
137 {
138 lock (ds)
139 {
140 foreach (SceneObjectPart prim in obj.Children.Values)
141 {
142 //m_log.Info("[DATASTORE]: Adding obj: " + obj.UUID + " to region: " + regionUUID);
143 addPrim(prim, obj.UUID, regionUUID);
144 }
145 }
146
147 Commit();
148 // m_log.Info("Dump of prims:", ds.GetXml());
149 }
150
151 public void RemoveObject(LLUUID obj, LLUUID regionUUID)
152 {
153 m_log.InfoFormat("[DATASTORE]: Removing obj: {0} from region: {1}", obj.UUID, regionUUID);
154
155 DataTable prims = ds.Tables["prims"];
156 DataTable shapes = ds.Tables["primshapes"];
157
158 string selectExp = "SceneGroupID = '" + obj.ToString() + "'";
159 lock (ds)
160 {
161 DataRow[] primRows = prims.Select(selectExp);
162 foreach (DataRow row in primRows)
163 {
164 LLUUID uuid = new LLUUID((string) row["UUID"]);
165 DataRow shapeRow = shapes.Rows.Find(uuid);
166 if (shapeRow != null)
167 {
168 shapeRow.Delete();
169 }
170 row.Delete();
171 }
172 }
173
174 Commit();
175 }
176
177 public List<SceneObjectGroup> LoadObjects(LLUUID regionUUID)
178 {
179 Dictionary<LLUUID, SceneObjectGroup> createdObjects = new Dictionary<LLUUID, SceneObjectGroup>();
180
181 List<SceneObjectGroup> retvals = new List<SceneObjectGroup>();
182
183 DataTable prims = ds.Tables["prims"];
184 DataTable shapes = ds.Tables["primshapes"];
185
186 string byRegion = "RegionUUID = '" + regionUUID.ToString() + "'";
187 string orderByParent = "ParentID ASC";
188
189 lock (ds)
190 {
191 DataRow[] primsForRegion = prims.Select(byRegion, orderByParent);
192 m_log.Info("[DATASTORE]: " +
193 "Loaded " + primsForRegion.Length + " prims for region: " + regionUUID);
194
195 foreach (DataRow primRow in primsForRegion)
196 {
197 try
198 {
199 string uuid = (string) primRow["UUID"];
200 string objID = (string) primRow["SceneGroupID"];
201 if (uuid == objID) //is new SceneObjectGroup ?
202 {
203 SceneObjectGroup group = new SceneObjectGroup();
204 SceneObjectPart prim = buildPrim(primRow);
205 DataRow shapeRow = shapes.Rows.Find(prim.UUID);
206 if (shapeRow != null)
207 {
208 prim.Shape = buildShape(shapeRow);
209 }
210 else
211 {
212 m_log.Info(
213 "No shape found for prim in storage, so setting default box shape");
214 prim.Shape = PrimitiveBaseShape.Default;
215 }
216 group.AddPart(prim);
217 group.RootPart = prim;
218
219 createdObjects.Add(group.UUID, group);
220 retvals.Add(group);
221 }
222 else
223 {
224 SceneObjectPart prim = buildPrim(primRow);
225 DataRow shapeRow = shapes.Rows.Find(prim.UUID);
226 if (shapeRow != null)
227 {
228 prim.Shape = buildShape(shapeRow);
229 }
230 else
231 {
232 m_log.Info(
233 "No shape found for prim in storage, so setting default box shape");
234 prim.Shape = PrimitiveBaseShape.Default;
235 }
236 createdObjects[new LLUUID(objID)].AddPart(prim);
237 }
238 }
239 catch (Exception e)
240 {
241 m_log.Error("[DATASTORE]: Failed create prim object, exception and data follows");
242 m_log.Info("[DATASTORE]: " + e.ToString());
243 foreach (DataColumn col in prims.Columns)
244 {
245 m_log.Info("[DATASTORE]: Col: " + col.ColumnName + " => " + primRow[col]);
246 }
247 }
248 }
249 }
250 return retvals;
251 }
252
253
254 public void StoreTerrain(double[,] ter, LLUUID regionID)
255 {
256 int revision = Util.UnixTimeSinceEpoch();
257
258 m_log.Info("[DATASTORE]: Storing terrain revision r" + revision.ToString());
259
260 DataTable terrain = ds.Tables["terrain"];
261 lock (ds)
262 {
263 DataRow newrow = terrain.NewRow();
264 fillTerrainRow(newrow, regionID, revision, ter);
265 terrain.Rows.Add(newrow);
266
267 Commit();
268 }
269 }
270
271 public double[,] LoadTerrain(LLUUID regionID)
272 {
273 double[,] terret = new double[256,256];
274 terret.Initialize();
275
276 DataTable terrain = ds.Tables["terrain"];
277
278 lock (ds)
279 {
280 DataRow[] rows = terrain.Select("RegionUUID = '" + regionID.ToString() + "'", "Revision DESC");
281
282 int rev = 0;
283
284 if (rows.Length > 0)
285 {
286 DataRow row = rows[0];
287
288 byte[] heightmap = (byte[]) row["Heightfield"];
289 for (int x = 0; x < 256; x++)
290 {
291 for (int y = 0; y < 256; y++)
292 {
293 terret[x, y] = BitConverter.ToDouble(heightmap, ((x*256) + y)*8);
294 }
295 }
296
297 rev = (int) row["Revision"];
298 }
299 else
300 {
301 m_log.Info("[DATASTORE]: No terrain found for region");
302 return null;
303 }
304
305
306 m_log.Info("[DATASTORE]: Loaded terrain revision r" + rev.ToString());
307 }
308
309 return terret;
310 }
311
312 public void RemoveLandObject(LLUUID globalID)
313 {
314 }
315
316 public void StoreLandObject(ILandObject parcel)
317 {
318 }
319
320 public List<LandData> LoadLandObjects(LLUUID regionUUID)
321 {
322 return new List<LandData>();
323 }
324
325 public void Commit()
326 {
327 lock (ds)
328 {
329 primDa.Update(ds, "prims");
330 shapeDa.Update(ds, "primshapes");
331 terrainDa.Update(ds, "terrain");
332 ds.AcceptChanges();
333 }
334 }
335
336 public void Shutdown()
337 {
338 Commit();
339 }
340
341 /***********************************************************************
342 *
343 * Database Definition Functions
344 *
345 * This should be db agnostic as we define them in ADO.NET terms
346 *
347 **********************************************************************/
348
349 private static void createCol(DataTable dt, string name, Type type)
350 {
351 DataColumn col = new DataColumn(name, type);
352 dt.Columns.Add(col);
353 }
354
355 private static DataTable createTerrainTable()
356 {
357 DataTable terrain = new DataTable("terrain");
358
359 createCol(terrain, "RegionUUID", typeof (String));
360 createCol(terrain, "Revision", typeof (Int32));
361 createCol(terrain, "Heightfield", typeof (Byte[]));
362
363 return terrain;
364 }
365
366 private static DataTable createPrimTable()
367 {
368 DataTable prims = new DataTable("prims");
369
370 createCol(prims, "UUID", typeof (String));
371 createCol(prims, "RegionUUID", typeof (String));
372 createCol(prims, "ParentID", typeof (Int32));
373 createCol(prims, "CreationDate", typeof (Int32));
374 createCol(prims, "Name", typeof (String));
375 createCol(prims, "SceneGroupID", typeof (String));
376 // various text fields
377 createCol(prims, "Text", typeof (String));
378 createCol(prims, "Description", typeof (String));
379 createCol(prims, "SitName", typeof (String));
380 createCol(prims, "TouchName", typeof (String));
381 // permissions
382 createCol(prims, "ObjectFlags", typeof (Int32));
383 createCol(prims, "CreatorID", typeof (String));
384 createCol(prims, "OwnerID", typeof (String));
385 createCol(prims, "GroupID", typeof (String));
386 createCol(prims, "LastOwnerID", typeof (String));
387 createCol(prims, "OwnerMask", typeof (Int32));
388 createCol(prims, "NextOwnerMask", typeof (Int32));
389 createCol(prims, "GroupMask", typeof (Int32));
390 createCol(prims, "EveryoneMask", typeof (Int32));
391 createCol(prims, "BaseMask", typeof (Int32));
392 // vectors
393 createCol(prims, "PositionX", typeof (Double));
394 createCol(prims, "PositionY", typeof (Double));
395 createCol(prims, "PositionZ", typeof (Double));
396 createCol(prims, "GroupPositionX", typeof (Double));
397 createCol(prims, "GroupPositionY", typeof (Double));
398 createCol(prims, "GroupPositionZ", typeof (Double));
399 createCol(prims, "VelocityX", typeof (Double));
400 createCol(prims, "VelocityY", typeof (Double));
401 createCol(prims, "VelocityZ", typeof (Double));
402 createCol(prims, "AngularVelocityX", typeof (Double));
403 createCol(prims, "AngularVelocityY", typeof (Double));
404 createCol(prims, "AngularVelocityZ", typeof (Double));
405 createCol(prims, "AccelerationX", typeof (Double));
406 createCol(prims, "AccelerationY", typeof (Double));
407 createCol(prims, "AccelerationZ", typeof (Double));
408 // quaternions
409 createCol(prims, "RotationX", typeof (Double));
410 createCol(prims, "RotationY", typeof (Double));
411 createCol(prims, "RotationZ", typeof (Double));
412 createCol(prims, "RotationW", typeof (Double));
413
414 // sit target
415 createCol(prims, "SitTargetOffsetX", typeof (Double));
416 createCol(prims, "SitTargetOffsetY", typeof (Double));
417 createCol(prims, "SitTargetOffsetZ", typeof (Double));
418
419 createCol(prims, "SitTargetOrientW", typeof (Double));
420 createCol(prims, "SitTargetOrientX", typeof (Double));
421 createCol(prims, "SitTargetOrientY", typeof (Double));
422 createCol(prims, "SitTargetOrientZ", typeof (Double));
423
424 // Add in contraints
425 prims.PrimaryKey = new DataColumn[] {prims.Columns["UUID"]};
426
427 return prims;
428 }
429
430 private static DataTable createShapeTable()
431 {
432 DataTable shapes = new DataTable("primshapes");
433 createCol(shapes, "UUID", typeof (String));
434 // shape is an enum
435 createCol(shapes, "Shape", typeof (Int32));
436 // vectors
437 createCol(shapes, "ScaleX", typeof (Double));
438 createCol(shapes, "ScaleY", typeof (Double));
439 createCol(shapes, "ScaleZ", typeof (Double));
440 // paths
441 createCol(shapes, "PCode", typeof (Int32));
442 createCol(shapes, "PathBegin", typeof (Int32));
443 createCol(shapes, "PathEnd", typeof (Int32));
444 createCol(shapes, "PathScaleX", typeof (Int32));
445 createCol(shapes, "PathScaleY", typeof (Int32));
446 createCol(shapes, "PathShearX", typeof (Int32));
447 createCol(shapes, "PathShearY", typeof (Int32));
448 createCol(shapes, "PathSkew", typeof (Int32));
449 createCol(shapes, "PathCurve", typeof (Int32));
450 createCol(shapes, "PathRadiusOffset", typeof (Int32));
451 createCol(shapes, "PathRevolutions", typeof (Int32));
452 createCol(shapes, "PathTaperX", typeof (Int32));
453 createCol(shapes, "PathTaperY", typeof (Int32));
454 createCol(shapes, "PathTwist", typeof (Int32));
455 createCol(shapes, "PathTwistBegin", typeof (Int32));
456 // profile
457 createCol(shapes, "ProfileBegin", typeof (Int32));
458 createCol(shapes, "ProfileEnd", typeof (Int32));
459 createCol(shapes, "ProfileCurve", typeof (Int32));
460 createCol(shapes, "ProfileHollow", typeof (Int32));
461 // text TODO: this isn't right, but I'm not sure the right
462 // way to specify this as a blob atm
463 createCol(shapes, "Texture", typeof (Byte[]));
464 createCol(shapes, "ExtraParams", typeof (Byte[]));
465
466 shapes.PrimaryKey = new DataColumn[] {shapes.Columns["UUID"]};
467
468 return shapes;
469 }
470
471 /***********************************************************************
472 *
473 * Convert between ADO.NET <=> OpenSim Objects
474 *
475 * These should be database independant
476 *
477 **********************************************************************/
478
479 private static SceneObjectPart buildPrim(DataRow row)
480 {
481 // TODO: this doesn't work yet because something more
482 // interesting has to be done to actually get these values
483 // back out. Not enough time to figure it out yet.
484 SceneObjectPart prim = new SceneObjectPart();
485 prim.UUID = new LLUUID((String) row["UUID"]);
486 // explicit conversion of integers is required, which sort
487 // of sucks. No idea if there is a shortcut here or not.
488 prim.ParentID = Convert.ToUInt32(row["ParentID"]);
489 prim.CreationDate = Convert.ToInt32(row["CreationDate"]);
490 prim.Name = (String) row["Name"];
491 // various text fields
492 prim.Text = (String) row["Text"];
493 prim.Description = (String) row["Description"];
494 prim.SitName = (String) row["SitName"];
495 prim.TouchName = (String) row["TouchName"];
496 // permissions
497 prim.ObjectFlags = Convert.ToUInt32(row["ObjectFlags"]);
498 prim.CreatorID = new LLUUID((String) row["CreatorID"]);
499 prim.OwnerID = new LLUUID((String) row["OwnerID"]);
500 prim.GroupID = new LLUUID((String) row["GroupID"]);
501 prim.LastOwnerID = new LLUUID((String) row["LastOwnerID"]);
502 prim.OwnerMask = Convert.ToUInt32(row["OwnerMask"]);
503 prim.NextOwnerMask = Convert.ToUInt32(row["NextOwnerMask"]);
504 prim.GroupMask = Convert.ToUInt32(row["GroupMask"]);
505 prim.EveryoneMask = Convert.ToUInt32(row["EveryoneMask"]);
506 prim.BaseMask = Convert.ToUInt32(row["BaseMask"]);
507 // vectors
508 prim.OffsetPosition = new LLVector3(
509 Convert.ToSingle(row["PositionX"]),
510 Convert.ToSingle(row["PositionY"]),
511 Convert.ToSingle(row["PositionZ"])
512 );
513 prim.GroupPosition = new LLVector3(
514 Convert.ToSingle(row["GroupPositionX"]),
515 Convert.ToSingle(row["GroupPositionY"]),
516 Convert.ToSingle(row["GroupPositionZ"])
517 );
518 prim.Velocity = new LLVector3(
519 Convert.ToSingle(row["VelocityX"]),
520 Convert.ToSingle(row["VelocityY"]),
521 Convert.ToSingle(row["VelocityZ"])
522 );
523 prim.AngularVelocity = new LLVector3(
524 Convert.ToSingle(row["AngularVelocityX"]),
525 Convert.ToSingle(row["AngularVelocityY"]),
526 Convert.ToSingle(row["AngularVelocityZ"])
527 );
528 prim.Acceleration = new LLVector3(
529 Convert.ToSingle(row["AccelerationX"]),
530 Convert.ToSingle(row["AccelerationY"]),
531 Convert.ToSingle(row["AccelerationZ"])
532 );
533 // quaternions
534 prim.RotationOffset = new LLQuaternion(
535 Convert.ToSingle(row["RotationX"]),
536 Convert.ToSingle(row["RotationY"]),
537 Convert.ToSingle(row["RotationZ"]),
538 Convert.ToSingle(row["RotationW"])
539 );
540
541 try
542 {
543 prim.SitTargetPositionLL = new LLVector3(
544 Convert.ToSingle(row["SitTargetOffsetX"]),
545 Convert.ToSingle(row["SitTargetOffsetY"]),
546 Convert.ToSingle(row["SitTargetOffsetZ"]));
547 prim.SitTargetOrientationLL = new LLQuaternion(
548 Convert.ToSingle(
549 row["SitTargetOrientX"]),
550 Convert.ToSingle(
551 row["SitTargetOrientY"]),
552 Convert.ToSingle(
553 row["SitTargetOrientZ"]),
554 Convert.ToSingle(
555 row["SitTargetOrientW"]));
556 }
557 catch (InvalidCastException)
558 {
559 // Database table was created before we got here and now has null values :P
560 }
561
562 return prim;
563 }
564
565
566 private static void fillPrimRow(DataRow row, SceneObjectPart prim, LLUUID sceneGroupID, LLUUID regionUUID)
567 {
568 row["UUID"] = prim.UUID;
569 row["RegionUUID"] = regionUUID;
570 row["ParentID"] = prim.ParentID;
571 row["CreationDate"] = prim.CreationDate;
572 row["Name"] = prim.Name;
573 row["SceneGroupID"] = sceneGroupID; // the UUID of the root part for this SceneObjectGroup
574 // various text fields
575 row["Text"] = prim.Text;
576 row["Description"] = prim.Description;
577 row["SitName"] = prim.SitName;
578 row["TouchName"] = prim.TouchName;
579 // permissions
580 row["ObjectFlags"] = prim.ObjectFlags;
581 row["CreatorID"] = prim.CreatorID;
582 row["OwnerID"] = prim.OwnerID;
583 row["GroupID"] = prim.GroupID;
584 row["LastOwnerID"] = prim.LastOwnerID;
585 row["OwnerMask"] = prim.OwnerMask;
586 row["NextOwnerMask"] = prim.NextOwnerMask;
587 row["GroupMask"] = prim.GroupMask;
588 row["EveryoneMask"] = prim.EveryoneMask;
589 row["BaseMask"] = prim.BaseMask;
590 // vectors
591 row["PositionX"] = prim.OffsetPosition.X;
592 row["PositionY"] = prim.OffsetPosition.Y;
593 row["PositionZ"] = prim.OffsetPosition.Z;
594 row["GroupPositionX"] = prim.GroupPosition.X;
595 row["GroupPositionY"] = prim.GroupPosition.Y;
596 row["GroupPositionZ"] = prim.GroupPosition.Z;
597 row["VelocityX"] = prim.Velocity.X;
598 row["VelocityY"] = prim.Velocity.Y;
599 row["VelocityZ"] = prim.Velocity.Z;
600 row["AngularVelocityX"] = prim.AngularVelocity.X;
601 row["AngularVelocityY"] = prim.AngularVelocity.Y;
602 row["AngularVelocityZ"] = prim.AngularVelocity.Z;
603 row["AccelerationX"] = prim.Acceleration.X;
604 row["AccelerationY"] = prim.Acceleration.Y;
605 row["AccelerationZ"] = prim.Acceleration.Z;
606 // quaternions
607 row["RotationX"] = prim.RotationOffset.X;
608 row["RotationY"] = prim.RotationOffset.Y;
609 row["RotationZ"] = prim.RotationOffset.Z;
610 row["RotationW"] = prim.RotationOffset.W;
611
612 try
613 {
614 // Sit target
615 LLVector3 sitTargetPos = prim.SitTargetPositionLL;
616 row["SitTargetOffsetX"] = sitTargetPos.X;
617 row["SitTargetOffsetY"] = sitTargetPos.Y;
618 row["SitTargetOffsetZ"] = sitTargetPos.Z;
619
620 LLQuaternion sitTargetOrient = prim.SitTargetOrientationLL;
621 row["SitTargetOrientW"] = sitTargetOrient.W;
622 row["SitTargetOrientX"] = sitTargetOrient.X;
623 row["SitTargetOrientY"] = sitTargetOrient.Y;
624 row["SitTargetOrientZ"] = sitTargetOrient.Z;
625 }
626 catch (Exception)
627 {
628 // TODO: Add Sit Target Rows!
629 }
630 }
631
632 private static PrimitiveBaseShape buildShape(DataRow row)
633 {
634 PrimitiveBaseShape s = new PrimitiveBaseShape();
635 s.Scale = new LLVector3(
636 Convert.ToSingle(row["ScaleX"]),
637 Convert.ToSingle(row["ScaleY"]),
638 Convert.ToSingle(row["ScaleZ"])
639 );
640 // paths
641 s.PCode = Convert.ToByte(row["PCode"]);
642 s.PathBegin = Convert.ToUInt16(row["PathBegin"]);
643 s.PathEnd = Convert.ToUInt16(row["PathEnd"]);
644 s.PathScaleX = Convert.ToByte(row["PathScaleX"]);
645 s.PathScaleY = Convert.ToByte(row["PathScaleY"]);
646 s.PathShearX = Convert.ToByte(row["PathShearX"]);
647 s.PathShearY = Convert.ToByte(row["PathShearY"]);
648 s.PathSkew = Convert.ToSByte(row["PathSkew"]);
649 s.PathCurve = Convert.ToByte(row["PathCurve"]);
650 s.PathRadiusOffset = Convert.ToSByte(row["PathRadiusOffset"]);
651 s.PathRevolutions = Convert.ToByte(row["PathRevolutions"]);
652 s.PathTaperX = Convert.ToSByte(row["PathTaperX"]);
653 s.PathTaperY = Convert.ToSByte(row["PathTaperY"]);
654 s.PathTwist = Convert.ToSByte(row["PathTwist"]);
655 s.PathTwistBegin = Convert.ToSByte(row["PathTwistBegin"]);
656 // profile
657 s.ProfileBegin = Convert.ToUInt16(row["ProfileBegin"]);
658 s.ProfileEnd = Convert.ToUInt16(row["ProfileEnd"]);
659 s.ProfileCurve = Convert.ToByte(row["ProfileCurve"]);
660 s.ProfileHollow = Convert.ToUInt16(row["ProfileHollow"]);
661
662 // text TODO: this isn't right] = but I'm not sure the right
663 // way to specify this as a blob atm
664 byte[] textureEntry = (byte[]) row["Texture"];
665 s.TextureEntry = textureEntry;
666
667
668 s.ExtraParams = (byte[]) row["ExtraParams"];
669
670 return s;
671 }
672
673 private static void fillShapeRow(DataRow row, SceneObjectPart prim)
674 {
675 PrimitiveBaseShape s = prim.Shape;
676 row["UUID"] = prim.UUID;
677 // shape is an enum
678 row["Shape"] = 0;
679 // vectors
680 row["ScaleX"] = s.Scale.X;
681 row["ScaleY"] = s.Scale.Y;
682 row["ScaleZ"] = s.Scale.Z;
683 // paths
684 row["PCode"] = s.PCode;
685 row["PathBegin"] = s.PathBegin;
686 row["PathEnd"] = s.PathEnd;
687 row["PathScaleX"] = s.PathScaleX;
688 row["PathScaleY"] = s.PathScaleY;
689 row["PathShearX"] = s.PathShearX;
690 row["PathShearY"] = s.PathShearY;
691 row["PathSkew"] = s.PathSkew;
692 row["PathCurve"] = s.PathCurve;
693 row["PathRadiusOffset"] = s.PathRadiusOffset;
694 row["PathRevolutions"] = s.PathRevolutions;
695 row["PathTaperX"] = s.PathTaperX;
696 row["PathTaperY"] = s.PathTaperY;
697 row["PathTwist"] = s.PathTwist;
698 row["PathTwistBegin"] = s.PathTwistBegin;
699 // profile
700 row["ProfileBegin"] = s.ProfileBegin;
701 row["ProfileEnd"] = s.ProfileEnd;
702 row["ProfileCurve"] = s.ProfileCurve;
703 row["ProfileHollow"] = s.ProfileHollow;
704 // text TODO: this isn't right] = but I'm not sure the right
705 // way to specify this as a blob atm
706
707 // And I couldn't work out how to save binary data either
708 // seems that the texture colum is being treated as a string in the Datarow
709 // if you do a .getType() on it, it returns string, while the other columns return correct type
710 // MW[10-08-07]
711 // Added following xml hack but not really ideal , also ExtraParams isn't currently part of the database
712 // am a bit worried about adding it now as some people will have old format databases, so for now including that data in this xml data
713 // MW[17-08-07]
714 row["Texture"] = s.TextureEntry;
715 row["ExtraParams"] = s.ExtraParams;
716 // TextureBlock textureBlock = new TextureBlock(s.TextureEntry);
717 // textureBlock.ExtraParams = s.ExtraParams;
718 // System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
719 // row["Texture"] = encoding.GetBytes(textureBlock.ToXMLString());
720 }
721
722 private void addPrim(SceneObjectPart prim, LLUUID sceneGroupID, LLUUID regionUUID)
723 {
724 DataTable prims = ds.Tables["prims"];
725 DataTable shapes = ds.Tables["primshapes"];
726
727 DataRow primRow = prims.Rows.Find(prim.UUID);
728 if (primRow == null)
729 {
730 primRow = prims.NewRow();
731 fillPrimRow(primRow, prim, sceneGroupID, regionUUID);
732 prims.Rows.Add(primRow);
733 }
734 else
735 {
736 fillPrimRow(primRow, prim, sceneGroupID, regionUUID);
737 }
738
739 DataRow shapeRow = shapes.Rows.Find(prim.UUID);
740 if (shapeRow == null)
741 {
742 shapeRow = shapes.NewRow();
743 fillShapeRow(shapeRow, prim);
744 shapes.Rows.Add(shapeRow);
745 }
746 else
747 {
748 fillShapeRow(shapeRow, prim);
749 }
750 }
751
752 // see IRegionDatastore
753 public void StorePrimInventory(LLUUID primID, ICollection<TaskInventoryItem> items)
754 {
755 // No implementation yet
756 }
757
758 /***********************************************************************
759 *
760 * SQL Statement Creation Functions
761 *
762 * These functions create SQL statements for update, insert, and create.
763 * They can probably be factored later to have a db independant
764 * portion and a db specific portion
765 *
766 **********************************************************************/
767
768 private static SqlCommand createInsertCommand(string table, DataTable dt)
769 {
770 /**
771 * This is subtle enough to deserve some commentary.
772 * Instead of doing *lots* and *lots of hardcoded strings
773 * for database definitions we'll use the fact that
774 * realistically all insert statements look like "insert
775 * into A(b, c) values(:b, :c) on the parameterized query
776 * front. If we just have a list of b, c, etc... we can
777 * generate these strings instead of typing them out.
778 */
779 string[] cols = new string[dt.Columns.Count];
780 for (int i = 0; i < dt.Columns.Count; i++)
781 {
782 DataColumn col = dt.Columns[i];
783 cols[i] = col.ColumnName;
784 }
785
786 string sql = "insert into " + table + "(";
787 sql += String.Join(", ", cols);
788 // important, the first ':' needs to be here, the rest get added in the join
789 sql += ") values (@";
790 sql += String.Join(", @", cols);
791 sql += ")";
792 SqlCommand cmd = new SqlCommand(sql);
793 // this provides the binding for all our parameters, so
794 // much less code than it used to be
795 foreach (DataColumn col in dt.Columns)
796 {
797 cmd.Parameters.Add(createSqlParameter(col.ColumnName, col.DataType));
798 }
799 return cmd;
800 }
801
802 private static SqlCommand createUpdateCommand(string table, string pk, DataTable dt)
803 {
804 string sql = "update " + table + " set ";
805 string subsql = String.Empty;
806 foreach (DataColumn col in dt.Columns)
807 {
808 if (subsql.Length > 0)
809 {
810 // a map function would rock so much here
811 subsql += ", ";
812 }
813 subsql += col.ColumnName + "= @" + col.ColumnName;
814 }
815 sql += subsql;
816 sql += " where " + pk;
817 SqlCommand cmd = new SqlCommand(sql);
818 // this provides the binding for all our parameters, so
819 // much less code than it used to be
820
821 foreach (DataColumn col in dt.Columns)
822 {
823 cmd.Parameters.Add(createSqlParameter(col.ColumnName, col.DataType));
824 }
825 return cmd;
826 }
827
828
829 private static string defineTable(DataTable dt)
830 {
831 string sql = "create table " + dt.TableName + "(";
832 string subsql = String.Empty;
833 foreach (DataColumn col in dt.Columns)
834 {
835 if (subsql.Length > 0)
836 {
837 // a map function would rock so much here
838 subsql += ",\n";
839 }
840 subsql += col.ColumnName + " " + SqlType(col.DataType);
841 if (dt.PrimaryKey.Length > 0 && col == dt.PrimaryKey[0])
842 {
843 subsql += " primary key";
844 }
845 }
846 sql += subsql;
847 sql += ")";
848
849 return sql;
850 }
851
852 private static void fillTerrainRow(DataRow row, LLUUID regionUUID, int rev, double[,] val)
853 {
854 row["RegionUUID"] = regionUUID;
855 row["Revision"] = rev;
856
857 MemoryStream str = new MemoryStream(65536*sizeof (double));
858 BinaryWriter bw = new BinaryWriter(str);
859
860 // TODO: COMPATIBILITY - Add byte-order conversions
861 for (int x = 0; x < 256; x++)
862 for (int y = 0; y < 256; y++)
863 bw.Write(val[x, y]);
864
865 row["Heightfield"] = str.ToArray();
866 }
867
868 /***********************************************************************
869 *
870 * Database Binding functions
871 *
872 * These will be db specific due to typing, and minor differences
873 * in databases.
874 *
875 **********************************************************************/
876
877 ///<summary>
878 /// This is a convenience function that collapses 5 repetitive
879 /// lines for defining SqlParameters to 2 parameters:
880 /// column name and database type.
881 ///
882 /// It assumes certain conventions like :param as the param
883 /// name to replace in parametrized queries, and that source
884 /// version is always current version, both of which are fine
885 /// for us.
886 ///</summary>
887 ///<returns>a built Sql parameter</returns>
888 private static SqlParameter createSqlParameter(string name, Type type)
889 {
890 SqlParameter param = new SqlParameter();
891 param.ParameterName = "@" + name;
892 param.DbType = dbtypeFromType(type);
893 param.SourceColumn = name;
894 param.SourceVersion = DataRowVersion.Current;
895 return param;
896 }
897
898 private void setupPrimCommands(SqlDataAdapter da, SqlConnection conn)
899 {
900 da.InsertCommand = createInsertCommand("prims", ds.Tables["prims"]);
901 da.InsertCommand.Connection = conn;
902
903 da.UpdateCommand = createUpdateCommand("prims", "UUID=@UUID", ds.Tables["prims"]);
904 da.UpdateCommand.Connection = conn;
905
906 SqlCommand delete = new SqlCommand("delete from prims where UUID = @UUID");
907 delete.Parameters.Add(createSqlParameter("UUID", typeof (String)));
908 delete.Connection = conn;
909 da.DeleteCommand = delete;
910 }
911
912 private void setupShapeCommands(SqlDataAdapter da, SqlConnection conn)
913 {
914 da.InsertCommand = createInsertCommand("primshapes", ds.Tables["primshapes"]);
915 da.InsertCommand.Connection = conn;
916
917 da.UpdateCommand = createUpdateCommand("primshapes", "UUID=@UUID", ds.Tables["primshapes"]);
918 da.UpdateCommand.Connection = conn;
919
920 SqlCommand delete = new SqlCommand("delete from primshapes where UUID = @UUID");
921 delete.Parameters.Add(createSqlParameter("UUID", typeof (String)));
922 delete.Connection = conn;
923 da.DeleteCommand = delete;
924 }
925
926 private void setupTerrainCommands(SqlDataAdapter da, SqlConnection conn)
927 {
928 da.InsertCommand = createInsertCommand("terrain", ds.Tables["terrain"]);
929 da.InsertCommand.Connection = conn;
930 }
931
932 private static void InitDB(SqlConnection conn)
933 {
934 string createPrims = defineTable(createPrimTable());
935 string createShapes = defineTable(createShapeTable());
936 string createTerrain = defineTable(createTerrainTable());
937
938 SqlCommand pcmd = new SqlCommand(createPrims, conn);
939 SqlCommand scmd = new SqlCommand(createShapes, conn);
940 SqlCommand tcmd = new SqlCommand(createTerrain, conn);
941 conn.Open();
942 try
943 {
944 pcmd.ExecuteNonQuery();
945 pcmd.Dispose();
946 }
947 catch (SqlException)
948 {
949 m_log.Warn("[MSSQL]: Primitives Table Already Exists");
950 }
951
952 try
953 {
954 scmd.ExecuteNonQuery();
955 scmd.Dispose();
956 }
957 catch (SqlException)
958 {
959 m_log.Warn("[MSSQL]: Shapes Table Already Exists");
960 }
961
962 try
963 {
964 tcmd.ExecuteNonQuery();
965 tcmd.Dispose();
966 }
967 catch (SqlException)
968 {
969 m_log.Warn("[MSSQL]: Terrain Table Already Exists");
970 }
971
972 conn.Close();
973 }
974
975 private static bool TestTables(SqlConnection conn)
976 {
977 SqlCommand primSelectCmd = new SqlCommand(primSelect, conn);
978 SqlDataAdapter pDa = new SqlDataAdapter(primSelectCmd);
979 SqlCommand shapeSelectCmd = new SqlCommand(shapeSelect, conn);
980 SqlDataAdapter sDa = new SqlDataAdapter(shapeSelectCmd);
981 SqlCommand terrainSelectCmd = new SqlCommand(terrainSelect, conn);
982 SqlDataAdapter tDa = new SqlDataAdapter(terrainSelectCmd);
983
984 DataSet tmpDS = new DataSet();
985 try
986 {
987 pDa.Fill(tmpDS, "prims");
988 sDa.Fill(tmpDS, "primshapes");
989 tDa.Fill(tmpDS, "terrain");
990 }
991 catch (SqlException)
992 {
993 m_log.Info("[DATASTORE]: MSSQL Database doesn't exist... creating");
994 InitDB(conn);
995 }
996
997 try
998 {
999 if (tmpDS.Tables == null || tmpDS.Tables.Count == 0)
1000 {
1001 pDa.Fill(tmpDS, "prims");
1002 sDa.Fill(tmpDS, "primshapes");
1003 tDa.Fill(tmpDS, "terrain");
1004 }
1005 }
1006 catch (SqlException e)
1007 {
1008 m_log.Info("[DATASTORE]: " + e.ToString());
1009 }
1010
1011 foreach (DataColumn col in createPrimTable().Columns)
1012 {
1013 if (!tmpDS.Tables["prims"].Columns.Contains(col.ColumnName))
1014 {
1015 m_log.Info("[DATASTORE]: Missing required column:" + col.ColumnName);
1016 return false;
1017 }
1018 }
1019 foreach (DataColumn col in createShapeTable().Columns)
1020 {
1021 if (!tmpDS.Tables["primshapes"].Columns.Contains(col.ColumnName))
1022 {
1023 m_log.Info("[DATASTORE]: Missing required column:" + col.ColumnName);
1024 return false;
1025 }
1026 }
1027 foreach (DataColumn col in createTerrainTable().Columns)
1028 {
1029 if (!tmpDS.Tables["terrain"].Columns.Contains(col.ColumnName))
1030 {
1031 m_log.Info("[DATASTORE]: Missing require column:" + col.ColumnName);
1032 return false;
1033 }
1034 }
1035 return true;
1036 }
1037
1038 /***********************************************************************
1039 *
1040 * Type conversion functions
1041 *
1042 **********************************************************************/
1043
1044 private static DbType dbtypeFromType(Type type)
1045 {
1046 if (type == typeof (String))
1047 {
1048 return DbType.String;
1049 }
1050 else if (type == typeof (Int32))
1051 {
1052 return DbType.Int32;
1053 }
1054 else if (type == typeof (Double))
1055 {
1056 return DbType.Double;
1057 }
1058 else if (type == typeof (Byte[]))
1059 {
1060 return DbType.Binary;
1061 }
1062 else
1063 {
1064 return DbType.String;
1065 }
1066 }
1067
1068 // this is something we'll need to implement for each db
1069 // slightly differently.
1070 private static string SqlType(Type type)
1071 {
1072 if (type == typeof (String))
1073 {
1074 return "varchar(255)";
1075 }
1076 else if (type == typeof (Int32))
1077 {
1078 return "integer";
1079 }
1080 else if (type == typeof (Double))
1081 {
1082 return "float";
1083 }
1084 else if (type == typeof (Byte[]))
1085 {
1086 return "image";
1087 }
1088 else
1089 {
1090 return "string";
1091 }
1092 }
1093 }
1094}