aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorMelanie Thielker2008-09-01 17:10:01 +0000
committerMelanie Thielker2008-09-01 17:10:01 +0000
commitb6bb5f944f19b330656105ff79cd5ca3f2d5c242 (patch)
tree433ee8a24136ac10ed63dc3cf715b16ba786b8a8
parentMantis #2072 (diff)
downloadopensim-SC-b6bb5f944f19b330656105ff79cd5ca3f2d5c242.zip
opensim-SC-b6bb5f944f19b330656105ff79cd5ca3f2d5c242.tar.gz
opensim-SC-b6bb5f944f19b330656105ff79cd5ca3f2d5c242.tar.bz2
opensim-SC-b6bb5f944f19b330656105ff79cd5ca3f2d5c242.tar.xz
Mantis #2095
Thank you, RuudL, for a complete adaptation of migration and estate data to MSSQL, and the updating of the RegionData handling in MSSQL.
-rw-r--r--OpenSim/Data/MSSQL/MSSQLEstateData.cs434
-rw-r--r--OpenSim/Data/MSSQL/MSSQLManager.cs116
-rw-r--r--OpenSim/Data/MSSQL/MSSQLMigration.cs45
-rw-r--r--OpenSim/Data/MSSQL/MSSQLRegionData.cs2410
-rw-r--r--OpenSim/Data/MSSQL/Resources/001_EstateStore.sql85
-rw-r--r--OpenSim/Data/MSSQL/Resources/002_RegionStore.sql50
-rw-r--r--OpenSim/Data/MSSQL/Resources/003_RegionStore.sql67
-rw-r--r--OpenSim/Data/MSSQL/Resources/004_RegionStore.sql40
-rw-r--r--OpenSim/Data/MSSQL/Resources/005_RegionStore.sql49
-rw-r--r--OpenSim/Data/MSSQL/Resources/006_RegionStore.sql36
-rw-r--r--OpenSim/Data/Migration.cs10
11 files changed, 1971 insertions, 1371 deletions
diff --git a/OpenSim/Data/MSSQL/MSSQLEstateData.cs b/OpenSim/Data/MSSQL/MSSQLEstateData.cs
new file mode 100644
index 0000000..ca4691c
--- /dev/null
+++ b/OpenSim/Data/MSSQL/MSSQLEstateData.cs
@@ -0,0 +1,434 @@
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.Reflection;
33using libsecondlife;
34using log4net;
35using OpenSim.Framework;
36using OpenSim.Region.Environment.Interfaces;
37
38namespace OpenSim.Data.MSSQL
39{
40 public class MSSQLEstateData : IEstateDataStore
41 {
42 private static readonly ILog _Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
43
44 private MSSQLManager _Database;
45
46 private FieldInfo[] _Fields;
47 private Dictionary<string, FieldInfo> _FieldMap = new Dictionary<string, FieldInfo>();
48
49 #region Public methods
50
51 /// <summary>
52 /// Initialises the estatedata class.
53 /// </summary>
54 /// <param name="connectionString">connectionString.</param>
55 public void Initialise(string connectionString)
56 {
57 if (string.IsNullOrEmpty(connectionString))
58 {
59 _Database = new MSSQLManager(connectionString);
60 }
61 else
62 {
63 //TODO when can this be deleted
64 IniFile iniFile = new IniFile("mssql_connection.ini");
65 string settingDataSource = iniFile.ParseFileReadValue("data_source");
66 string settingInitialCatalog = iniFile.ParseFileReadValue("initial_catalog");
67 string settingPersistSecurityInfo = iniFile.ParseFileReadValue("persist_security_info");
68 string settingUserId = iniFile.ParseFileReadValue("user_id");
69 string settingPassword = iniFile.ParseFileReadValue("password");
70
71 _Database =
72 new MSSQLManager(settingDataSource, settingInitialCatalog, settingPersistSecurityInfo, settingUserId,
73 settingPassword);
74 }
75
76 //Migration settings
77 using (SqlConnection connection = _Database.DatabaseConnection())
78 {
79 Assembly assem = GetType().Assembly;
80 MSSQLMigration migration = new MSSQLMigration(connection, assem, "EstateStore");
81
82 migration.Update();
83
84 connection.Close();
85 }
86
87 //Interesting way to get parameters! Maybe implement that also with other types
88 Type t = typeof(EstateSettings);
89 _Fields = t.GetFields(BindingFlags.NonPublic |
90 BindingFlags.Instance |
91 BindingFlags.DeclaredOnly);
92
93 foreach (FieldInfo f in _Fields)
94 {
95 if (f.Name.Substring(0, 2) == "m_")
96 _FieldMap[f.Name.Substring(2)] = f;
97 }
98 }
99
100 /// <summary>
101 /// Loads the estate settings.
102 /// </summary>
103 /// <param name="regionID">region ID.</param>
104 /// <returns></returns>
105 public EstateSettings LoadEstateSettings(LLUUID regionID)
106 {
107 EstateSettings es = new EstateSettings();
108
109 string sql = "select estate_settings." + String.Join(",estate_settings.", FieldList) + " from estate_map left join estate_settings on estate_map.EstateID = estate_settings.EstateID where estate_settings.EstateID is not null and RegionID = @RegionID";
110
111 bool insertEstate = false;
112
113 using (AutoClosingSqlCommand cmd = _Database.Query(sql))
114 {
115 cmd.Parameters.AddWithValue("@RegionID", regionID.ToString());
116
117 using (IDataReader reader = cmd.ExecuteReader())
118 {
119 if (reader.Read())
120 {
121 foreach (string name in FieldList)
122 {
123 if (_FieldMap[name].GetValue(es) is bool)
124 {
125 int v = Convert.ToInt32(reader[name]);
126 if (v != 0)
127 _FieldMap[name].SetValue(es, true);
128 else
129 _FieldMap[name].SetValue(es, false);
130 }
131 else if (_FieldMap[name].GetValue(es) is LLUUID)
132 {
133 LLUUID uuid;
134 LLUUID.TryParse(reader[name].ToString(), out uuid);
135
136 _FieldMap[name].SetValue(es, uuid);
137 }
138 else
139 {
140 _FieldMap[name].SetValue(es, reader[name]);
141 }
142 }
143 }
144 else
145 {
146 insertEstate = true;
147 }
148 }
149 }
150
151
152 if (insertEstate)
153 {
154 List<string> names = new List<string>(FieldList);
155
156 names.Remove("EstateID");
157
158 sql = string.Format("insert into estate_settings ({0}) values ( @{1})", String.Join(",", names.ToArray()), String.Join(", @", names.ToArray()));
159
160 //_Log.Debug("[DB ESTATE]: SQL: " + sql);
161 using (SqlConnection connection = _Database.DatabaseConnection())
162 {
163 using (SqlCommand insertCommand = connection.CreateCommand())
164 {
165 insertCommand.CommandText = sql + " SET @ID = SCOPE_IDENTITY()";
166
167 foreach (string name in names)
168 {
169 if (_FieldMap[name].GetValue(es) is bool)
170 {
171 SqlParameter tempBool = new SqlParameter("@" + name, SqlDbType.Bit);
172
173 if ((bool) _FieldMap[name].GetValue(es))
174 tempBool.Value = 1;
175 else
176 tempBool.Value = 0;
177
178 insertCommand.Parameters.Add(tempBool);
179 }
180 else
181 {
182 //cmd.Parameters.AddWithValue("@" + name, _FieldMap[name].GetValue(es));
183 SqlParameter tempPar = new SqlParameter("@" + name,
184 _Database.DbtypeFromType(_FieldMap[name].FieldType));
185 tempPar.Value = _FieldMap[name].GetValue(es).ToString();
186
187 insertCommand.Parameters.Add(tempPar);
188 }
189 }
190
191
192 SqlParameter idParameter = new SqlParameter("@ID", SqlDbType.Int);
193 idParameter.Direction = ParameterDirection.Output;
194 insertCommand.Parameters.Add(idParameter);
195
196 insertCommand.ExecuteNonQuery();
197
198 es.EstateID = Convert.ToUInt32(idParameter.Value);
199 }
200 }
201
202 using (AutoClosingSqlCommand cmd = _Database.Query("insert into estate_map values (@RegionID, @EstateID)"))
203 {
204 cmd.Parameters.AddWithValue("@RegionID", regionID.ToString());
205 cmd.Parameters.AddWithValue("@EstateID", es.EstateID);
206 // This will throw on dupe key
207 try
208 {
209 cmd.ExecuteNonQuery();
210 }
211 catch (Exception)
212 {
213 _Log.Debug("[ESTATE DB]: Error inserting regionID and EstateID in estate_map");
214 }
215 }
216
217 // Munge and transfer the ban list
218 //
219
220 sql = string.Format("insert into estateban select {0}, bannedUUID, bannedIp, bannedIpHostMask, '' from regionban where regionban.regionUUID = @UUID", es.EstateID);
221 using (AutoClosingSqlCommand cmd = _Database.Query(sql))
222 {
223 cmd.Parameters.AddWithValue("@UUID", regionID);
224 try
225 {
226
227 cmd.ExecuteNonQuery();
228 }
229 catch (Exception)
230 {
231 _Log.Debug("[ESTATE DB]: Error setting up estateban from regionban");
232 }
233 }
234
235 //TODO check if this is needed??
236 es.Save();
237 }
238
239 LoadBanList(es);
240
241 es.EstateManagers = LoadUUIDList(es.EstateID, "estate_managers");
242 es.EstateAccess = LoadUUIDList(es.EstateID, "estate_users");
243 es.EstateGroups = LoadUUIDList(es.EstateID, "estate_groups");
244
245 //Set event
246 es.OnSave += StoreEstateSettings;
247 return es;
248 }
249
250 /// <summary>
251 /// Stores the estate settings.
252 /// </summary>
253 /// <param name="es">estate settings</param>
254 public void StoreEstateSettings(EstateSettings es)
255 {
256 List<string> names = new List<string>(FieldList);
257
258 names.Remove("EstateID");
259
260 string sql = string.Format("UPDATE estate_settings SET ") ; // ({0}) values ( @{1}) WHERE EstateID = @EstateID", String.Join(",", names.ToArray()), String.Join(", @", names.ToArray()));
261 foreach (string name in names)
262 {
263 sql += name + " = @" + name + ", ";
264 }
265 sql = sql.Remove(sql.LastIndexOf(","));
266 sql += " WHERE EstateID = @EstateID";
267
268 using (AutoClosingSqlCommand cmd = _Database.Query(sql))
269 {
270 foreach (string name in names)
271 {
272 if (_FieldMap[name].GetValue(es) is bool)
273 {
274 SqlParameter tempBool = new SqlParameter("@" + name, SqlDbType.Bit);
275
276 if ((bool)_FieldMap[name].GetValue(es))
277 tempBool.Value = 1;
278 else
279 tempBool.Value = 0;
280
281 cmd.Parameters.Add(tempBool);
282 }
283 else
284 {
285 //cmd.Parameters.AddWithValue("@" + name, _FieldMap[name].GetValue(es));
286 SqlParameter tempPar = new SqlParameter("@" + name,
287 _Database.DbtypeFromType(_FieldMap[name].FieldType));
288 tempPar.Value = _FieldMap[name].GetValue(es).ToString();
289
290 cmd.Parameters.Add(tempPar);
291 }
292 }
293
294
295 SqlParameter idParameter = new SqlParameter("@EstateID", SqlDbType.Int);
296 idParameter.Value = es.EstateID;
297 cmd.Parameters.Add(idParameter);
298
299 cmd.ExecuteNonQuery();
300 }
301
302 SaveBanList(es);
303 SaveUUIDList(es.EstateID, "estate_managers", es.EstateManagers);
304 SaveUUIDList(es.EstateID, "estate_users", es.EstateAccess);
305 SaveUUIDList(es.EstateID, "estate_groups", es.EstateGroups);
306 }
307
308 #endregion
309
310 #region Private methods
311
312 private string[] FieldList
313 {
314 get { return new List<string>(_FieldMap.Keys).ToArray(); }
315 }
316
317 private void LoadBanList(EstateSettings es)
318 {
319 es.ClearBans();
320
321 string sql = "select bannedUUID from estateban where EstateID = @EstateID";
322
323 using (AutoClosingSqlCommand cmd = _Database.Query(sql))
324 {
325 SqlParameter idParameter = new SqlParameter("@EstateID", SqlDbType.Int);
326 idParameter.Value = es.EstateID;
327 cmd.Parameters.Add(idParameter);
328
329 using (IDataReader reader = cmd.ExecuteReader())
330 {
331 while (reader.Read())
332 {
333 EstateBan eb = new EstateBan();
334
335 LLUUID uuid;
336 LLUUID.TryParse(reader["bannedUUID"].ToString(), out uuid);
337
338 eb.bannedUUID = uuid;
339 eb.bannedIP = "0.0.0.0";
340 eb.bannedIPHostMask = "0.0.0.0";
341 es.AddBan(eb);
342 }
343 }
344 }
345 }
346
347 private LLUUID[] LoadUUIDList(uint estateID, string table)
348 {
349 List<LLUUID> uuids = new List<LLUUID>();
350
351 string sql = string.Format("select uuid from {0} where EstateID = @EstateID", table);
352
353 using (AutoClosingSqlCommand cmd = _Database.Query(sql))
354 {
355 cmd.Parameters.Add(_Database.CreateParameter("@EstateID", estateID));
356
357 using (IDataReader reader = cmd.ExecuteReader())
358 {
359 while (reader.Read())
360 {
361 // EstateBan eb = new EstateBan();
362
363 LLUUID uuid;
364 LLUUID.TryParse(reader["uuid"].ToString(), out uuid);
365
366 uuids.Add(uuid);
367 }
368 }
369 }
370
371 return uuids.ToArray();
372 }
373
374 private void SaveBanList(EstateSettings es)
375 {
376 //Delete first
377 string sql = "delete from estateban where EstateID = @EstateID";
378 using (AutoClosingSqlCommand cmd = _Database.Query(sql))
379 {
380 cmd.Parameters.Add(_Database.CreateParameter("@EstateID", es.EstateID));
381 cmd.ExecuteNonQuery();
382 }
383
384 //Insert after
385 sql = "insert into estateban (EstateID, bannedUUID) values ( @EstateID, @bannedUUID )";
386 using (AutoClosingSqlCommand cmd = _Database.Query(sql))
387 {
388 foreach (EstateBan b in es.EstateBans)
389 {
390 cmd.Parameters.Add(_Database.CreateParameter("@EstateID", es.EstateID));
391
392 cmd.Parameters.Add(_Database.CreateParameter("@bannedUUID", b.bannedUUID));
393
394 cmd.ExecuteNonQuery();
395
396 cmd.Parameters.Clear();
397 }
398 }
399 }
400
401 private void SaveUUIDList(uint estateID, string table, LLUUID[] data)
402 {
403 //Delete first
404 string sql = string.Format("delete from {0} where EstateID = @EstateID", table);
405 using (AutoClosingSqlCommand cmd = _Database.Query(sql))
406 {
407 cmd.Parameters.Add(_Database.CreateParameter("@EstateID", estateID));
408 cmd.ExecuteNonQuery();
409 }
410
411 sql = string.Format("insert into {0} (EstateID, uuid) values ( @EstateID, @uuid )", table);
412 using (AutoClosingSqlCommand cmd = _Database.Query(sql))
413 {
414 cmd.Parameters.Add(_Database.CreateParameter("@EstateID", estateID));
415
416 bool createParamOnce = true;
417
418 foreach (LLUUID uuid in data)
419 {
420 if (createParamOnce)
421 {
422 cmd.Parameters.Add(_Database.CreateParameter("@uuid", uuid));
423 createParamOnce = false;
424 }
425 else
426 cmd.Parameters["@uuid"].Value = uuid.ToString();
427
428 cmd.ExecuteNonQuery();
429 }
430 }
431 }
432 #endregion
433 }
434}
diff --git a/OpenSim/Data/MSSQL/MSSQLManager.cs b/OpenSim/Data/MSSQL/MSSQLManager.cs
index 1a053d5..535cf33 100644
--- a/OpenSim/Data/MSSQL/MSSQLManager.cs
+++ b/OpenSim/Data/MSSQL/MSSQLManager.cs
@@ -64,9 +64,20 @@ namespace OpenSim.Data.MSSQL
64 connectionString = builder.ToString(); 64 connectionString = builder.ToString();
65 } 65 }
66 66
67 private SqlConnection createConnection() 67 /// <summary>
68 /// Initialize the manager and set the connectionstring
69 /// </summary>
70 /// <param name="connection"></param>
71 public MSSQLManager(string connection)
72 {
73 connectionString = connection;
74 }
75
76 public SqlConnection DatabaseConnection()
68 { 77 {
69 SqlConnection conn = new SqlConnection(connectionString); 78 SqlConnection conn = new SqlConnection(connectionString);
79
80 //TODO is this good??? Opening connection here
70 conn.Open(); 81 conn.Open();
71 82
72 return conn; 83 return conn;
@@ -186,6 +197,105 @@ namespace OpenSim.Data.MSSQL
186 } 197 }
187 } 198 }
188 199
200 /// <summary>
201 /// Type conversion to a SQLDbType functions
202 /// </summary>
203 /// <param name="type"></param>
204 /// <returns></returns>
205 internal SqlDbType DbtypeFromType(Type type)
206 {
207 if (type == typeof(string))
208 {
209 return SqlDbType.VarChar;
210 }
211 if (type == typeof(double))
212 {
213 return SqlDbType.Float;
214 }
215 if (type == typeof(int))
216 {
217 return SqlDbType.Int;
218 }
219 if (type == typeof(bool))
220 {
221 return SqlDbType.Bit;
222 }
223 if (type == typeof(LLUUID))
224 {
225 return SqlDbType.VarChar;
226 }
227 if (type == typeof(Byte[]))
228 {
229 return SqlDbType.Image;
230 }
231 if (type == typeof(uint))
232 {
233 return SqlDbType.Int;
234 }
235 return SqlDbType.VarChar;
236 }
237
238 /// <summary>
239 /// Creates value for parameter.
240 /// </summary>
241 /// <param name="value">The value.</param>
242 /// <returns></returns>
243 private static object CreateParameterValue(object value)
244 {
245 Type valueType = value.GetType();
246
247 if (valueType == typeof(LLUUID))
248 {
249 return value.ToString();
250 }
251 if (valueType == typeof(bool))
252 {
253 return (bool)value ? 1 : 0;
254 }
255 if (valueType == typeof(Byte[]))
256 {
257 return value;
258 }
259 return value;
260 }
261
262 /// <summary>
263 /// Create a parameter for a command
264 /// </summary>
265 /// <param name="parameterName">Name of the parameter.</param>
266 /// <param name="parameterObject">parameter object.</param>
267 /// <returns></returns>
268 internal SqlParameter CreateParameter(string parameterName, object parameterObject)
269 {
270 return CreateParameter(parameterName, parameterObject, false);
271 }
272
273 /// <summary>
274 /// Creates the parameter for a command.
275 /// </summary>
276 /// <param name="parameterName">Name of the parameter.</param>
277 /// <param name="parameterObject">parameter object.</param>
278 /// <param name="parameterOut">if set to <c>true</c> parameter is a output parameter</param>
279 /// <returns></returns>
280 internal SqlParameter CreateParameter(string parameterName, object parameterObject, bool parameterOut)
281 {
282 //Tweak so we dont always have to add @ sign
283 if (!parameterName.StartsWith("@")) parameterName = "@" + parameterName;
284
285 SqlParameter parameter = new SqlParameter(parameterName, DbtypeFromType(parameterObject.GetType()));
286
287 if (parameterOut)
288 {
289 parameter.Direction = ParameterDirection.Output;
290 }
291 else
292 {
293 parameter.Direction = ParameterDirection.Input;
294 parameter.Value = CreateParameterValue(parameterObject);
295 }
296
297 return parameter;
298 }
189 299
190 private static readonly Dictionary<string, string> emptyDictionary = new Dictionary<string, string>(); 300 private static readonly Dictionary<string, string> emptyDictionary = new Dictionary<string, string>();
191 internal AutoClosingSqlCommand Query(string sql) 301 internal AutoClosingSqlCommand Query(string sql)
@@ -201,7 +311,7 @@ namespace OpenSim.Data.MSSQL
201 /// <returns>A Sql DB Command</returns> 311 /// <returns>A Sql DB Command</returns>
202 internal AutoClosingSqlCommand Query(string sql, Dictionary<string, string> parameters) 312 internal AutoClosingSqlCommand Query(string sql, Dictionary<string, string> parameters)
203 { 313 {
204 SqlCommand dbcommand = createConnection().CreateCommand(); 314 SqlCommand dbcommand = DatabaseConnection().CreateCommand();
205 dbcommand.CommandText = sql; 315 dbcommand.CommandText = sql;
206 foreach (KeyValuePair<string, string> param in parameters) 316 foreach (KeyValuePair<string, string> param in parameters)
207 { 317 {
@@ -211,8 +321,6 @@ namespace OpenSim.Data.MSSQL
211 return new AutoClosingSqlCommand(dbcommand); 321 return new AutoClosingSqlCommand(dbcommand);
212 } 322 }
213 323
214
215
216 /// <summary> 324 /// <summary>
217 /// Runs a database reader object and returns a region row 325 /// Runs a database reader object and returns a region row
218 /// </summary> 326 /// </summary>
diff --git a/OpenSim/Data/MSSQL/MSSQLMigration.cs b/OpenSim/Data/MSSQL/MSSQLMigration.cs
new file mode 100644
index 0000000..67fc606
--- /dev/null
+++ b/OpenSim/Data/MSSQL/MSSQLMigration.cs
@@ -0,0 +1,45 @@
1using System;
2using System.Collections.Generic;
3using System.Data;
4using System.Data.Common;
5using System.Reflection;
6using System.Text;
7
8namespace OpenSim.Data.MSSQL
9{
10 public class MSSQLMigration : Migration
11 {
12 public MSSQLMigration(DbConnection conn, Assembly assem, string type) : base(conn, assem, type)
13 {
14 }
15
16 public MSSQLMigration(DbConnection conn, Assembly assem, string subtype, string type) : base(conn, assem, subtype, type)
17 {
18 }
19
20 protected override int FindVersion(DbConnection conn, string type)
21 {
22 int version = 0;
23 using (DbCommand cmd = conn.CreateCommand())
24 {
25 try
26 {
27 cmd.CommandText = "select top 1 version from migrations where name = '" + type + "' order by version desc"; //Must be
28 using (IDataReader reader = cmd.ExecuteReader())
29 {
30 if (reader.Read())
31 {
32 version = Convert.ToInt32(reader["version"]);
33 }
34 reader.Close();
35 }
36 }
37 catch
38 {
39 // Something went wrong, so we're version 0
40 }
41 }
42 return version;
43 }
44 }
45}
diff --git a/OpenSim/Data/MSSQL/MSSQLRegionData.cs b/OpenSim/Data/MSSQL/MSSQLRegionData.cs
index 3f85fef..7af3e7e 100644
--- a/OpenSim/Data/MSSQL/MSSQLRegionData.cs
+++ b/OpenSim/Data/MSSQL/MSSQLRegionData.cs
@@ -42,225 +42,155 @@ namespace OpenSim.Data.MSSQL
42 /// <summary> 42 /// <summary>
43 /// A MSSQL Interface for the Region Server. 43 /// A MSSQL Interface for the Region Server.
44 /// </summary> 44 /// </summary>
45 public class MSSQLDataStore : IRegionDataStore 45 public class MSSQLRegionDataStore : IRegionDataStore
46 { 46 {
47 // private static FileSystemDataStore Instance = new FileSystemDataStore(); 47 // private static FileSystemDataStore Instance = new FileSystemDataStore();
48 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 48 private static readonly ILog _Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
49 49
50 private const string m_primSelect = "select * from prims"; 50 private MSSQLManager _Database;
51 private const string m_shapeSelect = "select * from primshapes"; 51
52 private const string m_itemsSelect = "select * from primitems"; 52// private const string _PrimSelect = "SELECT * FROM PRIMS WHERE RegionUUID = @RegionUUID AND (SceneGroupID LIKE @SceneGroupID OR UUID = @UUID)";
53 private const string m_terrainSelect = "select top 1 * from terrain"; 53// private const string _ShapeSelect = "SELECT * FROM PRIMSHAPES WHERE UUID in (SELECT UUID FROM PRIMS WHERE RegionUUID = @RegionUUID AND (SceneGroupID LIKE @SceneGroupID OR UUID = @UUID))";
54 private const string m_landSelect = "select * from land"; 54// private const string _ItemsSelect = "SELECT * FROM PRIMITEMS WHERE primID in (SELECT UUID FROM PRIMS WHERE RegionUUID = @RegionUUID AND (SceneGroupID LIKE @SceneGroupID OR UUID = @UUID))";
55 private const string m_landAccessListSelect = "select * from landaccesslist"; 55 private const string _PrimSelect = "SELECT * FROM PRIMS WHERE RegionUUID = @RegionUUID AND (SceneGroupID LIKE @SceneGroupID OR UUID IN (@UUID))";
56 56 private const string _ShapeSelect = "SELECT * FROM PRIMSHAPES WHERE UUID in (SELECT UUID FROM PRIMS WHERE RegionUUID = @RegionUUID AND (SceneGroupID LIKE @SceneGroupID OR UUID IN (@UUID)))";
57 private DataSet m_dataSet; 57 private const string _ItemsSelect = "SELECT * FROM PRIMITEMS WHERE primID in (SELECT UUID FROM PRIMS WHERE RegionUUID = @RegionUUID AND (SceneGroupID LIKE @SceneGroupID OR UUID IN (@UUID)))";
58 private SqlDataAdapter m_primDataAdapter; 58
59 private SqlDataAdapter m_shapeDataAdapter; 59 private DataSet _PrimsDataSet;
60 private SqlDataAdapter m_itemsDataAdapter; 60 private SqlDataAdapter _PrimDataAdapter;
61 private SqlConnection m_connection; 61 private SqlDataAdapter _ShapeDataAdapter;
62 private SqlDataAdapter m_terrainDataAdapter; 62 private SqlDataAdapter _ItemsDataAdapter;
63 private SqlDataAdapter m_landDataAdapter;
64 private SqlDataAdapter m_landAccessListDataAdapter;
65
66 private DataTable m_primTable;
67 private DataTable m_shapeTable;
68 private DataTable m_itemsTable;
69 private DataTable m_terrainTable;
70 private DataTable m_landTable;
71 private DataTable m_landAccessListTable;
72
73 /// <summary>Temporary attribute while this is experimental</summary>
74
75 /***********************************************************************
76 *
77 * Public Interface Functions
78 *
79 **********************************************************************/
80 63
81 /// <summary> 64 /// <summary>
82 /// see IRegionDataStore 65 /// Initialises the region datastore
83 /// </summary> 66 /// </summary>
84 /// <param name="connectionString"></param> 67 /// <param name="connectionString">The connection string.</param>
85 public void Initialise(string connectionString) 68 public void Initialise(string connectionString)
86 { 69 {
87 // Instance.Initialise("", true); 70 if (string.IsNullOrEmpty(connectionString))
88 71 {
89 m_dataSet = new DataSet(); 72 //Add MSSQLManager (dont know if we need it)
90 73 _Database = new MSSQLManager(connectionString);
91 m_log.Info("[REGION DB]: MSSql - connecting: " + connectionString); 74 }
92 m_connection = new SqlConnection(connectionString); 75 else
93 76 {
94 SqlCommand primSelectCmd = new SqlCommand(m_primSelect, m_connection); 77 IniFile iniFile = new IniFile("mssql_connection.ini");
95 m_primDataAdapter = new SqlDataAdapter(primSelectCmd); 78 string settingDataSource = iniFile.ParseFileReadValue("data_source");
96 79 string settingInitialCatalog = iniFile.ParseFileReadValue("initial_catalog");
97 SqlCommand shapeSelectCmd = new SqlCommand(m_shapeSelect, m_connection); 80 string settingPersistSecurityInfo = iniFile.ParseFileReadValue("persist_security_info");
98 m_shapeDataAdapter = new SqlDataAdapter(shapeSelectCmd); 81 string settingUserId = iniFile.ParseFileReadValue("user_id");
82 string settingPassword = iniFile.ParseFileReadValue("password");
83
84 _Database =
85 new MSSQLManager(settingDataSource, settingInitialCatalog, settingPersistSecurityInfo, settingUserId,
86 settingPassword);
87
88
89 SqlConnectionStringBuilder conBuilder = new SqlConnectionStringBuilder();
90 conBuilder.DataSource = settingDataSource;
91 conBuilder.InitialCatalog = settingInitialCatalog;
92 conBuilder.PersistSecurityInfo = Convert.ToBoolean(settingPersistSecurityInfo);
93 conBuilder.UserID = settingUserId;
94 conBuilder.Password = settingPassword;
95 conBuilder.ApplicationName = Assembly.GetEntryAssembly().Location;
96
97 connectionString = conBuilder.ToString();
98 }
99 99
100 SqlCommand itemsSelectCmd = new SqlCommand(m_itemsSelect, m_connection); 100 //Migration settings
101 m_itemsDataAdapter = new SqlDataAdapter(itemsSelectCmd); 101 Assembly assem = GetType().Assembly;
102 102
103 SqlCommand terrainSelectCmd = new SqlCommand(m_terrainSelect, m_connection); 103 using (SqlConnection connection = _Database.DatabaseConnection())
104 m_terrainDataAdapter = new SqlDataAdapter(terrainSelectCmd); 104 {
105 MSSQLMigration m = new MSSQLMigration(connection, assem, "RegionStore");
105 106
106 SqlCommand landSelectCmd = new SqlCommand(m_landSelect, m_connection); 107 m.Update();
107 m_landDataAdapter = new SqlDataAdapter(landSelectCmd);
108 108
109 SqlCommand landAccessListSelectCmd = new SqlCommand(m_landAccessListSelect, m_connection); 109 //Create Dataset. Not filled!!!
110 m_landAccessListDataAdapter = new SqlDataAdapter(landAccessListSelectCmd); 110 _PrimsDataSet = new DataSet("primsdata");
111 111
112 TestTables(m_connection); 112 using (SqlCommand primSelectCmd = new SqlCommand(_PrimSelect, connection))
113 {
114 primSelectCmd.Parameters.AddWithValue("@RegionUUID", "");
115 primSelectCmd.Parameters.AddWithValue("@SceneGroupID", "%");
116 primSelectCmd.Parameters.AddWithValue("@UUID", "");
117 _PrimDataAdapter = new SqlDataAdapter(primSelectCmd);
113 118
114 lock (m_dataSet) 119 DataTable primDataTable = new DataTable("prims");
115 { 120 _PrimDataAdapter.Fill(primDataTable);
116 m_primTable = createPrimTable(); 121 primDataTable.PrimaryKey = new DataColumn[] { primDataTable.Columns["UUID"] };
117 m_dataSet.Tables.Add(m_primTable); 122 _PrimsDataSet.Tables.Add(primDataTable);
118 setupPrimCommands(m_primDataAdapter, m_connection);
119 m_primDataAdapter.Fill(m_primTable);
120
121 m_shapeTable = createShapeTable();
122 m_dataSet.Tables.Add(m_shapeTable);
123 setupShapeCommands(m_shapeDataAdapter, m_connection);
124 m_shapeDataAdapter.Fill(m_shapeTable);
125
126 m_itemsTable = createItemsTable();
127 m_dataSet.Tables.Add(m_itemsTable);
128 SetupItemsCommands(m_itemsDataAdapter, m_connection);
129 m_itemsDataAdapter.Fill(m_itemsTable);
130
131 m_terrainTable = createTerrainTable();
132 m_dataSet.Tables.Add(m_terrainTable);
133 setupTerrainCommands(m_terrainDataAdapter, m_connection);
134 m_terrainDataAdapter.Fill(m_terrainTable);
135
136 m_landTable = createLandTable();
137 m_dataSet.Tables.Add(m_landTable);
138 setupLandCommands(m_landDataAdapter, m_connection);
139 m_landDataAdapter.Fill(m_landTable);
140
141 m_landAccessListTable = createLandAccessListTable();
142 m_dataSet.Tables.Add(m_landAccessListTable);
143 setupLandAccessCommands(m_landAccessListDataAdapter, m_connection);
144 m_landAccessListDataAdapter.Fill(m_landAccessListTable);
145 }
146 }
147 123
148 public void StoreRegionSettings(RegionSettings rs) 124 SetupCommands(_PrimDataAdapter); //, connection);
149 { 125 //SetupPrimCommands(_PrimDataAdapter, connection);
150 }
151 126
152 public RegionSettings LoadRegionSettings(LLUUID regionUUID) 127 primDataTable.Clear();
153 {
154 return null;
155 }
156
157 /// <summary>
158 ///
159 /// </summary>
160 /// <param name="obj"></param>
161 /// <param name="regionUUID"></param>
162 public void StoreObject(SceneObjectGroup obj, LLUUID regionUUID)
163 {
164 // Instance.StoreObject(obj, regionUUID);
165
166 lock (m_dataSet)
167 {
168 foreach (SceneObjectPart prim in obj.Children.Values)
169 {
170 if ((prim.GetEffectiveObjectFlags() & (uint)LLObject.ObjectFlags.Physics) == 0
171 && (prim.GetEffectiveObjectFlags() & (uint)LLObject.ObjectFlags.Temporary) == 0
172 && (prim.GetEffectiveObjectFlags() & (uint)LLObject.ObjectFlags.TemporaryOnRez) == 0)
173 {
174 //m_log.Info("[REGION DB]: Adding obj: " + obj.UUID + " to region: " + regionUUID);
175 addPrim(prim, obj.UUID, regionUUID);
176 }
177 else
178 {
179 // m_log.Info("[DATASTORE]: Ignoring Physical obj: " + obj.UUID + " in region: " + regionUUID);
180 }
181 } 128 }
182 }
183 129
184 Commit(); 130 using (SqlCommand shapeSelectCmd = new SqlCommand(_ShapeSelect, connection))
185 } 131 {
132 shapeSelectCmd.Parameters.AddWithValue("@RegionUUID", "");
133 shapeSelectCmd.Parameters.AddWithValue("@SceneGroupID", "%");
134 shapeSelectCmd.Parameters.AddWithValue("@UUID", "");
135 _ShapeDataAdapter = new SqlDataAdapter(shapeSelectCmd);
186 136
187 /// <summary> 137 DataTable shapeDataTable = new DataTable("primshapes");
188 /// 138 _ShapeDataAdapter.Fill(shapeDataTable);
189 /// </summary> 139 shapeDataTable.PrimaryKey = new DataColumn[] { shapeDataTable.Columns["UUID"] };
190 /// <param name="obj"></param> 140 _PrimsDataSet.Tables.Add(shapeDataTable);
191 /// <param name="regionUUID"></param>
192 public void RemoveObject(LLUUID obj, LLUUID regionUUID)
193 {
194 // Instance.RemoveObject(obj, regionUUID);
195 141
196 m_log.InfoFormat("[REGION DB]: Removing obj: {0} from region: {1}", obj.UUID, regionUUID); 142 SetupCommands(_ShapeDataAdapter); //, connection);
143 //SetupShapeCommands(_ShapeDataAdapter, connection);
197 144
198 DataTable prims = m_primTable; 145 shapeDataTable.Clear();
199 DataTable shapes = m_shapeTable; 146 }
200 147
201 string selectExp = "SceneGroupID = '" + obj.ToString() + "'"; 148 using (SqlCommand itemSelectCmd = new SqlCommand(_ItemsSelect, connection))
202 lock (m_dataSet)
203 {
204 foreach (DataRow row in prims.Select(selectExp))
205 { 149 {
206 // Remove shapes row 150 itemSelectCmd.Parameters.AddWithValue("@RegionUUID", "");
207 LLUUID uuid = new LLUUID((string)row["UUID"]); 151 itemSelectCmd.Parameters.AddWithValue("@SceneGroupID", "%");
152 itemSelectCmd.Parameters.AddWithValue("@UUID", "");
153 _ItemsDataAdapter = new SqlDataAdapter(itemSelectCmd);
208 154
209 DataRow shapeRow = shapes.Rows.Find(uuid.UUID); 155 DataTable itemsDataTable = new DataTable("primitems");
210 if (shapeRow != null) 156 _ItemsDataAdapter.Fill(itemsDataTable);
211 { 157 itemsDataTable.PrimaryKey = new DataColumn[] { itemsDataTable.Columns["itemID"] };
212 shapeRow.Delete(); 158 _PrimsDataSet.Tables.Add(itemsDataTable);
213 }
214 159
215 RemoveItems(new LLUUID((string)row["UUID"])); 160 SetupCommands(_ItemsDataAdapter); //, connection);
161 //SetupItemsCommands(_ItemsDataAdapter, connection);
216 162
217 // Remove prim row 163 itemsDataTable.Clear();
218 row.Delete();
219 } 164 }
220 }
221
222 Commit();
223 }
224
225 /// <summary>
226 /// Remove all persisted items of the given prim.
227 /// The caller must acquire the necessrary synchronization locks and commit or rollback changes.
228 /// </summary>
229 /// <param name="uuid">The item UUID</param>
230 private void RemoveItems(LLUUID uuid)
231 {
232 String sql = String.Format("primID = '{0}'", uuid);
233 DataRow[] itemRows = m_itemsTable.Select(sql);
234 165
235 foreach (DataRow itemRow in itemRows) 166 connection.Close();
236 {
237 itemRow.Delete();
238 } 167 }
168
169 //After this we have a empty fully configured DataSet.
239 } 170 }
240 171
241 /// <summary> 172 /// <summary>
242 /// Load persisted objects from region storage. 173 /// Loads the objects present in the region.
243 /// </summary> 174 /// </summary>
244 /// <param name="regionUUID">The region UUID</param> 175 /// <param name="regionUUID">The region UUID.</param>
176 /// <returns></returns>
245 public List<SceneObjectGroup> LoadObjects(LLUUID regionUUID) 177 public List<SceneObjectGroup> LoadObjects(LLUUID regionUUID)
246 { 178 {
247 // return Instance.LoadObjects(regionUUID);
248
249 Dictionary<LLUUID, SceneObjectGroup> createdObjects = new Dictionary<LLUUID, SceneObjectGroup>(); 179 Dictionary<LLUUID, SceneObjectGroup> createdObjects = new Dictionary<LLUUID, SceneObjectGroup>();
250 180
251 List<SceneObjectGroup> retvals = new List<SceneObjectGroup>(); 181 //Retrieve all values of current region
182 RetrievePrimsDataForRegion(regionUUID, LLUUID.Zero, "");
252 183
253 DataTable prims = m_primTable; 184 List<SceneObjectGroup> retvals = new List<SceneObjectGroup>();
254 DataTable shapes = m_shapeTable;
255 185
256 string byRegion = "RegionUUID = '" + regionUUID.ToString() + "'"; 186 DataTable prims = _PrimsDataSet.Tables["prims"];
257 string orderByParent = "ParentID ASC"; 187 DataTable shapes = _PrimsDataSet.Tables["primshapes"];
258 188
259 lock (m_dataSet) 189 lock (_PrimsDataSet)
260 { 190 {
261 DataRow[] primsForRegion = prims.Select(byRegion, orderByParent); 191 DataRow[] primsForRegion = prims.Select("", "ParentID ASC"); //.Select(byRegion, orderByParent);
262 m_log.Info("[REGION DB]: " + 192
263 "Loaded " + primsForRegion.Length + " prims for region: " + regionUUID); 193 _Log.Info("[REGION DB]: " + "Loaded " + primsForRegion.Length + " prims for region: " + regionUUID);
264 194
265 foreach (DataRow primRow in primsForRegion) 195 foreach (DataRow primRow in primsForRegion)
266 { 196 {
@@ -275,14 +205,14 @@ namespace OpenSim.Data.MSSQL
275 { 205 {
276 SceneObjectGroup group = new SceneObjectGroup(); 206 SceneObjectGroup group = new SceneObjectGroup();
277 207
278 DataRow shapeRow = shapes.Rows.Find(prim.UUID); 208 DataRow shapeRow = shapes.Rows.Find(prim.UUID.ToString());
279 if (shapeRow != null) 209 if (shapeRow != null)
280 { 210 {
281 prim.Shape = buildShape(shapeRow); 211 prim.Shape = buildShape(shapeRow);
282 } 212 }
283 else 213 else
284 { 214 {
285 m_log.Info( 215 _Log.Info(
286 "No shape found for prim in storage, so setting default box shape"); 216 "No shape found for prim in storage, so setting default box shape");
287 prim.Shape = PrimitiveBaseShape.Default; 217 prim.Shape = PrimitiveBaseShape.Default;
288 } 218 }
@@ -294,572 +224,712 @@ namespace OpenSim.Data.MSSQL
294 } 224 }
295 else 225 else
296 { 226 {
297 DataRow shapeRow = shapes.Rows.Find(prim.UUID); 227 DataRow shapeRow = shapes.Rows.Find(prim.UUID.ToString());
298 if (shapeRow != null) 228 if (shapeRow != null)
299 { 229 {
300 prim.Shape = buildShape(shapeRow); 230 prim.Shape = buildShape(shapeRow);
301 } 231 }
302 else 232 else
303 { 233 {
304 m_log.Info( 234 _Log.Info(
305 "No shape found for prim in storage, so setting default box shape"); 235 "No shape found for prim in storage, so setting default box shape");
306 prim.Shape = PrimitiveBaseShape.Default; 236 prim.Shape = PrimitiveBaseShape.Default;
307 } 237 }
308 createdObjects[new LLUUID(objID)].AddPart(prim); 238 createdObjects[new LLUUID(objID)].AddPart(prim);
309 } 239 }
310 240
311 LoadItems(prim); 241 LoadItems(prim);
312 } 242 }
313 catch (Exception e) 243 catch (Exception e)
314 { 244 {
315 m_log.Error("[DATASTORE]: Failed create prim object, exception and data follows"); 245 _Log.Error("[REGION DB]: Failed create prim object, exception and data follows");
316 m_log.Info("[DATASTORE]: " + e.ToString()); 246 _Log.Info("[REGION DB]: " + e.ToString());
317 foreach (DataColumn col in prims.Columns) 247 foreach (DataColumn col in prims.Columns)
318 { 248 {
319 m_log.Info("[DATASTORE]: Col: " + col.ColumnName + " => " + primRow[col]); 249 _Log.Info("[REGION DB]: Col: " + col.ColumnName + " => " + primRow[col]);
320 } 250 }
321 } 251 }
322 } 252 }
253
254 _PrimsDataSet.Tables["prims"].Clear();
255 _PrimsDataSet.Tables["primshapes"].Clear();
256 _PrimsDataSet.Tables["primitems"].Clear();
323 } 257 }
324 return retvals; 258 return retvals;
259
260 #region Experimental
261
262//
263// //Get all prims
264// string sql = "select * from prims where RegionUUID = @RegionUUID";
265//
266// using (AutoClosingSqlCommand cmdPrims = _Database.Query(sql))
267// {
268// cmdPrims.Parameters.AddWithValue("@RegionUUID", regionUUID.ToString());
269// using (SqlDataReader readerPrims = cmdPrims.ExecuteReader())
270// {
271// while (readerPrims.Read())
272// {
273// string uuid = (string)readerPrims["UUID"];
274// string objID = (string)readerPrims["SceneGroupID"];
275// SceneObjectPart prim = buildPrim(readerPrims);
276//
277// //Setting default shape, will change shape ltr
278// prim.Shape = PrimitiveBaseShape.Default;
279//
280// //Load inventory items of prim
281// //LoadItems(prim);
282//
283// if (uuid == objID)
284// {
285// SceneObjectGroup group = new SceneObjectGroup();
286//
287// group.AddPart(prim);
288// group.RootPart = prim;
289//
290// createdObjects.Add(group.UUID, group);
291// retvals.Add(group);
292// }
293// else
294// {
295// createdObjects[new LLUUID(objID)].AddPart(prim);
296// }
297// }
298// }
299// }
300// m_log.Info("[REGION DB]: Loaded " + retvals.Count + " prim objects for region: " + regionUUID);
301//
302// //Find all shapes related with prims
303// sql = "select * from primshapes";
304// using (AutoClosingSqlCommand cmdShapes = _Database.Query(sql))
305// {
306// using (SqlDataReader readerShapes = cmdShapes.ExecuteReader())
307// {
308// while (readerShapes.Read())
309// {
310// LLUUID UUID = new LLUUID((string) readerShapes["UUID"]);
311//
312// foreach (SceneObjectGroup objectGroup in createdObjects.Values)
313// {
314// if (objectGroup.Children.ContainsKey(UUID))
315// {
316// objectGroup.Children[UUID].Shape = buildShape(readerShapes);
317// }
318// }
319// }
320// }
321// }
322// return retvals;
323
324 #endregion
325 } 325 }
326 326
327 /// <summary> 327 public void StoreObject(SceneObjectGroup obj, LLUUID regionUUID)
328 /// Load in a prim's persisted inventory.
329 /// </summary>
330 /// <param name="prim"></param>
331 private void LoadItems(SceneObjectPart prim)
332 { 328 {
333 //m_log.InfoFormat("[DATASTORE]: Loading inventory for {0}, {1}", prim.Name, prim.UUID); 329 //Retrieve all values of current region, and current scene/or prims
334 330 //Build primID's, we use IN so I can select all prims from objgroup
335 DataTable dbItems = m_itemsTable; 331 string primID = "";
332 foreach (SceneObjectPart prim in obj.Children.Values)
333 {
334 primID += prim.UUID + "', '";
335 }
336 primID = primID.Remove(primID.LastIndexOf("',"));
336 337
337 String sql = String.Format("primID = '{0}'", prim.UUID.ToString()); 338 RetrievePrimsDataForRegion(regionUUID, obj.UUID, primID);
338 DataRow[] dbItemRows = dbItems.Select(sql);
339 339
340 IList<TaskInventoryItem> inventory = new List<TaskInventoryItem>(); 340 _Log.InfoFormat("[REGION DB]: Adding/Changing SceneObjectGroup: {0} to region: {1}, object has {2} prims.", obj.UUID, regionUUID, obj.Children.Count);
341 341
342 foreach (DataRow row in dbItemRows) 342 foreach (SceneObjectPart prim in obj.Children.Values)
343 { 343 {
344 TaskInventoryItem item = buildItem(row); 344 if ((prim.GetEffectiveObjectFlags() & (uint)LLObject.ObjectFlags.Physics) == 0
345 inventory.Add(item); 345 && (prim.GetEffectiveObjectFlags() & (uint)LLObject.ObjectFlags.Temporary) == 0
346 && (prim.GetEffectiveObjectFlags() & (uint)LLObject.ObjectFlags.TemporaryOnRez) == 0)
347 {
348 lock (_PrimsDataSet)
349 {
350 DataTable prims = _PrimsDataSet.Tables["prims"];
351 DataTable shapes = _PrimsDataSet.Tables["primshapes"];
346 352
347 //m_log.DebugFormat("[DATASTORE]: Restored item {0}, {1}", item.Name, item.ItemID); 353 DataRow primRow = prims.Rows.Find(prim.UUID.ToString());
354 if (primRow == null)
355 {
356 primRow = prims.NewRow();
357 fillPrimRow(primRow, prim, obj.UUID, regionUUID);
358 prims.Rows.Add(primRow);
359 }
360 else
361 {
362 fillPrimRow(primRow, prim, obj.UUID, regionUUID);
363 }
364
365 DataRow shapeRow = shapes.Rows.Find(prim.UUID.ToString());
366 if (shapeRow == null)
367 {
368 shapeRow = shapes.NewRow();
369 fillShapeRow(shapeRow, prim);
370 shapes.Rows.Add(shapeRow);
371 }
372 else
373 {
374 fillShapeRow(shapeRow, prim);
375 }
376 }
377 }
378 else
379 {
380 // m_log.Info("[DATASTORE]: Ignoring Physical obj: " + obj.UUID + " in region: " + regionUUID);
381 }
348 } 382 }
349 383
350 prim.RestoreInventoryItems(inventory); 384 //Save changes
385 CommitDataSet();
386 }
351 387
352 // XXX A nasty little hack to recover the folder id for the prim (which is currently stored in 388 /// <summary>
353 // every item). This data should really be stored in the prim table itself. 389 /// Removes a object from the database.
354 if (dbItemRows.Length > 0) 390 /// Meaning removing it from tables Prims, PrimShapes and PrimItems
391 /// </summary>
392 /// <param name="objectID">id of scenegroup</param>
393 /// <param name="regionUUID">regionUUID (is this used anyway</param>
394 public void RemoveObject(LLUUID objectID, LLUUID regionUUID)
395 {
396 _Log.InfoFormat("[REGION DB]: Removing obj: {0} from region: {1}", objectID, regionUUID);
397
398 //Remove from prims and primsitem table
399 string sqlPrims = string.Format("DELETE FROM PRIMS WHERE SceneGroupID = '{0}'", objectID);
400 string sqlPrimItems = string.Format("DELETE FROM PRIMITEMS WHERE primID in (SELECT UUID FROM PRIMS WHERE SceneGroupID = '{0}')", objectID);
401 string sqlPrimShapes = string.Format("DELETE FROM PRIMSHAPES WHERE uuid in (SELECT UUID FROM PRIMS WHERE SceneGroupID = '{0}')", objectID);
402
403 //Using the non transaction mode.
404 using (AutoClosingSqlCommand cmd = _Database.Query(sqlPrimShapes))
355 { 405 {
356 prim.FolderID = inventory[0].ParentID; 406 cmd.ExecuteNonQuery();
407
408 cmd.CommandText = sqlPrimItems;
409 cmd.ExecuteNonQuery();
410
411 cmd.CommandText = sqlPrims;
412 cmd.ExecuteNonQuery();
357 } 413 }
358 } 414 }
359 415
360 /// <summary> 416 /// <summary>
361 /// Store a terrain revision in region storage. 417 /// Store the inventory of a prim. Warning deletes everything first and then adds all again.
362 /// </summary> 418 /// </summary>
363 /// <param name="ter">HeightField data</param> 419 /// <param name="primID"></param>
364 /// <param name="regionID">Region UUID</param> 420 /// <param name="items"></param>
365 public void StoreTerrain(double[,] ter, LLUUID regionID) 421 public void StorePrimInventory(LLUUID primID, ICollection<TaskInventoryItem> items)
366 { 422 {
367 int revision = Util.UnixTimeSinceEpoch(); 423 _Log.InfoFormat("[REGION DB]: Persisting Prim Inventory with prim ID {0}", primID);
368 m_log.Info("[REGION DB]: Storing terrain revision r" + revision.ToString()); 424
425 //Statement from MySQL section!
426 // For now, we're just going to crudely remove all the previous inventory items
427 // no matter whether they have changed or not, and replace them with the current set.
369 428
370 // DataTable terrain = m_dataSet.Tables["terrain"]; 429 //Delete everything from PrimID
371 lock (m_dataSet) 430 //TODO add index on PrimID in DB, if not already exist
431 using (AutoClosingSqlCommand cmd = _Database.Query("DELETE PRIMITEMS WHERE primID = @primID"))
372 { 432 {
373 SqlCommand cmd = new SqlCommand("insert into terrain(RegionUUID, Revision, Heightfield)" + 433 cmd.Parameters.AddWithValue("@primID", primID.ToString());
374 " values(@RegionUUID, @Revision, @Heightfield)", m_connection); 434 cmd.ExecuteNonQuery();
375 using (cmd) 435 }
436
437 string sql =
438 "INSERT INTO [primitems] ([itemID],[primID],[assetID],[parentFolderID],[invType],[assetType],[name],[description],[creationDate],[creatorID],[ownerID],[lastOwnerID],[groupID],[nextPermissions],[currentPermissions],[basePermissions],[everyonePermissions],[groupPermissions],[flags]) VALUES (@itemID,@primID,@assetID,@parentFolderID,@invType,@assetType,@name,@description,@creationDate,@creatorID,@ownerID,@lastOwnerID,@groupID,@nextPermissions,@currentPermissions,@basePermissions,@everyonePermissions,@groupPermissions,@flags)";
439
440 using (AutoClosingSqlCommand cmd = _Database.Query(sql))
441 {
442 foreach (TaskInventoryItem newItem in items)
376 { 443 {
377 cmd.Parameters.Add(new SqlParameter("@RegionUUID", regionID.UUID)); 444 //
378 cmd.Parameters.Add(new SqlParameter("@Revision", revision)); 445 cmd.Parameters.AddRange(CreatePrimInventoryParameters(newItem));
379 cmd.Parameters.Add(new SqlParameter("@Heightfield", serializeTerrain(ter))); 446
380 cmd.ExecuteNonQuery(); 447 cmd.ExecuteNonQuery();
448
449 cmd.Parameters.Clear();
381 } 450 }
382 } 451 }
383 } 452 }
384 453
385 /// <summary> 454 /// <summary>
386 /// Load the latest terrain revision from region storage. 455 /// Loads the terrain map.
387 /// </summary> 456 /// </summary>
388 /// <param name="regionID">The Region UUID</param> 457 /// <param name="regionID">regionID.</param>
389 /// <returns>HeightField Data</returns> 458 /// <returns></returns>
390 public double[,] LoadTerrain(LLUUID regionID) 459 public double[,] LoadTerrain(LLUUID regionID)
391 { 460 {
392 double[,] terret = new double[256, 256]; 461 double[,] terrain = new double[256, 256];
393 terret.Initialize(); 462 terrain.Initialize();
394 463
395 SqlCommand cmd = new SqlCommand( 464 string sql = "select top 1 RegionUUID, Revision, Heightfield from terrain where RegionUUID = @RegionUUID order by Revision desc";
396 @"select top 1 RegionUUID, Revision, Heightfield from terrain
397 where RegionUUID=@RegionUUID order by Revision desc"
398 , m_connection);
399 465
400 // SqlParameter param = new SqlParameter(); 466 using (AutoClosingSqlCommand cmd = _Database.Query(sql))
401 cmd.Parameters.Add(new SqlParameter("@RegionUUID", regionID.UUID));
402
403 if (m_connection.State != ConnectionState.Open)
404 { 467 {
405 m_connection.Open(); 468 // MySqlParameter param = new MySqlParameter();
406 } 469 cmd.Parameters.AddWithValue("@RegionUUID", regionID.ToString());
407 470
408 using (SqlDataReader row = cmd.ExecuteReader()) 471 using (SqlDataReader reader = cmd.ExecuteReader())
409 {
410 int rev = 0;
411 if (row.Read())
412 { 472 {
413 MemoryStream str = new MemoryStream((byte[])row["Heightfield"]); 473 int rev = 0;
414 BinaryReader br = new BinaryReader(str); 474 if (reader.Read())
415 for (int x = 0; x < 256; x++)
416 { 475 {
417 for (int y = 0; y < 256; y++) 476 MemoryStream str = new MemoryStream((byte[])reader["Heightfield"]);
477 BinaryReader br = new BinaryReader(str);
478 for (int x = 0; x < 256; x++)
418 { 479 {
419 terret[x, y] = br.ReadDouble(); 480 for (int y = 0; y < 256; y++)
481 {
482 terrain[x, y] = br.ReadDouble();
483 }
420 } 484 }
485 rev = (int)reader["Revision"];
421 } 486 }
422 rev = (int)row["Revision"]; 487 else
423 } 488 {
424 else 489 _Log.Info("[REGION DB]: No terrain found for region");
425 { 490 return null;
426 m_log.Info("[REGION DB]: No terrain found for region"); 491 }
427 return null; 492 _Log.Info("[REGION DB]: Loaded terrain revision r" + rev);
428 } 493 }
429
430 m_log.Info("[REGION DB]: Loaded terrain revision r" + rev.ToString());
431 } 494 }
432 495
433 return terret; 496 return terrain;
434 } 497 }
435 498
436 /// <summary> 499 /// <summary>
437 /// 500 /// Stores the terrain map to DB.
438 /// </summary> 501 /// </summary>
439 /// <param name="globalID"></param> 502 /// <param name="terrain">terrain map data.</param>
440 public void RemoveLandObject(LLUUID globalID) 503 /// <param name="regionID">regionID.</param>
504 public void StoreTerrain(double[,] terrain, LLUUID regionID)
441 { 505 {
442 // Instance.RemoveLandObject(globalID); 506 int revision = Util.UnixTimeSinceEpoch();
443 507
444 lock (m_dataSet) 508 //Delete old terrain map
509 string sql = "delete from terrain where RegionUUID=@RegionUUID";
510 using (AutoClosingSqlCommand cmd = _Database.Query(sql))
445 { 511 {
446 using (SqlCommand cmd = new SqlCommand("delete from land where UUID=@UUID", m_connection)) 512 cmd.Parameters.AddWithValue("@RegionUUID", regionID.ToString());
447 { 513 cmd.ExecuteNonQuery();
448 cmd.Parameters.Add(new SqlParameter("@UUID", globalID.UUID)); 514 }
449 cmd.ExecuteNonQuery();
450 }
451 515
452 using ( 516 sql = "insert into terrain(RegionUUID, Revision, Heightfield)" +
453 SqlCommand cmd = new SqlCommand("delete from landaccesslist where LandUUID=@UUID", m_connection) 517 " values(@RegionUUID, @Revision, @Heightfield)";
454 ) 518
455 { 519 using (AutoClosingSqlCommand cmd = _Database.Query(sql))
456 cmd.Parameters.Add(new SqlParameter("@UUID", globalID.UUID)); 520 {
457 cmd.ExecuteNonQuery(); 521 cmd.Parameters.AddWithValue("@RegionUUID", regionID.ToString());
458 } 522 cmd.Parameters.AddWithValue("@Revision", revision);
523 cmd.Parameters.AddWithValue("@Heightfield", serializeTerrain(terrain));
524 cmd.ExecuteNonQuery();
459 } 525 }
526
527 _Log.Info("[REGION DB]: Stored terrain revision r" + revision);
460 } 528 }
461 529
462 /// <summary> 530 /// <summary>
463 /// 531 /// Loads all the land objects of a region.
464 /// </summary> 532 /// </summary>
465 /// <param name="parcel"></param> 533 /// <param name="regionUUID">The region UUID.</param>
466 public void StoreLandObject(ILandObject parcel) 534 /// <returns></returns>
535 public List<LandData> LoadLandObjects(LLUUID regionUUID)
467 { 536 {
468 lock (m_dataSet) 537 List<LandData> landDataForRegion = new List<LandData>();
538
539 string sql = "select * from land where RegionUUID = @RegionUUID";
540
541 //Retrieve all land data from region
542 using (AutoClosingSqlCommand cmdLandData = _Database.Query(sql))
469 { 543 {
470 DataTable land = m_landTable; 544 cmdLandData.Parameters.AddWithValue("@RegionUUID", regionUUID.ToString());
471 DataTable landaccesslist = m_landAccessListTable;
472 545
473 DataRow landRow = land.Rows.Find(parcel.landData.GlobalID.UUID); 546 using (SqlDataReader readerLandData = cmdLandData.ExecuteReader())
474 if (landRow == null)
475 {
476 landRow = land.NewRow();
477 fillLandRow(landRow, parcel.landData, parcel.regionUUID);
478 land.Rows.Add(landRow);
479 }
480 else
481 { 547 {
482 fillLandRow(landRow, parcel.landData, parcel.regionUUID); 548 while (readerLandData.Read())
483 } 549 {
550 LandData data = buildLandData(readerLandData);
484 551
485 using ( 552 }
486 SqlCommand cmd =
487 new SqlCommand("delete from landaccesslist where LandUUID=@LandUUID", m_connection))
488 {
489 cmd.Parameters.Add(new SqlParameter("@LandUUID", parcel.landData.GlobalID.UUID));
490 cmd.ExecuteNonQuery();
491 } 553 }
554 }
492 555
493 foreach (ParcelManager.ParcelAccessEntry entry in parcel.landData.ParcelAccessList) 556 //Retrieve all accesslist data for all landdata
557 foreach (LandData landData in landDataForRegion)
558 {
559 sql = "select * from landaccesslist where LandUUID = @LandUUID";
560 using (AutoClosingSqlCommand cmdAccessList = _Database.Query(sql))
494 { 561 {
495 DataRow newAccessRow = landaccesslist.NewRow(); 562 cmdAccessList.Parameters.AddWithValue("@LandUUID", landData.GlobalID);
496 fillLandAccessRow(newAccessRow, entry, parcel.landData.GlobalID); 563 using (SqlDataReader readerAccessList = cmdAccessList.ExecuteReader())
497 landaccesslist.Rows.Add(newAccessRow); 564 {
565 while (readerAccessList.Read())
566 {
567 landData.ParcelAccessList.Add(buildLandAccessData(readerAccessList));
568 }
569 }
498 } 570 }
499
500 } 571 }
501 Commit(); 572
573 //Return data
574 return landDataForRegion;
502 } 575 }
503 576
504 /// <summary> 577 /// <summary>
505 /// 578 /// Stores land object with landaccess list.
506 /// </summary> 579 /// </summary>
507 /// <param name="regionUUID">The region UUID</param> 580 /// <param name="parcel">parcel data.</param>
508 /// <returns></returns> 581 public void StoreLandObject(ILandObject parcel)
509 public List<LandData> LoadLandObjects(LLUUID regionUUID)
510 { 582 {
511 List<LandData> landDataForRegion = new List<LandData>(); 583 //As this is only one record in land table I just delete all and then add a new record.
512 lock (m_dataSet) 584 //As the delete landaccess is already in the mysql code
585
586 //Delete old values
587 RemoveLandObject(parcel.landData.GlobalID);
588
589 //Insert new values
590 string sql = @"INSERT INTO [land]
591([UUID],[RegionUUID],[LocalLandID],[Bitmap],[Name],[Description],[OwnerUUID],[IsGroupOwned],[Area],[AuctionID],[Category],[ClaimDate],[ClaimPrice],[GroupUUID],[SalePrice],[LandStatus],[LandFlags],[LandingType],[MediaAutoScale],[MediaTextureUUID],[MediaURL],[MusicURL],[PassHours],[PassPrice],[SnapshotUUID],[UserLocationX],[UserLocationY],[UserLocationZ],[UserLookAtX],[UserLookAtY],[UserLookAtZ],[AuthbuyerID])
592VALUES
593(@UUID,@RegionUUID,@LocalLandID,@Bitmap,@Name,@Description,@OwnerUUID,@IsGroupOwned,@Area,@AuctionID,@Category,@ClaimDate,@ClaimPrice,@GroupUUID,@SalePrice,@LandStatus,@LandFlags,@LandingType,@MediaAutoScale,@MediaTextureUUID,@MediaURL,@MusicURL,@PassHours,@PassPrice,@SnapshotUUID,@UserLocationX,@UserLocationY,@UserLocationZ,@UserLookAtX,@UserLookAtY,@UserLookAtZ,@AuthbuyerID)";
594
595 using (AutoClosingSqlCommand cmd = _Database.Query(sql))
513 { 596 {
514 DataTable land = m_landTable; 597 cmd.Parameters.AddRange(CreateLandParameters(parcel.landData, parcel.regionUUID));
515 DataTable landaccesslist = m_landAccessListTable; 598
516 string searchExp = "RegionUUID = '" + regionUUID.UUID + "'"; 599 cmd.ExecuteNonQuery();
517 DataRow[] rawDataForRegion = land.Select(searchExp); 600 }
518 foreach (DataRow rawDataLand in rawDataForRegion) 601
602 sql = "INSERT INTO [landaccesslist] ([LandUUID],[AccessUUID],[Flags]) VALUES (@LandUUID,@AccessUUID,@Flags)";
603
604 using (AutoClosingSqlCommand cmd = _Database.Query(sql))
605 {
606 foreach (ParcelManager.ParcelAccessEntry parcelAccessEntry in parcel.landData.ParcelAccessList)
519 { 607 {
520 LandData newLand = buildLandData(rawDataLand); 608 cmd.Parameters.AddRange(CreateLandAccessParameters(parcelAccessEntry, parcel.regionUUID));
521 string accessListSearchExp = "LandUUID = '" + newLand.GlobalID.UUID + "'"; 609
522 DataRow[] rawDataForLandAccessList = landaccesslist.Select(accessListSearchExp); 610 cmd.ExecuteNonQuery();
523 foreach (DataRow rawDataLandAccess in rawDataForLandAccessList)
524 {
525 newLand.ParcelAccessList.Add(buildLandAccessData(rawDataLandAccess));
526 }
527 611
528 landDataForRegion.Add(newLand); 612 cmd.Parameters.Clear();
529 } 613 }
530 } 614 }
531 return landDataForRegion;
532 } 615 }
533 616
534 /// <summary> 617 /// <summary>
535 /// Load (fetch?) the region banlist 618 /// Removes a land object from DB.
536 /// </summary> 619 /// </summary>
537 /// <param name="regionUUID">the region UUID</param> 620 /// <param name="globalID">UUID of landobject</param>
538 /// <returns>the banlist list</returns> 621 public void RemoveLandObject(LLUUID globalID)
539 public List<EstateBan> LoadRegionBanList(LLUUID regionUUID)
540 { 622 {
541 List<EstateBan> regionbanlist = new List<EstateBan>(); 623 using (AutoClosingSqlCommand cmd = _Database.Query("delete from land where UUID=@UUID"))
542 return regionbanlist; 624 {
625 cmd.Parameters.Add(_Database.CreateParameter("@UUID", globalID));
626 cmd.ExecuteNonQuery();
627 }
628
629 using (AutoClosingSqlCommand cmd = _Database.Query("delete from landaccesslist where LandUUID=@UUID"))
630 {
631 cmd.Parameters.Add(_Database.CreateParameter("@UUID", globalID));
632 cmd.ExecuteNonQuery();
633 }
543 } 634 }
544 635
545 /// <summary> 636 /// <summary>
546 /// STUB, add an item into region banlist 637 /// Loads the settings of a region.
547 /// </summary> 638 /// </summary>
548 /// <param name="item">the item</param> 639 /// <param name="regionUUID">The region UUID.</param>
549 public void AddToRegionBanlist(EstateBan item) 640 /// <returns></returns>
641 public RegionSettings LoadRegionSettings(LLUUID regionUUID)
550 { 642 {
643 string sql = "select * from regionsettings where regionUUID = @regionUUID";
644 RegionSettings regionSettings;
645 using (AutoClosingSqlCommand cmd = _Database.Query(sql))
646 {
647 cmd.Parameters.AddWithValue("@regionUUID", regionUUID.ToString());
648 using(SqlDataReader reader = cmd.ExecuteReader())
649 {
650 if (reader.Read())
651 {
652 regionSettings = buildRegionSettings(reader);
653 regionSettings.OnSave += StoreRegionSettings;
551 654
552 } 655 return regionSettings;
656 }
657 }
658 }
553 659
554 /// <summary> 660 //If comes here then there is now region setting for that region
555 /// STUB, remove an item from region banlist 661 regionSettings = new RegionSettings();
556 /// </summary> 662 regionSettings.RegionUUID = regionUUID;
557 /// <param name="item"></param> 663 regionSettings.OnSave += StoreRegionSettings;
558 public void RemoveFromRegionBanlist(EstateBan item)
559 {
560 664
665 //Store new values
666 StoreNewRegionSettings(regionSettings);
667
668 return regionSettings;
561 } 669 }
562 670
563 /// <summary> 671 /// <summary>
564 /// Commit 672 /// Store region settings, need to check if the check is really necesary. If we can make something for creating new region.
565 /// </summary> 673 /// </summary>
566 public void Commit() 674 /// <param name="regionSettings">region settings.</param>
675 public void StoreRegionSettings(RegionSettings regionSettings)
567 { 676 {
568 if (m_connection.State != ConnectionState.Open) 677 //Little check if regionUUID already exist in DB
678 string regionUUID = null;
679 using (AutoClosingSqlCommand cmd = _Database.Query("SELECT regionUUID FROM regionsettings WHERE regionUUID = @regionUUID"))
569 { 680 {
570 m_connection.Open(); 681 regionUUID = cmd.ExecuteScalar().ToString();
571 } 682 }
572 683
573 lock (m_dataSet) 684 if (string.IsNullOrEmpty(regionUUID))
574 { 685 {
575 // DisplayDataSet(m_dataSet, "Region DataSet"); 686 StoreNewRegionSettings(regionSettings);
576 687 }
577 m_primDataAdapter.Update(m_primTable); 688 else
578 m_shapeDataAdapter.Update(m_shapeTable); 689 {
579 690 //This method only updates region settings!!! First call LoadRegionSettings to create new region settings in DB
580 m_itemsDataAdapter.Update(m_itemsTable); 691 string sql =
581 692 @"UPDATE [regionsettings] SET [block_terraform] = @block_terraform ,[block_fly] = @block_fly ,[allow_damage] = @allow_damage
582 m_terrainDataAdapter.Update(m_terrainTable); 693,[restrict_pushing] = @restrict_pushing ,[allow_land_resell] = @allow_land_resell ,[allow_land_join_divide] = @allow_land_join_divide
583 m_landDataAdapter.Update(m_landTable); 694,[block_show_in_search] = @block_show_in_search ,[agent_limit] = @agent_limit ,[object_bonus] = @object_bonus ,[maturity] = @maturity
584 m_landAccessListDataAdapter.Update(m_landAccessListTable); 695,[disable_scripts] = @disable_scripts ,[disable_collisions] = @disable_collisions ,[disable_physics] = @disable_physics
696,[terrain_texture_1] = @terrain_texture_1 ,[terrain_texture_2] = @terrain_texture_2 ,[terrain_texture_3] = @terrain_texture_3
697,[terrain_texture_4] = @terrain_texture_4 ,[elevation_1_nw] = @elevation_1_nw ,[elevation_2_nw] = @elevation_2_nw
698,[elevation_1_ne] = @elevation_1_ne ,[elevation_2_ne] = @elevation_2_ne ,[elevation_1_se] = @elevation_1_se ,[elevation_2_se] = @elevation_2_se
699,[elevation_1_sw] = @elevation_1_sw ,[elevation_2_sw] = @elevation_2_sw ,[water_height] = @water_height ,[terrain_raise_limit] = @terrain_raise_limit
700,[terrain_lower_limit] = @terrain_lower_limit ,[use_estate_sun] = @use_estate_sun ,[fixed_sun] = @fixed_sun ,[sun_position] = @sun_position
701,[covenant] = @covenant ,[Sandbox] = @Sandbox WHERE [regionUUID] = @regionUUID";
702
703 using (AutoClosingSqlCommand cmd = _Database.Query(sql))
704 {
705 cmd.Parameters.AddRange(CreateRegionSettingParameters(regionSettings));
585 706
586 m_dataSet.AcceptChanges(); 707 cmd.ExecuteNonQuery();
708 }
587 } 709 }
588 } 710 }
589 711
590 /// <summary>
591 /// See <see cref="Commit"/>
592 /// </summary>
593 public void Shutdown() 712 public void Shutdown()
594 { 713 {
595 Commit(); 714 //Not used??
596 } 715 }
597 716
598 /*********************************************************************** 717 #region Private Methods
599 *
600 * Database Definition Functions
601 *
602 * This should be db agnostic as we define them in ADO.NET terms
603 *
604 **********************************************************************/
605
606 /// <summary>
607 ///
608 /// </summary>
609 /// <param name="dt"></param>
610 /// <param name="name"></param>
611 /// <param name="type"></param>
612 /// <returns></returns>
613 private static DataColumn createCol(DataTable dt, string name, Type type)
614 {
615 DataColumn col = new DataColumn(name, type);
616 dt.Columns.Add(col);
617 return col;
618 }
619 718
620 /// <summary> 719 /// <summary>
621 /// Create the "terrain" table 720 /// Load in a prim's persisted inventory.
622 /// </summary> 721 /// </summary>
623 /// <returns>the datatable</returns> 722 /// <param name="prim">The prim</param>
624 private static DataTable createTerrainTable() 723 private void LoadItems(SceneObjectPart prim)
625 { 724 {
626 DataTable terrain = new DataTable("terrain"); 725 DataTable dbItems = _PrimsDataSet.Tables["primitems"];
627 726
628 createCol(terrain, "RegionUUID", typeof(String)); 727 String sql = String.Format("primID = '{0}'", prim.UUID.ToString());
629 createCol(terrain, "Revision", typeof(Int32)); 728 DataRow[] dbItemRows = dbItems.Select(sql);
630 createCol(terrain, "Heightfield", typeof(Byte[]));
631
632 return terrain;
633 }
634 729
635 /// <summary> 730 IList<TaskInventoryItem> inventory = new List<TaskInventoryItem>();
636 /// Create the "prims" table
637 /// </summary>
638 /// <returns>the datatable</returns>
639 private static DataTable createPrimTable()
640 {
641 DataTable prims = new DataTable("prims");
642
643 createCol(prims, "UUID", typeof(String));
644 createCol(prims, "RegionUUID", typeof(String));
645 createCol(prims, "ParentID", typeof(Int32));
646 createCol(prims, "CreationDate", typeof(Int32));
647 createCol(prims, "Name", typeof(String));
648 createCol(prims, "SceneGroupID", typeof(String));
649 // various text fields
650 createCol(prims, "Text", typeof(String));
651 createCol(prims, "Description", typeof(String));
652 createCol(prims, "SitName", typeof(String));
653 createCol(prims, "TouchName", typeof(String));
654 // permissions
655 createCol(prims, "ObjectFlags", typeof(Int32));
656 createCol(prims, "CreatorID", typeof(String));
657 createCol(prims, "OwnerID", typeof(String));
658 createCol(prims, "GroupID", typeof(String));
659 createCol(prims, "LastOwnerID", typeof(String));
660 createCol(prims, "OwnerMask", typeof(Int32));
661 createCol(prims, "NextOwnerMask", typeof(Int32));
662 createCol(prims, "GroupMask", typeof(Int32));
663 createCol(prims, "EveryoneMask", typeof(Int32));
664 createCol(prims, "BaseMask", typeof(Int32));
665 // vectors
666 createCol(prims, "PositionX", typeof(Double));
667 createCol(prims, "PositionY", typeof(Double));
668 createCol(prims, "PositionZ", typeof(Double));
669 createCol(prims, "GroupPositionX", typeof(Double));
670 createCol(prims, "GroupPositionY", typeof(Double));
671 createCol(prims, "GroupPositionZ", typeof(Double));
672 createCol(prims, "VelocityX", typeof(Double));
673 createCol(prims, "VelocityY", typeof(Double));
674 createCol(prims, "VelocityZ", typeof(Double));
675 createCol(prims, "AngularVelocityX", typeof(Double));
676 createCol(prims, "AngularVelocityY", typeof(Double));
677 createCol(prims, "AngularVelocityZ", typeof(Double));
678 createCol(prims, "AccelerationX", typeof(Double));
679 createCol(prims, "AccelerationY", typeof(Double));
680 createCol(prims, "AccelerationZ", typeof(Double));
681 // quaternions
682 createCol(prims, "RotationX", typeof(Double));
683 createCol(prims, "RotationY", typeof(Double));
684 createCol(prims, "RotationZ", typeof(Double));
685 createCol(prims, "RotationW", typeof(Double));
686 731
687 // sit target 732 foreach (DataRow row in dbItemRows)
688 createCol(prims, "SitTargetOffsetX", typeof(Double)); 733 {
689 createCol(prims, "SitTargetOffsetY", typeof(Double)); 734 TaskInventoryItem item = buildItem(row);
690 createCol(prims, "SitTargetOffsetZ", typeof(Double)); 735 inventory.Add(item);
691 736
692 createCol(prims, "SitTargetOrientW", typeof(Double)); 737 //m_log.DebugFormat("[DATASTORE]: Restored item {0}, {1}", item.Name, item.ItemID);
693 createCol(prims, "SitTargetOrientX", typeof(Double)); 738 }
694 createCol(prims, "SitTargetOrientY", typeof(Double));
695 createCol(prims, "SitTargetOrientZ", typeof(Double));
696 739
697 // Add in contraints 740 prim.RestoreInventoryItems(inventory);
698 prims.PrimaryKey = new DataColumn[] { prims.Columns["UUID"] };
699 741
700 return prims; 742 // XXX A nasty little hack to recover the folder id for the prim (which is currently stored in
743 // every item). This data should really be stored in the prim table itself.
744 if (dbItemRows.Length > 0)
745 {
746 prim.FolderID = inventory[0].ParentID;
747 }
701 } 748 }
702 749
703 /// <summary> 750 /// <summary>
704 /// Create the "land" table 751 /// Serializes the terrain data for storage in DB.
705 /// </summary> 752 /// </summary>
706 /// <returns>the datatable</returns> 753 /// <param name="val">terrain data</param>
707 private static DataTable createLandTable() 754 /// <returns></returns>
755 private static Array serializeTerrain(double[,] val)
708 { 756 {
709 DataTable land = new DataTable("land"); 757 MemoryStream str = new MemoryStream(65536 * sizeof(double));
710 createCol(land, "UUID", typeof(String)); 758 BinaryWriter bw = new BinaryWriter(str);
711 createCol(land, "RegionUUID", typeof(String));
712 createCol(land, "LocalLandID", typeof(Int32));
713 759
714 // Bitmap is a byte[512] 760 // TODO: COMPATIBILITY - Add byte-order conversions
715 createCol(land, "Bitmap", typeof(Byte[])); 761 for (int x = 0; x < 256; x++)
716 762 for (int y = 0; y < 256; y++)
717 createCol(land, "Name", typeof(String)); 763 {
718 createCol(land, "Description", typeof(String)); 764 double height = val[x, y];
719 createCol(land, "OwnerUUID", typeof(String)); 765 if (height == 0.0)
720 createCol(land, "IsGroupOwned", typeof(Int32)); 766 height = double.Epsilon;
721 createCol(land, "Area", typeof(Int32)); 767
722 createCol(land, "AuctionID", typeof(Int32)); //Unemplemented 768 bw.Write(height);
723 createCol(land, "Category", typeof(Int32)); //Enum libsecondlife.Parcel.ParcelCategory 769 }
724 createCol(land, "ClaimDate", typeof(Int32)); 770
725 createCol(land, "ClaimPrice", typeof(Int32)); 771 return str.ToArray();
726 createCol(land, "GroupUUID", typeof(String));
727 createCol(land, "SalePrice", typeof(Int32));
728 createCol(land, "LandStatus", typeof(Int32)); //Enum. libsecondlife.Parcel.ParcelStatus
729 createCol(land, "LandFlags", typeof(Int32));
730 createCol(land, "LandingType", typeof(Int32));
731 createCol(land, "MediaAutoScale", typeof(Int32));
732 createCol(land, "MediaTextureUUID", typeof(String));
733 createCol(land, "MediaURL", typeof(String));
734 createCol(land, "MusicURL", typeof(String));
735 createCol(land, "PassHours", typeof(Double));
736 createCol(land, "PassPrice", typeof(Int32));
737 createCol(land, "SnapshotUUID", typeof(String));
738 createCol(land, "UserLocationX", typeof(Double));
739 createCol(land, "UserLocationY", typeof(Double));
740 createCol(land, "UserLocationZ", typeof(Double));
741 createCol(land, "UserLookAtX", typeof(Double));
742 createCol(land, "UserLookAtY", typeof(Double));
743 createCol(land, "UserLookAtZ", typeof(Double));
744
745 land.PrimaryKey = new DataColumn[] { land.Columns["UUID"] };
746
747 return land;
748 } 772 }
749 773
750 /// <summary> 774 /// <summary>
751 /// Create "landacceslist" table 775 /// Stores new regionsettings.
752 /// </summary> 776 /// </summary>
753 /// <returns>the datatable</returns> 777 /// <param name="regionSettings">The region settings.</param>
754 private static DataTable createLandAccessListTable() 778 private void StoreNewRegionSettings(RegionSettings regionSettings)
755 { 779 {
756 DataTable landaccess = new DataTable("landaccesslist"); 780 string sql = @"INSERT INTO [regionsettings]
757 createCol(landaccess, "LandUUID", typeof(String)); 781([regionUUID],[block_terraform],[block_fly],[allow_damage],[restrict_pushing],[allow_land_resell],[allow_land_join_divide],[block_show_in_search],[agent_limit],[object_bonus],[maturity],[disable_scripts],[disable_collisions],[disable_physics],[terrain_texture_1],[terrain_texture_2],[terrain_texture_3],[terrain_texture_4],[elevation_1_nw],[elevation_2_nw],[elevation_1_ne],[elevation_2_ne],[elevation_1_se],[elevation_2_se],[elevation_1_sw],[elevation_2_sw],[water_height],[terrain_raise_limit],[terrain_lower_limit],[use_estate_sun],[fixed_sun],[sun_position],[covenant],[Sandbox]) VALUES
758 createCol(landaccess, "AccessUUID", typeof(String)); 782(@regionUUID,@block_terraform,@block_fly,@allow_damage,@restrict_pushing,@allow_land_resell,@allow_land_join_divide,@block_show_in_search,@agent_limit,@object_bonus,@maturity,@disable_scripts,@disable_collisions,@disable_physics,@terrain_texture_1,@terrain_texture_2,@terrain_texture_3,@terrain_texture_4,@elevation_1_nw,@elevation_2_nw,@elevation_1_ne,@elevation_2_ne,@elevation_1_se,@elevation_2_se,@elevation_1_sw,@elevation_2_sw,@water_height,@terrain_raise_limit,@terrain_lower_limit,@use_estate_sun,@fixed_sun,@sun_position,@covenant,@Sandbox)";
759 createCol(landaccess, "Flags", typeof(Int32)); 783
784 using (AutoClosingSqlCommand cmd = _Database.Query(sql))
785 {
786 cmd.Parameters.AddRange(CreateRegionSettingParameters(regionSettings));
760 787
761 return landaccess; 788 cmd.ExecuteNonQuery();
789 }
762 } 790 }
763 791
792 #region Private DataRecord conversion methods
793
764 /// <summary> 794 /// <summary>
765 /// Create "primsshapes" table 795 /// Builds the region settings from a datarecod.
766 /// </summary> 796 /// </summary>
767 /// <returns>the datatable</returns> 797 /// <param name="row">datarecord with regionsettings.</param>
768 private static DataTable createShapeTable() 798 /// <returns></returns>
799 private static RegionSettings buildRegionSettings(IDataRecord row)
769 { 800 {
770 DataTable shapes = new DataTable("primshapes"); 801 //TODO change this is some more generic code so we doesnt have to change it every time a new field is added?
771 createCol(shapes, "UUID", typeof(String)); 802 RegionSettings newSettings = new RegionSettings();
772 // shape is an enum 803
773 createCol(shapes, "Shape", typeof(Int32)); 804 newSettings.RegionUUID = new LLUUID((string)row["regionUUID"]);
774 // vectors 805 newSettings.BlockTerraform = Convert.ToBoolean(row["block_terraform"]);
775 createCol(shapes, "ScaleX", typeof(Double)); 806 newSettings.AllowDamage = Convert.ToBoolean(row["allow_damage"]);
776 createCol(shapes, "ScaleY", typeof(Double)); 807 newSettings.BlockFly = Convert.ToBoolean(row["block_fly"]);
777 createCol(shapes, "ScaleZ", typeof(Double)); 808 newSettings.RestrictPushing = Convert.ToBoolean(row["restrict_pushing"]);
778 // paths 809 newSettings.AllowLandResell = Convert.ToBoolean(row["allow_land_resell"]);
779 createCol(shapes, "PCode", typeof(Int32)); 810 newSettings.AllowLandJoinDivide = Convert.ToBoolean(row["allow_land_join_divide"]);
780 createCol(shapes, "PathBegin", typeof(Int32)); 811 newSettings.BlockShowInSearch = Convert.ToBoolean(row["block_show_in_search"]);
781 createCol(shapes, "PathEnd", typeof(Int32)); 812 newSettings.AgentLimit = Convert.ToInt32(row["agent_limit"]);
782 createCol(shapes, "PathScaleX", typeof(Int32)); 813 newSettings.ObjectBonus = Convert.ToDouble(row["object_bonus"]);
783 createCol(shapes, "PathScaleY", typeof(Int32)); 814 newSettings.Maturity = Convert.ToInt32(row["maturity"]);
784 createCol(shapes, "PathShearX", typeof(Int32)); 815 newSettings.DisableScripts = Convert.ToBoolean(row["disable_scripts"]);
785 createCol(shapes, "PathShearY", typeof(Int32)); 816 newSettings.DisableCollisions = Convert.ToBoolean(row["disable_collisions"]);
786 createCol(shapes, "PathSkew", typeof(Int32)); 817 newSettings.DisablePhysics = Convert.ToBoolean(row["disable_physics"]);
787 createCol(shapes, "PathCurve", typeof(Int32)); 818 newSettings.TerrainTexture1 = new LLUUID((String)row["terrain_texture_1"]);
788 createCol(shapes, "PathRadiusOffset", typeof(Int32)); 819 newSettings.TerrainTexture2 = new LLUUID((String)row["terrain_texture_2"]);
789 createCol(shapes, "PathRevolutions", typeof(Int32)); 820 newSettings.TerrainTexture3 = new LLUUID((String)row["terrain_texture_3"]);
790 createCol(shapes, "PathTaperX", typeof(Int32)); 821 newSettings.TerrainTexture4 = new LLUUID((String)row["terrain_texture_4"]);
791 createCol(shapes, "PathTaperY", typeof(Int32)); 822 newSettings.Elevation1NW = Convert.ToDouble(row["elevation_1_nw"]);
792 createCol(shapes, "PathTwist", typeof(Int32)); 823 newSettings.Elevation2NW = Convert.ToDouble(row["elevation_2_nw"]);
793 createCol(shapes, "PathTwistBegin", typeof(Int32)); 824 newSettings.Elevation1NE = Convert.ToDouble(row["elevation_1_ne"]);
794 // profile 825 newSettings.Elevation2NE = Convert.ToDouble(row["elevation_2_ne"]);
795 createCol(shapes, "ProfileBegin", typeof(Int32)); 826 newSettings.Elevation1SE = Convert.ToDouble(row["elevation_1_se"]);
796 createCol(shapes, "ProfileEnd", typeof(Int32)); 827 newSettings.Elevation2SE = Convert.ToDouble(row["elevation_2_se"]);
797 createCol(shapes, "ProfileCurve", typeof(Int32)); 828 newSettings.Elevation1SW = Convert.ToDouble(row["elevation_1_sw"]);
798 createCol(shapes, "ProfileHollow", typeof(Int32)); 829 newSettings.Elevation2SW = Convert.ToDouble(row["elevation_2_sw"]);
799 createCol(shapes, "State", typeof(Int32)); 830 newSettings.WaterHeight = Convert.ToDouble(row["water_height"]);
800 // text TODO: this isn't right, but I'm not sure the right 831 newSettings.TerrainRaiseLimit = Convert.ToDouble(row["terrain_raise_limit"]);
801 // way to specify this as a blob atm 832 newSettings.TerrainLowerLimit = Convert.ToDouble(row["terrain_lower_limit"]);
802 createCol(shapes, "Texture", typeof(Byte[])); 833 newSettings.UseEstateSun = Convert.ToBoolean(row["use_estate_sun"]);
803 createCol(shapes, "ExtraParams", typeof(Byte[])); 834 newSettings.Sandbox = Convert.ToBoolean(row["sandbox"]);
804 835 newSettings.FixedSun = Convert.ToBoolean(row["fixed_sun"]);
805 shapes.PrimaryKey = new DataColumn[] { shapes.Columns["UUID"] }; 836 newSettings.SunPosition = Convert.ToDouble(row["sun_position"]);
806 837 newSettings.Covenant = new LLUUID((String)row["covenant"]);
807 return shapes; 838
839 return newSettings;
808 } 840 }
809 841
810 /// <summary> 842 /// <summary>
811 /// Create "primitems" table 843 /// Builds the land data from a datarecord.
812 /// </summary> 844 /// </summary>
813 /// <returns>the datatable</returns> 845 /// <param name="row">datarecord with land data</param>
814 private static DataTable createItemsTable() 846 /// <returns></returns>
847 private static LandData buildLandData(IDataRecord row)
815 { 848 {
816 DataTable items = new DataTable("primitems"); 849 LandData newData = new LandData();
817 850
818 createCol(items, "itemID", typeof(String)); 851 newData.GlobalID = new LLUUID((String)row["UUID"]);
819 createCol(items, "primID", typeof(String)); 852 newData.LocalID = Convert.ToInt32(row["LocalLandID"]);
820 createCol(items, "assetID", typeof(String)); 853
821 createCol(items, "parentFolderID", typeof(String)); 854 // Bitmap is a byte[512]
855 newData.Bitmap = (Byte[])row["Bitmap"];
856
857 newData.Name = (String)row["Name"];
858 newData.Description = (String)row["Description"];
859 newData.OwnerID = (String)row["OwnerUUID"];
860 newData.IsGroupOwned = Convert.ToBoolean(row["IsGroupOwned"]);
861 newData.Area = Convert.ToInt32(row["Area"]);
862 newData.AuctionID = Convert.ToUInt32(row["AuctionID"]); //Unemplemented
863 newData.Category = (Parcel.ParcelCategory)Convert.ToInt32(row["Category"]);
864 //Enum libsecondlife.Parcel.ParcelCategory
865 newData.ClaimDate = Convert.ToInt32(row["ClaimDate"]);
866 newData.ClaimPrice = Convert.ToInt32(row["ClaimPrice"]);
867 newData.GroupID = new LLUUID((String)row["GroupUUID"]);
868 newData.SalePrice = Convert.ToInt32(row["SalePrice"]);
869 newData.Status = (Parcel.ParcelStatus)Convert.ToInt32(row["LandStatus"]);
870 //Enum. libsecondlife.Parcel.ParcelStatus
871 newData.Flags = Convert.ToUInt32(row["LandFlags"]);
872 newData.LandingType = Convert.ToByte(row["LandingType"]);
873 newData.MediaAutoScale = Convert.ToByte(row["MediaAutoScale"]);
874 newData.MediaID = new LLUUID((String)row["MediaTextureUUID"]);
875 newData.MediaURL = (String)row["MediaURL"];
876 newData.MusicURL = (String)row["MusicURL"];
877 newData.PassHours = Convert.ToSingle(row["PassHours"]);
878 newData.PassPrice = Convert.ToInt32(row["PassPrice"]);
822 879
823 createCol(items, "invType", typeof(Int32)); 880 LLUUID authedbuyer;
824 createCol(items, "assetType", typeof(Int32)); 881 LLUUID snapshotID;
825 882
826 createCol(items, "name", typeof(String)); 883 if (LLUUID.TryParse((string)row["AuthBuyerID"], out authedbuyer))
827 createCol(items, "description", typeof(String)); 884 newData.AuthBuyerID = authedbuyer;
828 885
829 createCol(items, "creationDate", typeof(Int64)); 886 if (LLUUID.TryParse((string)row["SnapshotUUID"], out snapshotID))
830 createCol(items, "creatorID", typeof(String)); 887 newData.SnapshotID = snapshotID;
831 createCol(items, "ownerID", typeof(String));
832 createCol(items, "lastOwnerID", typeof(String));
833 createCol(items, "groupID", typeof(String));
834 888
835 createCol(items, "nextPermissions", typeof(Int32)); 889 try
836 createCol(items, "currentPermissions", typeof(Int32)); 890 {
837 createCol(items, "basePermissions", typeof(Int32)); 891 newData.UserLocation =
838 createCol(items, "everyonePermissions", typeof(Int32)); 892 new LLVector3(Convert.ToSingle(row["UserLocationX"]), Convert.ToSingle(row["UserLocationY"]),
839 createCol(items, "groupPermissions", typeof(Int32)); 893 Convert.ToSingle(row["UserLocationZ"]));
840// createCol(items, "flags", typeof(Int32)); 894 newData.UserLookAt =
895 new LLVector3(Convert.ToSingle(row["UserLookAtX"]), Convert.ToSingle(row["UserLookAtY"]),
896 Convert.ToSingle(row["UserLookAtZ"]));
897 }
898 catch (InvalidCastException)
899 {
900 newData.UserLocation = LLVector3.Zero;
901 newData.UserLookAt = LLVector3.Zero;
902 _Log.ErrorFormat("[PARCEL]: unable to get parcel telehub settings for {1}", newData.Name);
903 }
841 904
842 items.PrimaryKey = new DataColumn[] { items.Columns["itemID"] }; 905 newData.ParcelAccessList = new List<ParcelManager.ParcelAccessEntry>();
843 906
844 return items; 907 return newData;
845 } 908 }
846 909
847 /*********************************************************************** 910 /// <summary>
848 * 911 /// Builds the landaccess data from a data record.
849 * Convert between ADO.NET <=> OpenSim Objects 912 /// </summary>
850 * 913 /// <param name="row">datarecord with landaccess data</param>
851 * These should be database independant 914 /// <returns></returns>
852 * 915 private static ParcelManager.ParcelAccessEntry buildLandAccessData(IDataRecord row)
853 **********************************************************************/ 916 {
917 ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry();
918 entry.AgentID = new LLUUID((string)row["AccessUUID"]);
919 entry.Flags = (ParcelManager.AccessList)Convert.ToInt32(row["Flags"]);
920 entry.Time = new DateTime();
921 return entry;
922 }
854 923
855 /// <summary> 924 /// <summary>
856 /// 925 /// Builds the prim from a datarecord.
857 /// </summary> 926 /// </summary>
858 /// <param name="row"></param> 927 /// <param name="row">datarecord</param>
859 /// <returns></returns> 928 /// <returns></returns>
860 private SceneObjectPart buildPrim(DataRow row) 929 private static SceneObjectPart buildPrim(DataRow row)
861 { 930 {
862 SceneObjectPart prim = new SceneObjectPart(); 931 SceneObjectPart prim = new SceneObjectPart();
932
863 prim.UUID = new LLUUID((String)row["UUID"]); 933 prim.UUID = new LLUUID((String)row["UUID"]);
864 // explicit conversion of integers is required, which sort 934 // explicit conversion of integers is required, which sort
865 // of sucks. No idea if there is a shortcut here or not. 935 // of sucks. No idea if there is a shortcut here or not.
@@ -915,330 +985,73 @@ namespace OpenSim.Data.MSSQL
915 Convert.ToSingle(row["RotationZ"]), 985 Convert.ToSingle(row["RotationZ"]),
916 Convert.ToSingle(row["RotationW"]) 986 Convert.ToSingle(row["RotationW"])
917 ); 987 );
918 try 988 prim.SitTargetPositionLL = new LLVector3(
919 { 989 Convert.ToSingle(row["SitTargetOffsetX"]),
920 prim.SitTargetPositionLL = new LLVector3( 990 Convert.ToSingle(row["SitTargetOffsetY"]),
921 Convert.ToSingle(row["SitTargetOffsetX"]), 991 Convert.ToSingle(row["SitTargetOffsetZ"])
922 Convert.ToSingle(row["SitTargetOffsetY"]), 992 );
923 Convert.ToSingle(row["SitTargetOffsetZ"])); 993 prim.SitTargetOrientationLL = new LLQuaternion(
924 prim.SitTargetOrientationLL = new LLQuaternion( 994 Convert.ToSingle(row["SitTargetOrientX"]),
925 Convert.ToSingle( 995 Convert.ToSingle(row["SitTargetOrientY"]),
926 row["SitTargetOrientX"]), 996 Convert.ToSingle(row["SitTargetOrientZ"]),
927 Convert.ToSingle( 997 Convert.ToSingle(row["SitTargetOrientW"])
928 row["SitTargetOrientY"]), 998 );
929 Convert.ToSingle(
930 row["SitTargetOrientZ"]),
931 Convert.ToSingle(
932 row["SitTargetOrientW"]));
933 }
934 catch (InvalidCastException)
935 {
936 // Database table was created before we got here and now has null values :P
937
938 using (
939 SqlCommand cmd =
940 new SqlCommand(
941 "ALTER TABLE [prims] ADD COLUMN [SitTargetOffsetX] float NOT NULL default 0, ADD COLUMN [SitTargetOffsetY] float NOT NULL default 0, ADD COLUMN [SitTargetOffsetZ] float NOT NULL default 0, ADD COLUMN [SitTargetOrientW] float NOT NULL default 0, ADD COLUMN [SitTargetOrientX] float NOT NULL default 0, ADD COLUMN [SitTargetOrientY] float NOT NULL default 0, ADD COLUMN [SitTargetOrientZ] float NOT NULL default 0;",
942 m_connection))
943 {
944 cmd.ExecuteNonQuery();
945 }
946 }
947
948 return prim;
949 }
950
951 /// <summary>
952 /// Build a prim inventory item from the persisted data.
953 /// </summary>
954 /// <param name="row"></param>
955 /// <returns></returns>
956 private static TaskInventoryItem buildItem(DataRow row)
957 {
958 TaskInventoryItem taskItem = new TaskInventoryItem();
959
960 taskItem.ItemID = new LLUUID((String)row["itemID"]);
961 taskItem.ParentPartID = new LLUUID((String)row["primID"]);
962 taskItem.AssetID = new LLUUID((String)row["assetID"]);
963 taskItem.ParentID = new LLUUID((String)row["parentFolderID"]);
964
965 taskItem.InvType = Convert.ToInt32(row["invType"]);
966 taskItem.Type = Convert.ToInt32(row["assetType"]);
967
968 taskItem.Name = (String)row["name"];
969 taskItem.Description = (String)row["description"];
970 taskItem.CreationDate = Convert.ToUInt32(row["creationDate"]);
971 taskItem.CreatorID = new LLUUID((String)row["creatorID"]);
972 taskItem.OwnerID = new LLUUID((String)row["ownerID"]);
973 taskItem.LastOwnerID = new LLUUID((String)row["lastOwnerID"]);
974 taskItem.GroupID = new LLUUID((String)row["groupID"]);
975
976 taskItem.NextPermissions = Convert.ToUInt32(row["nextPermissions"]);
977 taskItem.CurrentPermissions = Convert.ToUInt32(row["currentPermissions"]);
978 taskItem.BasePermissions = Convert.ToUInt32(row["basePermissions"]);
979 taskItem.EveryonePermissions = Convert.ToUInt32(row["everyonePermissions"]);
980 taskItem.GroupPermissions = Convert.ToUInt32(row["groupPermissions"]);
981// taskItem.Flags = Convert.ToUInt32(row["flags"]);
982
983 return taskItem;
984 }
985
986 /// <summary>
987 ///
988 /// </summary>
989 /// <param name="row"></param>
990 /// <returns></returns>
991 private static LandData buildLandData(DataRow row)
992 {
993 LandData newData = new LandData();
994 999
995 newData.GlobalID = new LLUUID((String)row["UUID"]); 1000 prim.PayPrice[0] = Convert.ToInt32(row["PayPrice"]);
996 newData.LocalID = Convert.ToInt32(row["LocalLandID"]); 1001 prim.PayPrice[1] = Convert.ToInt32(row["PayButton1"]);
1002 prim.PayPrice[2] = Convert.ToInt32(row["PayButton2"]);
1003 prim.PayPrice[3] = Convert.ToInt32(row["PayButton3"]);
1004 prim.PayPrice[4] = Convert.ToInt32(row["PayButton4"]);
997 1005
998 // Bitmap is a byte[512] 1006 prim.Sound = new LLUUID(row["LoopedSound"].ToString());
999 newData.Bitmap = (Byte[])row["Bitmap"]; 1007 prim.SoundGain = Convert.ToSingle(row["LoopedSoundGain"]);
1008 prim.SoundFlags = 1; // If it's persisted at all, it's looped
1000 1009
1001 newData.Name = (String)row["Name"]; 1010 if (row["TextureAnimation"] != null && row["TextureAnimation"] != DBNull.Value)
1002 newData.Description = (String)row["Description"]; 1011 prim.TextureAnimation = (Byte[])row["TextureAnimation"];
1003 newData.OwnerID = (String)row["OwnerUUID"];
1004 newData.IsGroupOwned = Convert.ToBoolean(row["IsGroupOwned"]);
1005 newData.Area = Convert.ToInt32(row["Area"]);
1006 newData.AuctionID = Convert.ToUInt32(row["AuctionID"]); //Unemplemented
1007 newData.Category = (Parcel.ParcelCategory)Convert.ToInt32(row["Category"]);
1008 //Enum libsecondlife.Parcel.ParcelCategory
1009 newData.ClaimDate = Convert.ToInt32(row["ClaimDate"]);
1010 newData.ClaimPrice = Convert.ToInt32(row["ClaimPrice"]);
1011 newData.GroupID = new LLUUID((String)row["GroupUUID"]);
1012 newData.SalePrice = Convert.ToInt32(row["SalePrice"]);
1013 newData.Status = (Parcel.ParcelStatus)Convert.ToInt32(row["LandStatus"]);
1014 //Enum. libsecondlife.Parcel.ParcelStatus
1015 newData.Flags = Convert.ToUInt32(row["LandFlags"]);
1016 newData.LandingType = Convert.ToByte(row["LandingType"]);
1017 newData.MediaAutoScale = Convert.ToByte(row["MediaAutoScale"]);
1018 newData.MediaID = new LLUUID((String)row["MediaTextureUUID"]);
1019 newData.MediaURL = (String)row["MediaURL"];
1020 newData.MusicURL = (String)row["MusicURL"];
1021 newData.PassHours = Convert.ToSingle(row["PassHours"]);
1022 newData.PassPrice = Convert.ToInt32(row["PassPrice"]);
1023 newData.SnapshotID = (String)row["SnapshotUUID"];
1024
1025 newData.UserLocation =
1026 new LLVector3(Convert.ToSingle(row["UserLocationX"]), Convert.ToSingle(row["UserLocationY"]),
1027 Convert.ToSingle(row["UserLocationZ"]));
1028 newData.UserLookAt =
1029 new LLVector3(Convert.ToSingle(row["UserLookAtX"]), Convert.ToSingle(row["UserLookAtY"]),
1030 Convert.ToSingle(row["UserLookAtZ"]));
1031 newData.ParcelAccessList = new List<ParcelManager.ParcelAccessEntry>();
1032 1012
1033 return newData; 1013 prim.RotationalVelocity = new LLVector3(
1034 } 1014 Convert.ToSingle(row["OmegaX"]),
1035 1015 Convert.ToSingle(row["OmegaY"]),
1036 /// <summary> 1016 Convert.ToSingle(row["OmegaZ"])
1037 /// 1017 );
1038 /// </summary>
1039 /// <param name="row"></param>
1040 /// <returns></returns>
1041 private static ParcelManager.ParcelAccessEntry buildLandAccessData(DataRow row)
1042 {
1043 ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry();
1044 entry.AgentID = new LLUUID((string)row["AccessUUID"]);
1045 entry.Flags = (ParcelManager.AccessList)Convert.ToInt32(row["Flags"]);
1046 entry.Time = new DateTime();
1047 return entry;
1048 }
1049
1050 /// <summary>
1051 /// Serialize terrain HeightField
1052 /// </summary>
1053 /// <param name="val">the terrain heightfield</param>
1054 /// <returns></returns>
1055 private static Array serializeTerrain(double[,] val)
1056 {
1057 MemoryStream str = new MemoryStream(65536 * sizeof(double));
1058 BinaryWriter bw = new BinaryWriter(str);
1059 1018
1060 // TODO: COMPATIBILITY - Add byte-order conversions 1019 // TODO: Rotation
1061 for (int x = 0; x < 256; x++) 1020 // OmegaX, OmegaY, OmegaZ
1062 for (int y = 0; y < 256; y++)
1063 bw.Write(val[x, y]);
1064 1021
1065 return str.ToArray(); 1022 prim.SetCameraEyeOffset(new LLVector3(
1066 } 1023 Convert.ToSingle(row["CameraEyeOffsetX"]),
1024 Convert.ToSingle(row["CameraEyeOffsetY"]),
1025 Convert.ToSingle(row["CameraEyeOffsetZ"])
1026 ));
1067 1027
1068 /// <summary> 1028 prim.SetCameraAtOffset(new LLVector3(
1069 /// 1029 Convert.ToSingle(row["CameraAtOffsetX"]),
1070 /// </summary> 1030 Convert.ToSingle(row["CameraAtOffsetY"]),
1071 /// <param name="row"></param> 1031 Convert.ToSingle(row["CameraAtOffsetZ"])
1072 /// <param name="prim"></param> 1032 ));
1073 /// <param name="sceneGroupID"></param>
1074 /// <param name="regionUUID"></param>
1075 private void fillPrimRow(DataRow row, SceneObjectPart prim, LLUUID sceneGroupID, LLUUID regionUUID)
1076 {
1077 row["UUID"] = prim.UUID;
1078 row["RegionUUID"] = regionUUID;
1079 row["ParentID"] = prim.ParentID;
1080 row["CreationDate"] = prim.CreationDate;
1081 row["Name"] = prim.Name;
1082 row["SceneGroupID"] = sceneGroupID;
1083 // the UUID of the root part for this SceneObjectGroup
1084 // various text fields
1085 row["Text"] = prim.Text;
1086 row["Description"] = prim.Description;
1087 row["SitName"] = prim.SitName;
1088 row["TouchName"] = prim.TouchName;
1089 // permissions
1090 row["ObjectFlags"] = prim.ObjectFlags;
1091 row["CreatorID"] = prim.CreatorID;
1092 row["OwnerID"] = prim.OwnerID;
1093 row["GroupID"] = prim.GroupID;
1094 row["LastOwnerID"] = prim.LastOwnerID;
1095 row["OwnerMask"] = prim.OwnerMask;
1096 row["NextOwnerMask"] = prim.NextOwnerMask;
1097 row["GroupMask"] = prim.GroupMask;
1098 row["EveryoneMask"] = prim.EveryoneMask;
1099 row["BaseMask"] = prim.BaseMask;
1100 // vectors
1101 row["PositionX"] = prim.OffsetPosition.X;
1102 row["PositionY"] = prim.OffsetPosition.Y;
1103 row["PositionZ"] = prim.OffsetPosition.Z;
1104 row["GroupPositionX"] = prim.GroupPosition.X;
1105 row["GroupPositionY"] = prim.GroupPosition.Y;
1106 row["GroupPositionZ"] = prim.GroupPosition.Z;
1107 row["VelocityX"] = prim.Velocity.X;
1108 row["VelocityY"] = prim.Velocity.Y;
1109 row["VelocityZ"] = prim.Velocity.Z;
1110 row["AngularVelocityX"] = prim.AngularVelocity.X;
1111 row["AngularVelocityY"] = prim.AngularVelocity.Y;
1112 row["AngularVelocityZ"] = prim.AngularVelocity.Z;
1113 row["AccelerationX"] = prim.Acceleration.X;
1114 row["AccelerationY"] = prim.Acceleration.Y;
1115 row["AccelerationZ"] = prim.Acceleration.Z;
1116 // quaternions
1117 row["RotationX"] = prim.RotationOffset.X;
1118 row["RotationY"] = prim.RotationOffset.Y;
1119 row["RotationZ"] = prim.RotationOffset.Z;
1120 row["RotationW"] = prim.RotationOffset.W;
1121 1033
1122 try 1034 if (Convert.ToInt16(row["ForceMouselook"]) != 0)
1123 { 1035 prim.SetForceMouselook(true);
1124 // Sit target
1125 LLVector3 sitTargetPos = prim.SitTargetPositionLL;
1126 row["SitTargetOffsetX"] = sitTargetPos.X;
1127 row["SitTargetOffsetY"] = sitTargetPos.Y;
1128 row["SitTargetOffsetZ"] = sitTargetPos.Z;
1129
1130 LLQuaternion sitTargetOrient = prim.SitTargetOrientationLL;
1131 row["SitTargetOrientW"] = sitTargetOrient.W;
1132 row["SitTargetOrientX"] = sitTargetOrient.X;
1133 row["SitTargetOrientY"] = sitTargetOrient.Y;
1134 row["SitTargetOrientZ"] = sitTargetOrient.Z;
1135 }
1136 catch (Exception)
1137 {
1138 // Database table was created before we got here and needs to be created! :P
1139 1036
1140 using ( 1037 prim.ScriptAccessPin = Convert.ToInt32(row["ScriptAccessPin"]);
1141 SqlCommand cmd =
1142 new SqlCommand(
1143 "ALTER TABLE [prims] ADD COLUMN [SitTargetOffsetX] float NOT NULL default 0, ADD COLUMN [SitTargetOffsetY] float NOT NULL default 0, ADD COLUMN [SitTargetOffsetZ] float NOT NULL default 0, ADD COLUMN [SitTargetOrientW] float NOT NULL default 0, ADD COLUMN [SitTargetOrientX] float NOT NULL default 0, ADD COLUMN [SitTargetOrientY] float NOT NULL default 0, ADD COLUMN [SitTargetOrientZ] float NOT NULL default 0;",
1144 m_connection))
1145 {
1146 cmd.ExecuteNonQuery();
1147 }
1148 }
1149 }
1150 1038
1151 /// <summary> 1039 if (Convert.ToInt16(row["AllowedDrop"]) != 0)
1152 /// 1040 prim.AllowedDrop = true;
1153 /// </summary>
1154 /// <param name="row"></param>
1155 /// <param name="taskItem"></param>
1156 private static void fillItemRow(DataRow row, TaskInventoryItem taskItem)
1157 {
1158 row["itemID"] = taskItem.ItemID;
1159 row["primID"] = taskItem.ParentPartID;
1160 row["assetID"] = taskItem.AssetID;
1161 row["parentFolderID"] = taskItem.ParentID;
1162
1163 row["invType"] = taskItem.InvType;
1164 row["assetType"] = taskItem.Type;
1165
1166 row["name"] = taskItem.Name;
1167 row["description"] = taskItem.Description;
1168 row["creationDate"] = taskItem.CreationDate;
1169 row["creatorID"] = taskItem.CreatorID;
1170 row["ownerID"] = taskItem.OwnerID;
1171 row["lastOwnerID"] = taskItem.LastOwnerID;
1172 row["groupID"] = taskItem.GroupID;
1173 row["nextPermissions"] = taskItem.NextPermissions;
1174 row["currentPermissions"] = taskItem.CurrentPermissions;
1175 row["basePermissions"] = taskItem.BasePermissions;
1176 row["everyonePermissions"] = taskItem.EveryonePermissions;
1177 row["groupPermissions"] = taskItem.GroupPermissions;
1178// row["flags"] = taskItem.Flags;
1179 }
1180 1041
1181 /// <summary> 1042 if (Convert.ToInt16(row["DieAtEdge"]) != 0)
1182 /// 1043 prim.DIE_AT_EDGE = true;
1183 /// </summary>
1184 /// <param name="row"></param>
1185 /// <param name="land"></param>
1186 /// <param name="regionUUID"></param>
1187 private static void fillLandRow(DataRow row, LandData land, LLUUID regionUUID)
1188 {
1189 row["UUID"] = land.GlobalID.UUID;
1190 row["RegionUUID"] = regionUUID.UUID;
1191 row["LocalLandID"] = land.LocalID;
1192 1044
1193 // Bitmap is a byte[512] 1045 prim.SalePrice = Convert.ToInt32(row["SalePrice"]);
1194 row["Bitmap"] = land.Bitmap; 1046 prim.ObjectSaleType = Convert.ToByte(row["SaleType"]);
1195
1196 row["Name"] = land.Name;
1197 row["Description"] = land.Description;
1198 row["OwnerUUID"] = land.OwnerID.UUID;
1199 row["IsGroupOwned"] = land.IsGroupOwned;
1200 row["Area"] = land.Area;
1201 row["AuctionID"] = land.AuctionID; //Unemplemented
1202 row["Category"] = land.Category; //Enum libsecondlife.Parcel.ParcelCategory
1203 row["ClaimDate"] = land.ClaimDate;
1204 row["ClaimPrice"] = land.ClaimPrice;
1205 row["GroupUUID"] = land.GroupID.UUID;
1206 row["SalePrice"] = land.SalePrice;
1207 row["LandStatus"] = land.Status; //Enum. libsecondlife.Parcel.ParcelStatus
1208 row["LandFlags"] = land.Flags;
1209 row["LandingType"] = land.LandingType;
1210 row["MediaAutoScale"] = land.MediaAutoScale;
1211 row["MediaTextureUUID"] = land.MediaID.UUID;
1212 row["MediaURL"] = land.MediaURL;
1213 row["MusicURL"] = land.MusicURL;
1214 row["PassHours"] = land.PassHours;
1215 row["PassPrice"] = land.PassPrice;
1216 row["SnapshotUUID"] = land.SnapshotID.UUID;
1217 row["UserLocationX"] = land.UserLocation.X;
1218 row["UserLocationY"] = land.UserLocation.Y;
1219 row["UserLocationZ"] = land.UserLocation.Z;
1220 row["UserLookAtX"] = land.UserLookAt.X;
1221 row["UserLookAtY"] = land.UserLookAt.Y;
1222 row["UserLookAtZ"] = land.UserLookAt.Z;
1223 }
1224 1047
1225 /// <summary> 1048 return prim;
1226 ///
1227 /// </summary>
1228 /// <param name="row"></param>
1229 /// <param name="entry"></param>
1230 /// <param name="parcelID"></param>
1231 private static void fillLandAccessRow(DataRow row, ParcelManager.ParcelAccessEntry entry, LLUUID parcelID)
1232 {
1233 row["LandUUID"] = parcelID.UUID;
1234 row["AccessUUID"] = entry.AgentID.UUID;
1235 row["Flags"] = entry.Flags;
1236 } 1049 }
1237 1050
1238 /// <summary> 1051 /// <summary>
1239 /// 1052 /// Builds the prim shape from a datarecord.
1240 /// </summary> 1053 /// </summary>
1241 /// <param name="row"></param> 1054 /// <param name="row">The row.</param>
1242 /// <returns></returns> 1055 /// <returns></returns>
1243 private static PrimitiveBaseShape buildShape(DataRow row) 1056 private static PrimitiveBaseShape buildShape(DataRow row)
1244 { 1057 {
@@ -1269,572 +1082,445 @@ namespace OpenSim.Data.MSSQL
1269 s.ProfileEnd = Convert.ToUInt16(row["ProfileEnd"]); 1082 s.ProfileEnd = Convert.ToUInt16(row["ProfileEnd"]);
1270 s.ProfileCurve = Convert.ToByte(row["ProfileCurve"]); 1083 s.ProfileCurve = Convert.ToByte(row["ProfileCurve"]);
1271 s.ProfileHollow = Convert.ToUInt16(row["ProfileHollow"]); 1084 s.ProfileHollow = Convert.ToUInt16(row["ProfileHollow"]);
1272 s.State = Convert.ToByte(row["State"]);
1273 1085
1274 byte[] textureEntry = (byte[])row["Texture"]; 1086 byte[] textureEntry = (byte[])row["Texture"];
1275 s.TextureEntry = textureEntry; 1087 s.TextureEntry = textureEntry;
1276 1088
1277 s.ExtraParams = (byte[])row["ExtraParams"]; 1089 s.ExtraParams = (byte[])row["ExtraParams"];
1278 1090
1279 return s; 1091 try
1280 }
1281
1282 /// <summary>
1283 ///
1284 /// </summary>
1285 /// <param name="row"></param>
1286 /// <param name="prim"></param>
1287 private static void fillShapeRow(DataRow row, SceneObjectPart prim)
1288 {
1289 PrimitiveBaseShape s = prim.Shape;
1290 row["UUID"] = prim.UUID;
1291 // shape is an enum
1292 row["Shape"] = 0;
1293 // vectors
1294 row["ScaleX"] = s.Scale.X;
1295 row["ScaleY"] = s.Scale.Y;
1296 row["ScaleZ"] = s.Scale.Z;
1297 // paths
1298 row["PCode"] = s.PCode;
1299 row["PathBegin"] = s.PathBegin;
1300 row["PathEnd"] = s.PathEnd;
1301 row["PathScaleX"] = s.PathScaleX;
1302 row["PathScaleY"] = s.PathScaleY;
1303 row["PathShearX"] = s.PathShearX;
1304 row["PathShearY"] = s.PathShearY;
1305 row["PathSkew"] = s.PathSkew;
1306 row["PathCurve"] = s.PathCurve;
1307 row["PathRadiusOffset"] = s.PathRadiusOffset;
1308 row["PathRevolutions"] = s.PathRevolutions;
1309 row["PathTaperX"] = s.PathTaperX;
1310 row["PathTaperY"] = s.PathTaperY;
1311 row["PathTwist"] = s.PathTwist;
1312 row["PathTwistBegin"] = s.PathTwistBegin;
1313 // profile
1314 row["ProfileBegin"] = s.ProfileBegin;
1315 row["ProfileEnd"] = s.ProfileEnd;
1316 row["ProfileCurve"] = s.ProfileCurve;
1317 row["ProfileHollow"] = s.ProfileHollow;
1318 row["State"] = s.State;
1319 row["Texture"] = s.TextureEntry;
1320 row["ExtraParams"] = s.ExtraParams;
1321 }
1322
1323 /// <summary>
1324 ///
1325 /// </summary>
1326 /// <param name="prim"></param>
1327 /// <param name="sceneGroupID"></param>
1328 /// <param name="regionUUID"></param>
1329 private void addPrim(SceneObjectPart prim, LLUUID sceneGroupID, LLUUID regionUUID)
1330 {
1331 DataTable prims = m_dataSet.Tables["prims"];
1332 DataTable shapes = m_dataSet.Tables["primshapes"];
1333
1334 DataRow primRow = prims.Rows.Find(prim.UUID);
1335 if (primRow == null)
1336 { 1092 {
1337 primRow = prims.NewRow(); 1093 s.State = Convert.ToByte(row["State"]);
1338 fillPrimRow(primRow, prim, sceneGroupID, regionUUID);
1339 prims.Rows.Add(primRow);
1340 } 1094 }
1341 else 1095 catch (InvalidCastException)
1342 { 1096 {
1343 fillPrimRow(primRow, prim, sceneGroupID, regionUUID);
1344 } 1097 }
1345 1098
1346 DataRow shapeRow = shapes.Rows.Find(prim.UUID); 1099 return s;
1347 if (shapeRow == null)
1348 {
1349 shapeRow = shapes.NewRow();
1350 fillShapeRow(shapeRow, prim);
1351 shapes.Rows.Add(shapeRow);
1352 }
1353 else
1354 {
1355 fillShapeRow(shapeRow, prim);
1356 }
1357 } 1100 }
1358 1101
1359 /// <summary> 1102 /// <summary>
1360 /// See <see cref="IRegionDatastore"/> 1103 /// Build a prim inventory item from the persisted data.
1361 /// </summary> 1104 /// </summary>
1362 /// <param name="primID"></param> 1105 /// <param name="row"></param>
1363 /// <param name="items"></param> 1106 /// <returns></returns>
1364 public void StorePrimInventory(LLUUID primID, ICollection<TaskInventoryItem> items) 1107 private static TaskInventoryItem buildItem(DataRow row)
1365 { 1108 {
1366 m_log.InfoFormat("[REGION DB]: Persisting Prim Inventory with prim ID {0}", primID); 1109 TaskInventoryItem taskItem = new TaskInventoryItem();
1367
1368 // For now, we're just going to crudely remove all the previous inventory items
1369 // no matter whether they have changed or not, and replace them with the current set.
1370 lock (m_dataSet)
1371 {
1372 RemoveItems(primID);
1373 1110
1374 // repalce with current inventory details 1111 taskItem.ItemID = new LLUUID((String)row["itemID"]);
1375 foreach (TaskInventoryItem newItem in items) 1112 taskItem.ParentPartID = new LLUUID((String)row["primID"]);
1376 { 1113 taskItem.AssetID = new LLUUID((String)row["assetID"]);
1377 // m_log.InfoFormat( 1114 taskItem.ParentID = new LLUUID((String)row["parentFolderID"]);
1378 // "[REGION DB]: " + 1115
1379 // "Adding item {0}, {1} to prim ID {2}", 1116 taskItem.InvType = Convert.ToInt32(row["invType"]);
1380 // newItem.Name, newItem.ItemID, newItem.ParentPartID); 1117 taskItem.Type = Convert.ToInt32(row["assetType"]);
1381 1118
1382 DataRow newItemRow = m_itemsTable.NewRow(); 1119 taskItem.Name = (String)row["name"];
1383 fillItemRow(newItemRow, newItem); 1120 taskItem.Description = (String)row["description"];
1384 m_itemsTable.Rows.Add(newItemRow); 1121 taskItem.CreationDate = Convert.ToUInt32(row["creationDate"]);
1385 } 1122 taskItem.CreatorID = new LLUUID((String)row["creatorID"]);
1386 } 1123 taskItem.OwnerID = new LLUUID((String)row["ownerID"]);
1124 taskItem.LastOwnerID = new LLUUID((String)row["lastOwnerID"]);
1125 taskItem.GroupID = new LLUUID((String)row["groupID"]);
1126
1127 taskItem.NextPermissions = Convert.ToUInt32(row["nextPermissions"]);
1128 taskItem.CurrentPermissions = Convert.ToUInt32(row["currentPermissions"]);
1129 taskItem.BasePermissions = Convert.ToUInt32(row["basePermissions"]);
1130 taskItem.EveryonePermissions = Convert.ToUInt32(row["everyonePermissions"]);
1131 taskItem.GroupPermissions = Convert.ToUInt32(row["groupPermissions"]);
1132 taskItem.Flags = Convert.ToUInt32(row["flags"]);
1387 1133
1388 Commit(); 1134 return taskItem;
1389 } 1135 }
1390 1136
1391 /*********************************************************************** 1137 #endregion
1392 * 1138
1393 * SQL Statement Creation Functions 1139 #region Create parameters methods
1394 *
1395 * These functions create SQL statements for update, insert, and create.
1396 * They can probably be factored later to have a db independant
1397 * portion and a db specific portion
1398 *
1399 **********************************************************************/
1400 1140
1401 /// <summary> 1141 /// <summary>
1402 /// Create an Insert command 1142 /// Creates the prim inventory parameters.
1403 /// </summary> 1143 /// </summary>
1404 /// <param name="table"></param> 1144 /// <param name="taskItem">item in inventory.</param>
1405 /// <param name="dt"></param> 1145 /// <returns></returns>
1406 /// <returns>the sql command</returns> 1146 private SqlParameter[] CreatePrimInventoryParameters(TaskInventoryItem taskItem)
1407 private static SqlCommand createInsertCommand(string table, DataTable dt)
1408 { 1147 {
1409 /** 1148 SqlParameter[] parameters = new SqlParameter[19];
1410 * This is subtle enough to deserve some commentary. 1149
1411 * Instead of doing *lots* and *lots of hardcoded strings 1150 parameters[0] = _Database.CreateParameter("itemID", taskItem.ItemID);
1412 * for database definitions we'll use the fact that 1151 parameters[1] = _Database.CreateParameter("primID", taskItem.ParentPartID);
1413 * realistically all insert statements look like "insert 1152 parameters[2] = _Database.CreateParameter("assetID", taskItem.AssetID);
1414 * into A(b, c) values(:b, :c) on the parameterized query 1153 parameters[3] = _Database.CreateParameter("parentFolderID", taskItem.ParentID);
1415 * front. If we just have a list of b, c, etc... we can 1154
1416 * generate these strings instead of typing them out. 1155 parameters[4] = _Database.CreateParameter("invType", taskItem.InvType);
1417 */ 1156 parameters[5] = _Database.CreateParameter("assetType", taskItem.Type);
1418 string[] cols = new string[dt.Columns.Count]; 1157
1419 for (int i = 0; i < dt.Columns.Count; i++) 1158 parameters[6] = _Database.CreateParameter("name", taskItem.Name);
1420 { 1159 parameters[7] = _Database.CreateParameter("description", taskItem.Description);
1421 DataColumn col = dt.Columns[i]; 1160 parameters[8] = _Database.CreateParameter("creationDate", taskItem.CreationDate);
1422 cols[i] = col.ColumnName; 1161 parameters[9] = _Database.CreateParameter("creatorID", taskItem.CreatorID);
1423 } 1162 parameters[10] = _Database.CreateParameter("ownerID", taskItem.OwnerID);
1424 1163 parameters[11] = _Database.CreateParameter("lastOwnerID", taskItem.LastOwnerID);
1425 string sql = "insert into " + table + "("; 1164 parameters[12] = _Database.CreateParameter("groupID", taskItem.GroupID);
1426 sql += String.Join(", ", cols); 1165 parameters[13] = _Database.CreateParameter("nextPermissions", taskItem.NextPermissions);
1427 // important, the first ':' needs to be here, the rest get added in the join 1166 parameters[14] = _Database.CreateParameter("currentPermissions", taskItem.CurrentPermissions);
1428 sql += ") values (@"; 1167 parameters[15] = _Database.CreateParameter("basePermissions", taskItem.BasePermissions);
1429 sql += String.Join(", @", cols); 1168 parameters[16] = _Database.CreateParameter("everyonePermissions", taskItem.EveryonePermissions);
1430 sql += ")"; 1169 parameters[17] = _Database.CreateParameter("groupPermissions", taskItem.GroupPermissions);
1431 SqlCommand cmd = new SqlCommand(sql); 1170 parameters[18] = _Database.CreateParameter("flags", taskItem.Flags);
1432 1171
1433 // this provides the binding for all our parameters, so 1172 return parameters;
1434 // much less code than it used to be
1435 foreach (DataColumn col in dt.Columns)
1436 {
1437 cmd.Parameters.Add(createSqlParameter(col.ColumnName, col.DataType));
1438 }
1439 return cmd;
1440 } 1173 }
1441 1174
1442 /// <summary> 1175 /// <summary>
1443 /// Create an update command 1176 /// Creates the region setting parameters.
1444 /// </summary> 1177 /// </summary>
1445 /// <param name="table"></param> 1178 /// <param name="settings">regionsettings.</param>
1446 /// <param name="pk"></param> 1179 /// <returns></returns>
1447 /// <param name="dt"></param> 1180 private SqlParameter[] CreateRegionSettingParameters(RegionSettings settings)
1448 /// <returns>the sql command</returns>
1449 private static SqlCommand createUpdateCommand(string table, string pk, DataTable dt)
1450 { 1181 {
1451 string sql = "update " + table + " set "; 1182 SqlParameter[] parameters = new SqlParameter[34];
1452 string subsql = String.Empty; 1183
1453 foreach (DataColumn col in dt.Columns) 1184 parameters[0] = _Database.CreateParameter("regionUUID", settings.RegionUUID);
1454 { 1185 parameters[1] = _Database.CreateParameter("block_terraform", settings.BlockTerraform);
1455 if (subsql.Length > 0) 1186 parameters[2] = _Database.CreateParameter("block_fly", settings.BlockFly);
1456 { 1187 parameters[3] = _Database.CreateParameter("allow_damage", settings.AllowDamage);
1457 // a map function would rock so much here 1188 parameters[4] = _Database.CreateParameter("restrict_pushing", settings.RestrictPushing);
1458 subsql += ", "; 1189 parameters[5] = _Database.CreateParameter("allow_land_resell", settings.AllowLandResell);
1459 } 1190 parameters[6] = _Database.CreateParameter("allow_land_join_divide", settings.AllowLandJoinDivide);
1460 subsql += col.ColumnName + "= @" + col.ColumnName; 1191 parameters[7] = _Database.CreateParameter("block_show_in_search", settings.BlockShowInSearch);
1461 } 1192 parameters[8] = _Database.CreateParameter("agent_limit", settings.AgentLimit);
1462 sql += subsql; 1193 parameters[9] = _Database.CreateParameter("object_bonus", settings.ObjectBonus);
1463 sql += " where " + pk; 1194 parameters[10] = _Database.CreateParameter("maturity", settings.Maturity);
1464 SqlCommand cmd = new SqlCommand(sql); 1195 parameters[11] = _Database.CreateParameter("disable_scripts", settings.DisableScripts);
1465 1196 parameters[12] = _Database.CreateParameter("disable_collisions", settings.DisableCollisions);
1466 // this provides the binding for all our parameters, so 1197 parameters[13] = _Database.CreateParameter("disable_physics", settings.DisablePhysics);
1467 // much less code than it used to be 1198 parameters[14] = _Database.CreateParameter("terrain_texture_1", settings.TerrainTexture1);
1468 1199 parameters[15] = _Database.CreateParameter("terrain_texture_2", settings.TerrainTexture2);
1469 foreach (DataColumn col in dt.Columns) 1200 parameters[16] = _Database.CreateParameter("terrain_texture_3", settings.TerrainTexture3);
1470 { 1201 parameters[17] = _Database.CreateParameter("terrain_texture_4", settings.TerrainTexture4);
1471 cmd.Parameters.Add(createSqlParameter(col.ColumnName, col.DataType)); 1202 parameters[18] = _Database.CreateParameter("elevation_1_nw", settings.Elevation1NW);
1472 } 1203 parameters[19] = _Database.CreateParameter("elevation_2_nw", settings.Elevation2NW);
1473 return cmd; 1204 parameters[20] = _Database.CreateParameter("elevation_1_ne", settings.Elevation1NE);
1205 parameters[21] = _Database.CreateParameter("elevation_2_ne", settings.Elevation2NE);
1206 parameters[22] = _Database.CreateParameter("elevation_1_se", settings.Elevation1SE);
1207 parameters[23] = _Database.CreateParameter("elevation_2_se", settings.Elevation2SE);
1208 parameters[24] = _Database.CreateParameter("elevation_1_sw", settings.Elevation1SW);
1209 parameters[25] = _Database.CreateParameter("elevation_2_sw", settings.Elevation2SW);
1210 parameters[26] = _Database.CreateParameter("water_height", settings.WaterHeight);
1211 parameters[27] = _Database.CreateParameter("terrain_raise_limit", settings.TerrainRaiseLimit);
1212 parameters[28] = _Database.CreateParameter("terrain_lower_limit", settings.TerrainLowerLimit);
1213 parameters[29] = _Database.CreateParameter("use_estate_sun", settings.UseEstateSun);
1214 parameters[30] = _Database.CreateParameter("sandbox", settings.Sandbox);
1215 parameters[31] = _Database.CreateParameter("fixed_sun", settings.FixedSun);
1216 parameters[32] = _Database.CreateParameter("sun_position", settings.SunPosition);
1217 parameters[33] = _Database.CreateParameter("covenant", settings.Covenant);
1218
1219 return parameters;
1474 } 1220 }
1475 1221
1476 /// <summary> 1222 /// <summary>
1477 /// 1223 /// Creates the land parameters.
1478 /// </summary> 1224 /// </summary>
1479 /// <param name="dt"></param> 1225 /// <param name="land">land parameters.</param>
1226 /// <param name="regionUUID">region UUID.</param>
1480 /// <returns></returns> 1227 /// <returns></returns>
1481 private static string defineTable(DataTable dt) 1228 private SqlParameter[] CreateLandParameters(LandData land, LLUUID regionUUID)
1482 { 1229 {
1483 string sql = "create table " + dt.TableName + "("; 1230 SqlParameter[] parameters = new SqlParameter[32];
1484 string subsql = String.Empty;
1485 foreach (DataColumn col in dt.Columns)
1486 {
1487 if (subsql.Length > 0)
1488 {
1489 // a map function would rock so much here
1490 subsql += ",\n";
1491 }
1492 subsql += col.ColumnName + " " + MSSQLManager.SqlType(col.DataType);
1493 if (dt.PrimaryKey.Length > 0 && col == dt.PrimaryKey[0])
1494 {
1495 subsql += " primary key";
1496 }
1497 }
1498 sql += subsql;
1499 sql += ")";
1500 1231
1501 return sql; 1232 parameters[0] = _Database.CreateParameter("UUID", land.GlobalID);
1502 } 1233 parameters[1] = _Database.CreateParameter("RegionUUID", regionUUID);
1234 parameters[2] = _Database.CreateParameter("LocalLandID", land.LocalID);
1503 1235
1504 /*********************************************************************** 1236 // Bitmap is a byte[512]
1505 * 1237 parameters[3] = _Database.CreateParameter("Bitmap", land.Bitmap);
1506 * Database Binding functions 1238
1507 * 1239 parameters[4] = _Database.CreateParameter("Name", land.Name);
1508 * These will be db specific due to typing, and minor differences 1240 parameters[5] = _Database.CreateParameter("Description", land.Description);
1509 * in databases. 1241 parameters[6] = _Database.CreateParameter("OwnerUUID", land.OwnerID);
1510 * 1242 parameters[7] = _Database.CreateParameter("IsGroupOwned", land.IsGroupOwned);
1511 **********************************************************************/ 1243 parameters[8] = _Database.CreateParameter("Area", land.Area);
1512 1244 parameters[9] = _Database.CreateParameter("AuctionID", land.AuctionID); //Unemplemented
1513 ///<summary> 1245 parameters[10] = _Database.CreateParameter("Category", (int)land.Category); //Enum libsecondlife.Parcel.ParcelCategory
1514 /// <para> 1246 parameters[11] = _Database.CreateParameter("ClaimDate", land.ClaimDate);
1515 /// This is a convenience function that collapses 5 repetitive 1247 parameters[12] = _Database.CreateParameter("ClaimPrice", land.ClaimPrice);
1516 /// lines for defining SqlParameters to 2 parameters: 1248 parameters[13] = _Database.CreateParameter("GroupUUID", land.GroupID);
1517 /// column name and database type. 1249 parameters[14] = _Database.CreateParameter("SalePrice", land.SalePrice);
1518 /// </para> 1250 parameters[15] = _Database.CreateParameter("LandStatus", (int)land.Status); //Enum. libsecondlife.Parcel.ParcelStatus
1519 /// 1251 parameters[16] = _Database.CreateParameter("LandFlags", land.Flags);
1520 /// <para> 1252 parameters[17] = _Database.CreateParameter("LandingType", land.LandingType);
1521 /// It assumes certain conventions like :param as the param 1253 parameters[18] = _Database.CreateParameter("MediaAutoScale", land.MediaAutoScale);
1522 /// name to replace in parametrized queries, and that source 1254 parameters[19] = _Database.CreateParameter("MediaTextureUUID", land.MediaID);
1523 /// version is always current version, both of which are fine 1255 parameters[20] = _Database.CreateParameter("MediaURL", land.MediaURL);
1524 /// for us. 1256 parameters[21] = _Database.CreateParameter("MusicURL", land.MusicURL);
1525 /// </para> 1257 parameters[22] = _Database.CreateParameter("PassHours", land.PassHours);
1526 ///</summary> 1258 parameters[23] = _Database.CreateParameter("PassPrice", land.PassPrice);
1527 ///<returns>a built Sql parameter</returns> 1259 parameters[24] = _Database.CreateParameter("SnapshotUUID", land.SnapshotID);
1528 private static SqlParameter createSqlParameter(string name, Type type) 1260 parameters[25] = _Database.CreateParameter("UserLocationX", land.UserLocation.X);
1529 { 1261 parameters[26] = _Database.CreateParameter("UserLocationY", land.UserLocation.Y);
1530 SqlParameter param = new SqlParameter(); 1262 parameters[27] = _Database.CreateParameter("UserLocationZ", land.UserLocation.Z);
1531 param.ParameterName = "@" + name; 1263 parameters[28] = _Database.CreateParameter("UserLookAtX", land.UserLookAt.X);
1532 param.DbType = dbtypeFromType(type); 1264 parameters[29] = _Database.CreateParameter("UserLookAtY", land.UserLookAt.Y);
1533 param.SourceColumn = name; 1265 parameters[30] = _Database.CreateParameter("UserLookAtZ", land.UserLookAt.Z);
1534 param.SourceVersion = DataRowVersion.Current; 1266 parameters[31] = _Database.CreateParameter("AuthBuyerID", land.AuthBuyerID);
1535 return param; 1267
1268 return parameters;
1536 } 1269 }
1537 1270
1538 /// <summary> 1271 /// <summary>
1539 /// 1272 /// Creates the land access parameters.
1540 /// </summary> 1273 /// </summary>
1541 /// <param name="da"></param> 1274 /// <param name="parcelAccessEntry">parcel access entry.</param>
1542 /// <param name="conn"></param> 1275 /// <param name="parcelID">parcel ID.</param>
1543 private void setupPrimCommands(SqlDataAdapter da, SqlConnection conn) 1276 /// <returns></returns>
1277 private SqlParameter[] CreateLandAccessParameters(ParcelManager.ParcelAccessEntry parcelAccessEntry, LLUUID parcelID)
1544 { 1278 {
1545 da.InsertCommand = createInsertCommand("prims", m_dataSet.Tables["prims"]); 1279 SqlParameter[] parameters = new SqlParameter[3];
1546 da.InsertCommand.Connection = conn;
1547 1280
1548 da.UpdateCommand = createUpdateCommand("prims", "UUID=@UUID", m_dataSet.Tables["prims"]); 1281 parameters[0] = _Database.CreateParameter("LandUUID", parcelID);
1549 da.UpdateCommand.Connection = conn; 1282 parameters[1] = _Database.CreateParameter("AccessUUID", parcelAccessEntry.AgentID);
1283 parameters[2] = _Database.CreateParameter("Flags", parcelAccessEntry.Flags);
1550 1284
1551 SqlCommand delete = new SqlCommand("delete from prims where UUID = @UUID"); 1285 return parameters;
1552 delete.Parameters.Add(createSqlParameter("UUID", typeof(String)));
1553 delete.Connection = conn;
1554 da.DeleteCommand = delete;
1555 } 1286 }
1556 1287
1557 /// <summary> 1288 /// <summary>
1558 /// 1289 /// Fills/Updates the prim datarow.
1559 /// </summary> 1290 /// </summary>
1560 /// <param name="da"></param> 1291 /// <param name="row">datarow.</param>
1561 /// <param name="conn"></param> 1292 /// <param name="prim">prim data.</param>
1562 private void SetupItemsCommands(SqlDataAdapter da, SqlConnection conn) 1293 /// <param name="sceneGroupID">scenegroup ID.</param>
1294 /// <param name="regionUUID">regionUUID.</param>
1295 private static void fillPrimRow(DataRow row, SceneObjectPart prim, LLUUID sceneGroupID, LLUUID regionUUID)
1563 { 1296 {
1564 da.InsertCommand = createInsertCommand("primitems", m_itemsTable); 1297 row["UUID"] = prim.UUID.ToString();
1565 da.InsertCommand.Connection = conn; 1298 row["RegionUUID"] = regionUUID.ToString();
1299 row["ParentID"] = prim.ParentID;
1300 row["CreationDate"] = prim.CreationDate;
1301 row["Name"] = prim.Name;
1302 row["SceneGroupID"] = sceneGroupID.ToString();
1303 // the UUID of the root part for this SceneObjectGroup
1304 // various text fields
1305 row["Text"] = prim.Text;
1306 row["Description"] = prim.Description;
1307 row["SitName"] = prim.SitName;
1308 row["TouchName"] = prim.TouchName;
1309 // permissions
1310 row["ObjectFlags"] = prim.ObjectFlags;
1311 row["CreatorID"] = prim.CreatorID.ToString();
1312 row["OwnerID"] = prim.OwnerID.ToString();
1313 row["GroupID"] = prim.GroupID.ToString();
1314 row["LastOwnerID"] = prim.LastOwnerID.ToString();
1315 row["OwnerMask"] = prim.OwnerMask;
1316 row["NextOwnerMask"] = prim.NextOwnerMask;
1317 row["GroupMask"] = prim.GroupMask;
1318 row["EveryoneMask"] = prim.EveryoneMask;
1319 row["BaseMask"] = prim.BaseMask;
1320 // vectors
1321 row["PositionX"] = prim.OffsetPosition.X;
1322 row["PositionY"] = prim.OffsetPosition.Y;
1323 row["PositionZ"] = prim.OffsetPosition.Z;
1324 row["GroupPositionX"] = prim.GroupPosition.X;
1325 row["GroupPositionY"] = prim.GroupPosition.Y;
1326 row["GroupPositionZ"] = prim.GroupPosition.Z;
1327 row["VelocityX"] = prim.Velocity.X;
1328 row["VelocityY"] = prim.Velocity.Y;
1329 row["VelocityZ"] = prim.Velocity.Z;
1330 row["AngularVelocityX"] = prim.AngularVelocity.X;
1331 row["AngularVelocityY"] = prim.AngularVelocity.Y;
1332 row["AngularVelocityZ"] = prim.AngularVelocity.Z;
1333 row["AccelerationX"] = prim.Acceleration.X;
1334 row["AccelerationY"] = prim.Acceleration.Y;
1335 row["AccelerationZ"] = prim.Acceleration.Z;
1336 // quaternions
1337 row["RotationX"] = prim.RotationOffset.X;
1338 row["RotationY"] = prim.RotationOffset.Y;
1339 row["RotationZ"] = prim.RotationOffset.Z;
1340 row["RotationW"] = prim.RotationOffset.W;
1341
1342 // Sit target
1343 LLVector3 sitTargetPos = prim.SitTargetPositionLL;
1344 row["SitTargetOffsetX"] = sitTargetPos.X;
1345 row["SitTargetOffsetY"] = sitTargetPos.Y;
1346 row["SitTargetOffsetZ"] = sitTargetPos.Z;
1347
1348 LLQuaternion sitTargetOrient = prim.SitTargetOrientationLL;
1349 row["SitTargetOrientW"] = sitTargetOrient.W;
1350 row["SitTargetOrientX"] = sitTargetOrient.X;
1351 row["SitTargetOrientY"] = sitTargetOrient.Y;
1352 row["SitTargetOrientZ"] = sitTargetOrient.Z;
1353
1354 row["PayPrice"] = prim.PayPrice[0];
1355 row["PayButton1"] = prim.PayPrice[1];
1356 row["PayButton2"] = prim.PayPrice[2];
1357 row["PayButton3"] = prim.PayPrice[3];
1358 row["PayButton4"] = prim.PayPrice[4];
1359
1360 if ((prim.SoundFlags & 1) != 0) // Looped
1361 {
1362 row["LoopedSound"] = prim.Sound.ToString();
1363 row["LoopedSoundGain"] = prim.SoundGain;
1364 }
1365 else
1366 {
1367 row["LoopedSound"] = LLUUID.Zero;
1368 row["LoopedSoundGain"] = 0.0f;
1369 }
1566 1370
1567 da.UpdateCommand = createUpdateCommand("primitems", "itemID = @itemID", m_itemsTable); 1371 row["TextureAnimation"] = prim.TextureAnimation;
1568 da.UpdateCommand.Connection = conn;
1569 1372
1570 SqlCommand delete = new SqlCommand("delete from primitems where itemID = @itemID"); 1373 row["OmegaX"] = prim.RotationalVelocity.X;
1571 delete.Parameters.Add(createSqlParameter("itemID", typeof(String))); 1374 row["OmegaY"] = prim.RotationalVelocity.Y;
1572 delete.Connection = conn; 1375 row["OmegaZ"] = prim.RotationalVelocity.Z;
1573 da.DeleteCommand = delete;
1574 }
1575 1376
1576 /// <summary> 1377 row["CameraEyeOffsetX"] = prim.GetCameraEyeOffset().X;
1577 /// 1378 row["CameraEyeOffsetY"] = prim.GetCameraEyeOffset().Y;
1578 /// </summary> 1379 row["CameraEyeOffsetZ"] = prim.GetCameraEyeOffset().Z;
1579 /// <param name="da"></param>
1580 /// <param name="conn"></param>
1581 private void setupTerrainCommands(SqlDataAdapter da, SqlConnection conn)
1582 {
1583 da.InsertCommand = createInsertCommand("terrain", m_dataSet.Tables["terrain"]);
1584 da.InsertCommand.Connection = conn;
1585 }
1586 1380
1587 /// <summary> 1381 row["CameraAtOffsetX"] = prim.GetCameraAtOffset().X;
1588 /// 1382 row["CameraAtOffsetY"] = prim.GetCameraAtOffset().Y;
1589 /// </summary> 1383 row["CameraAtOffsetZ"] = prim.GetCameraAtOffset().Z;
1590 /// <param name="da"></param>
1591 /// <param name="conn"></param>
1592 private void setupLandCommands(SqlDataAdapter da, SqlConnection conn)
1593 {
1594 da.InsertCommand = createInsertCommand("land", m_dataSet.Tables["land"]);
1595 da.InsertCommand.Connection = conn;
1596 1384
1597 da.UpdateCommand = createUpdateCommand("land", "UUID=@UUID", m_dataSet.Tables["land"]); 1385 if (prim.GetForceMouselook())
1598 da.UpdateCommand.Connection = conn; 1386 row["ForceMouselook"] = 1;
1599 } 1387 else
1388 row["ForceMouselook"] = 0;
1600 1389
1601 /// <summary> 1390 row["ScriptAccessPin"] = prim.ScriptAccessPin;
1602 ///
1603 /// </summary>
1604 /// <param name="da"></param>
1605 /// <param name="conn"></param>
1606 private void setupLandAccessCommands(SqlDataAdapter da, SqlConnection conn)
1607 {
1608 da.InsertCommand = createInsertCommand("landaccesslist", m_dataSet.Tables["landaccesslist"]);
1609 da.InsertCommand.Connection = conn;
1610 }
1611 1391
1612 /// <summary> 1392 if (prim.AllowedDrop)
1613 /// 1393 row["AllowedDrop"] = 1;
1614 /// </summary> 1394 else
1615 /// <param name="da"></param> 1395 row["AllowedDrop"] = 0;
1616 /// <param name="conn"></param>
1617 private void setupShapeCommands(SqlDataAdapter da, SqlConnection conn)
1618 {
1619 da.InsertCommand = createInsertCommand("primshapes", m_dataSet.Tables["primshapes"]);
1620 da.InsertCommand.Connection = conn;
1621 1396
1622 da.UpdateCommand = createUpdateCommand("primshapes", "UUID=@UUID", m_dataSet.Tables["primshapes"]); 1397 if (prim.DIE_AT_EDGE)
1623 da.UpdateCommand.Connection = conn; 1398 row["DieAtEdge"] = 1;
1399 else
1400 row["DieAtEdge"] = 0;
1624 1401
1625 SqlCommand delete = new SqlCommand("delete from primshapes where UUID = @UUID"); 1402 row["SalePrice"] = prim.SalePrice;
1626 delete.Parameters.Add(createSqlParameter("UUID", typeof(String))); 1403 row["SaleType"] = Convert.ToInt16(prim.ObjectSaleType);
1627 delete.Connection = conn;
1628 da.DeleteCommand = delete;
1629 } 1404 }
1630 1405
1631 /// <summary> 1406 /// <summary>
1632 /// 1407 /// Fills/Updates the shape datarow.
1633 /// </summary> 1408 /// </summary>
1634 /// <param name="conn"></param> 1409 /// <param name="row">datarow to fill/update.</param>
1635 private static void InitDB(SqlConnection conn) 1410 /// <param name="prim">prim shape data.</param>
1411 private static void fillShapeRow(DataRow row, SceneObjectPart prim)
1636 { 1412 {
1637 string createPrims = defineTable(createPrimTable()); 1413 PrimitiveBaseShape s = prim.Shape;
1638 string createShapes = defineTable(createShapeTable()); 1414 row["UUID"] = prim.UUID.ToString();
1639 string createItems = defineTable(createItemsTable()); 1415 // shape is an enum
1640 string createTerrain = defineTable(createTerrainTable()); 1416 row["Shape"] = 0;
1641 string createLand = defineTable(createLandTable()); 1417 // vectors
1642 string createLandAccessList = defineTable(createLandAccessListTable()); 1418 row["ScaleX"] = s.Scale.X;
1643 1419 row["ScaleY"] = s.Scale.Y;
1644 SqlCommand pcmd = new SqlCommand(createPrims, conn); 1420 row["ScaleZ"] = s.Scale.Z;
1645 SqlCommand scmd = new SqlCommand(createShapes, conn); 1421 // paths
1646 SqlCommand icmd = new SqlCommand(createItems, conn); 1422 row["PCode"] = s.PCode;
1647 SqlCommand tcmd = new SqlCommand(createTerrain, conn); 1423 row["PathBegin"] = s.PathBegin;
1648 SqlCommand lcmd = new SqlCommand(createLand, conn); 1424 row["PathEnd"] = s.PathEnd;
1649 SqlCommand lalcmd = new SqlCommand(createLandAccessList, conn); 1425 row["PathScaleX"] = s.PathScaleX;
1650 1426 row["PathScaleY"] = s.PathScaleY;
1651 conn.Open(); 1427 row["PathShearX"] = s.PathShearX;
1652 try 1428 row["PathShearY"] = s.PathShearY;
1653 { 1429 row["PathSkew"] = s.PathSkew;
1654 pcmd.ExecuteNonQuery(); 1430 row["PathCurve"] = s.PathCurve;
1655 } 1431 row["PathRadiusOffset"] = s.PathRadiusOffset;
1656 catch (SqlException e) 1432 row["PathRevolutions"] = s.PathRevolutions;
1657 { 1433 row["PathTaperX"] = s.PathTaperX;
1658 m_log.WarnFormat("[MSSql]: Primitives Table Already Exists: {0}", e); 1434 row["PathTaperY"] = s.PathTaperY;
1659 } 1435 row["PathTwist"] = s.PathTwist;
1660 1436 row["PathTwistBegin"] = s.PathTwistBegin;
1661 try 1437 // profile
1662 { 1438 row["ProfileBegin"] = s.ProfileBegin;
1663 scmd.ExecuteNonQuery(); 1439 row["ProfileEnd"] = s.ProfileEnd;
1664 } 1440 row["ProfileCurve"] = s.ProfileCurve;
1665 catch (SqlException e) 1441 row["ProfileHollow"] = s.ProfileHollow;
1666 { 1442 row["Texture"] = s.TextureEntry;
1667 m_log.WarnFormat("[MSSql]: Shapes Table Already Exists: {0}", e); 1443 row["ExtraParams"] = s.ExtraParams;
1668 } 1444 row["State"] = s.State;
1669
1670 try
1671 {
1672 icmd.ExecuteNonQuery();
1673 }
1674 catch (SqlException e)
1675 {
1676 m_log.WarnFormat("[MSSql]: Items Table Already Exists: {0}", e);
1677 }
1678
1679 try
1680 {
1681 tcmd.ExecuteNonQuery();
1682 }
1683 catch (SqlException e)
1684 {
1685 m_log.WarnFormat("[MSSql]: Terrain Table Already Exists: {0}", e);
1686 }
1687
1688 try
1689 {
1690 lcmd.ExecuteNonQuery();
1691 }
1692 catch (SqlException e)
1693 {
1694 m_log.WarnFormat("[MSSql]: Land Table Already Exists: {0}", e);
1695 }
1696
1697 try
1698 {
1699 lalcmd.ExecuteNonQuery();
1700 }
1701 catch (SqlException e)
1702 {
1703 m_log.WarnFormat("[MSSql]: LandAccessList Table Already Exists: {0}", e);
1704 }
1705 conn.Close();
1706 } 1445 }
1707 1446
1708 /// <summary> 1447 #endregion
1709 /// 1448
1710 /// </summary> 1449 private void RetrievePrimsDataForRegion(LLUUID regionUUID, LLUUID sceneGroupID, string primID)
1711 /// <param name="conn"></param>
1712 /// <returns></returns>
1713 private bool TestTables(SqlConnection conn)
1714 { 1450 {
1715 SqlCommand primSelectCmd = new SqlCommand(m_primSelect, conn); 1451 using (SqlConnection connection = _Database.DatabaseConnection())
1716 SqlDataAdapter pDa = new SqlDataAdapter(primSelectCmd);
1717 SqlCommand shapeSelectCmd = new SqlCommand(m_shapeSelect, conn);
1718 SqlDataAdapter sDa = new SqlDataAdapter(shapeSelectCmd);
1719 SqlCommand itemsSelectCmd = new SqlCommand(m_itemsSelect, conn);
1720 SqlDataAdapter iDa = new SqlDataAdapter(itemsSelectCmd);
1721 SqlCommand terrainSelectCmd = new SqlCommand(m_terrainSelect, conn);
1722 SqlDataAdapter tDa = new SqlDataAdapter(terrainSelectCmd);
1723 SqlCommand landSelectCmd = new SqlCommand(m_landSelect, conn);
1724 SqlDataAdapter lDa = new SqlDataAdapter(landSelectCmd);
1725 SqlCommand landAccessListSelectCmd = new SqlCommand(m_landAccessListSelect, conn);
1726 SqlDataAdapter lalDa = new SqlDataAdapter(landAccessListSelectCmd);
1727
1728 DataSet tmpDS = new DataSet();
1729 try
1730 { 1452 {
1731 pDa.Fill(tmpDS, "prims"); 1453 _PrimDataAdapter.SelectCommand.Connection = connection;
1732 sDa.Fill(tmpDS, "primshapes"); 1454 _PrimDataAdapter.SelectCommand.Parameters["@RegionUUID"].Value = regionUUID.ToString();
1733 1455 if (sceneGroupID != LLUUID.Zero)
1734 iDa.Fill(tmpDS, "primitems"); 1456 _PrimDataAdapter.SelectCommand.Parameters["@SceneGroupID"].Value = sceneGroupID.ToString();
1457 else
1458 _PrimDataAdapter.SelectCommand.Parameters["@SceneGroupID"].Value = "%";
1459 _PrimDataAdapter.SelectCommand.Parameters["@UUID"].Value = primID;
1735 1460
1736 tDa.Fill(tmpDS, "terrain"); 1461 _PrimDataAdapter.Fill(_PrimsDataSet, "prims");
1737 lDa.Fill(tmpDS, "land");
1738 lalDa.Fill(tmpDS, "landaccesslist");
1739 }
1740 catch (SqlException)
1741 {
1742 m_log.Info("[REGION DB]: MS Sql Database doesn't exist... creating");
1743 InitDB(conn);
1744 }
1745 1462
1746 pDa.Fill(tmpDS, "prims"); 1463 _ShapeDataAdapter.SelectCommand.Connection = connection;
1747 sDa.Fill(tmpDS, "primshapes"); 1464 _ShapeDataAdapter.SelectCommand.Parameters["@RegionUUID"].Value = regionUUID.ToString();
1465 if (sceneGroupID != LLUUID.Zero)
1466 _ShapeDataAdapter.SelectCommand.Parameters["@SceneGroupID"].Value = sceneGroupID.ToString();
1467 else
1468 _ShapeDataAdapter.SelectCommand.Parameters["@SceneGroupID"].Value = "%";
1469 _ShapeDataAdapter.SelectCommand.Parameters["@UUID"].Value = primID;
1748 1470
1749 iDa.Fill(tmpDS, "primitems"); 1471 _ShapeDataAdapter.Fill(_PrimsDataSet, "primshapes");
1750 1472
1751 tDa.Fill(tmpDS, "terrain"); 1473 _ItemsDataAdapter.SelectCommand.Connection = connection;
1752 lDa.Fill(tmpDS, "land"); 1474 _ItemsDataAdapter.SelectCommand.Parameters["@RegionUUID"].Value = regionUUID.ToString();
1753 lalDa.Fill(tmpDS, "landaccesslist"); 1475 if (sceneGroupID != LLUUID.Zero)
1476 _ItemsDataAdapter.SelectCommand.Parameters["@SceneGroupID"].Value = sceneGroupID.ToString();
1477 else
1478 _ItemsDataAdapter.SelectCommand.Parameters["@SceneGroupID"].Value = "%";
1479 _ItemsDataAdapter.SelectCommand.Parameters["@UUID"].Value = primID;
1754 1480
1755 foreach (DataColumn col in createPrimTable().Columns) 1481 _ItemsDataAdapter.Fill(_PrimsDataSet, "primitems");
1756 {
1757 if (!tmpDS.Tables["prims"].Columns.Contains(col.ColumnName))
1758 {
1759 m_log.Info("[REGION DB]: Missing required column:" + col.ColumnName);
1760 return false;
1761 }
1762 } 1482 }
1483 }
1763 1484
1764 foreach (DataColumn col in createShapeTable().Columns) 1485 private void CommitDataSet()
1486 {
1487 lock (_PrimsDataSet)
1765 { 1488 {
1766 if (!tmpDS.Tables["primshapes"].Columns.Contains(col.ColumnName)) 1489 using (SqlConnection connection = _Database.DatabaseConnection())
1767 { 1490 {
1768 m_log.Info("[REGION DB]: Missing required column:" + col.ColumnName); 1491 _PrimDataAdapter.InsertCommand.Connection = connection;
1769 return false; 1492 _PrimDataAdapter.UpdateCommand.Connection = connection;
1770 } 1493 _PrimDataAdapter.DeleteCommand.Connection = connection;
1771 }
1772 1494
1773 // XXX primitems should probably go here eventually 1495 _ShapeDataAdapter.InsertCommand.Connection = connection;
1496 _ShapeDataAdapter.UpdateCommand.Connection = connection;
1497 _ShapeDataAdapter.DeleteCommand.Connection = connection;
1774 1498
1775 foreach (DataColumn col in createTerrainTable().Columns) 1499 _ItemsDataAdapter.InsertCommand.Connection = connection;
1776 { 1500 _ItemsDataAdapter.UpdateCommand.Connection = connection;
1777 if (!tmpDS.Tables["terrain"].Columns.Contains(col.ColumnName)) 1501 _ItemsDataAdapter.DeleteCommand.Connection = connection;
1778 {
1779 m_log.Info("[REGION DB]: Missing require column:" + col.ColumnName);
1780 return false;
1781 }
1782 }
1783 1502
1784 foreach (DataColumn col in createLandTable().Columns) 1503 _PrimDataAdapter.Update(_PrimsDataSet.Tables["prims"]);
1785 { 1504 _ShapeDataAdapter.Update(_PrimsDataSet.Tables["primshapes"]);
1786 if (!tmpDS.Tables["land"].Columns.Contains(col.ColumnName)) 1505 _ItemsDataAdapter.Update(_PrimsDataSet.Tables["primitems"]);
1787 {
1788 m_log.Info("[REGION DB]: Missing require column:" + col.ColumnName);
1789 return false;
1790 }
1791 }
1792 1506
1793 foreach (DataColumn col in createLandAccessListTable().Columns) 1507 _PrimsDataSet.AcceptChanges();
1794 { 1508
1795 if (!tmpDS.Tables["landaccesslist"].Columns.Contains(col.ColumnName)) 1509 _PrimsDataSet.Tables["prims"].Clear();
1796 { 1510 _PrimsDataSet.Tables["primshapes"].Clear();
1797 m_log.Info("[REGION DB]: Missing require column:" + col.ColumnName); 1511 _PrimsDataSet.Tables["primitems"].Clear();
1798 return false;
1799 } 1512 }
1800 } 1513 }
1801
1802 return true;
1803 } 1514 }
1804 1515
1805 /*********************************************************************** 1516 private static void SetupCommands(SqlDataAdapter dataAdapter)
1806 *
1807 * Type conversion functions
1808 *
1809 **********************************************************************/
1810
1811 /// <summary>
1812 /// Type conversion function
1813 /// </summary>
1814 /// <param name="type">a Type</param>
1815 /// <returns>a DbType</returns>
1816 private static DbType dbtypeFromType(Type type)
1817 { 1517 {
1818 if (type == typeof(String)) 1518 SqlCommandBuilder commandBuilder = new SqlCommandBuilder(dataAdapter);
1819 { 1519
1820 return DbType.String; 1520 dataAdapter.InsertCommand = commandBuilder.GetInsertCommand(true);
1821 } 1521 dataAdapter.UpdateCommand = commandBuilder.GetUpdateCommand(true);
1822 else if (type == typeof(Int32)) 1522 dataAdapter.DeleteCommand = commandBuilder.GetDeleteCommand(true);
1823 {
1824 return DbType.Int32;
1825 }
1826 else if (type == typeof(Double))
1827 {
1828 return DbType.Double;
1829 }
1830 else if (type == typeof(Byte[]))
1831 {
1832 return DbType.Binary;
1833 }
1834 else
1835 {
1836 return DbType.String;
1837 }
1838 } 1523 }
1524 #endregion
1839 } 1525 }
1840} 1526}
diff --git a/OpenSim/Data/MSSQL/Resources/001_EstateStore.sql b/OpenSim/Data/MSSQL/Resources/001_EstateStore.sql
new file mode 100644
index 0000000..9bb2f75
--- /dev/null
+++ b/OpenSim/Data/MSSQL/Resources/001_EstateStore.sql
@@ -0,0 +1,85 @@
1BEGIN TRANSACTION
2
3CREATE TABLE [dbo].[estate_managers](
4 [EstateID] [int] NOT NULL,
5 [uuid] [varchar](36) NOT NULL,
6 CONSTRAINT [PK_estate_managers] PRIMARY KEY CLUSTERED
7(
8 [EstateID] ASC
9)WITH (PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]
10) ON [PRIMARY];
11
12CREATE TABLE [dbo].[estate_groups](
13 [EstateID] [int] NOT NULL,
14 [uuid] [varchar](36) NOT NULL,
15 CONSTRAINT [PK_estate_groups] PRIMARY KEY CLUSTERED
16(
17 [EstateID] ASC
18)WITH (PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]
19) ON [PRIMARY];
20
21
22CREATE TABLE [dbo].[estate_users](
23 [EstateID] [int] NOT NULL,
24 [uuid] [varchar](36) NOT NULL,
25 CONSTRAINT [PK_estate_users] PRIMARY KEY CLUSTERED
26(
27 [EstateID] ASC
28)WITH (PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]
29) ON [PRIMARY];
30
31
32CREATE TABLE [dbo].[estateban](
33 [EstateID] [int] NOT NULL,
34 [bannedUUID] [varchar](36) NOT NULL,
35 [bannedIp] [varchar](16) NOT NULL,
36 [bannedIpHostMask] [varchar](16) NOT NULL,
37 [bannedNameMask] [varchar](64) NULL DEFAULT (NULL),
38 CONSTRAINT [PK_estateban] PRIMARY KEY CLUSTERED
39(
40 [EstateID] ASC
41)WITH (PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]
42) ON [PRIMARY];
43
44CREATE TABLE [dbo].[estate_settings](
45 [EstateID] [int] IDENTITY(1,100) NOT NULL,
46 [EstateName] [varchar](64) NULL DEFAULT (NULL),
47 [AbuseEmailToEstateOwner] [bit] NOT NULL,
48 [DenyAnonymous] [bit] NOT NULL,
49 [ResetHomeOnTeleport] [bit] NOT NULL,
50 [FixedSun] [bit] NOT NULL,
51 [DenyTransacted] [bit] NOT NULL,
52 [BlockDwell] [bit] NOT NULL,
53 [DenyIdentified] [bit] NOT NULL,
54 [AllowVoice] [bit] NOT NULL,
55 [UseGlobalTime] [bit] NOT NULL,
56 [PricePerMeter] [int] NOT NULL,
57 [TaxFree] [bit] NOT NULL,
58 [AllowDirectTeleport] [bit] NOT NULL,
59 [RedirectGridX] [int] NOT NULL,
60 [RedirectGridY] [int] NOT NULL,
61 [ParentEstateID] [int] NOT NULL,
62 [SunPosition] [float] NOT NULL,
63 [EstateSkipScripts] [bit] NOT NULL,
64 [BillableFactor] [float] NOT NULL,
65 [PublicAccess] [bit] NOT NULL,
66 [AbuseEmail] [varchar](255) NOT NULL,
67 [EstateOwner] [varchar](36) NOT NULL,
68 [DenyMinors] [bit] NOT NULL,
69 CONSTRAINT [PK_estate_settings] PRIMARY KEY CLUSTERED
70(
71 [EstateID] ASC
72)WITH (PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]
73) ON [PRIMARY];
74
75
76CREATE TABLE [dbo].[estate_map](
77 [RegionID] [varchar](36) NOT NULL DEFAULT ('00000000-0000-0000-0000-000000000000'),
78 [EstateID] [int] NOT NULL,
79 CONSTRAINT [PK_estate_map] PRIMARY KEY CLUSTERED
80(
81 [RegionID] ASC
82)WITH (PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]
83) ON [PRIMARY];
84
85COMMIT \ No newline at end of file
diff --git a/OpenSim/Data/MSSQL/Resources/002_RegionStore.sql b/OpenSim/Data/MSSQL/Resources/002_RegionStore.sql
new file mode 100644
index 0000000..1801035
--- /dev/null
+++ b/OpenSim/Data/MSSQL/Resources/002_RegionStore.sql
@@ -0,0 +1,50 @@
1BEGIN TRANSACTION
2
3CREATE TABLE regionban (
4 [regionUUID] VARCHAR(36) NOT NULL,
5 [bannedUUID] VARCHAR(36) NOT NULL,
6 [bannedIp] VARCHAR(16) NOT NULL,
7 [bannedIpHostMask] VARCHAR(16) NOT NULL)
8
9create table [dbo].[regionsettings] (
10 [regionUUID] [varchar](36) not null,
11 [block_terraform] [bit] not null,
12 [block_fly] [bit] not null,
13 [allow_damage] [bit] not null,
14 [restrict_pushing] [bit] not null,
15 [allow_land_resell] [bit] not null,
16 [allow_land_join_divide] [bit] not null,
17 [block_show_in_search] [bit] not null,
18 [agent_limit] [int] not null,
19 [object_bonus] [float] not null,
20 [maturity] [int] not null,
21 [disable_scripts] [bit] not null,
22 [disable_collisions] [bit] not null,
23 [disable_physics] [bit] not null,
24 [terrain_texture_1] [varchar](36) not null,
25 [terrain_texture_2] [varchar](36) not null,
26 [terrain_texture_3] [varchar](36) not null,
27 [terrain_texture_4] [varchar](36) not null,
28 [elevation_1_nw] [float] not null,
29 [elevation_2_nw] [float] not null,
30 [elevation_1_ne] [float] not null,
31 [elevation_2_ne] [float] not null,
32 [elevation_1_se] [float] not null,
33 [elevation_2_se] [float] not null,
34 [elevation_1_sw] [float] not null,
35 [elevation_2_sw] [float] not null,
36 [water_height] [float] not null,
37 [terrain_raise_limit] [float] not null,
38 [terrain_lower_limit] [float] not null,
39 [use_estate_sun] [bit] not null,
40 [fixed_sun] [bit] not null,
41 [sun_position] [float] not null,
42 [covenant] [varchar](36) default NULL,
43 [Sandbox] [bit] NOT NULL,
44PRIMARY KEY CLUSTERED
45(
46 [regionUUID] ASC
47)WITH (PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]
48) ON [PRIMARY]
49
50COMMIT \ No newline at end of file
diff --git a/OpenSim/Data/MSSQL/Resources/003_RegionStore.sql b/OpenSim/Data/MSSQL/Resources/003_RegionStore.sql
new file mode 100644
index 0000000..a8f40c2
--- /dev/null
+++ b/OpenSim/Data/MSSQL/Resources/003_RegionStore.sql
@@ -0,0 +1,67 @@
1BEGIN TRANSACTION
2
3CREATE TABLE dbo.Tmp_prims
4 (
5 UUID varchar(36) NOT NULL,
6 RegionUUID varchar(36) NULL,
7 ParentID int NULL,
8 CreationDate int NULL,
9 Name varchar(255) NULL,
10 SceneGroupID varchar(36) NULL,
11 Text varchar(255) NULL,
12 Description varchar(255) NULL,
13 SitName varchar(255) NULL,
14 TouchName varchar(255) NULL,
15 ObjectFlags int NULL,
16 CreatorID varchar(36) NULL,
17 OwnerID varchar(36) NULL,
18 GroupID varchar(36) NULL,
19 LastOwnerID varchar(36) NULL,
20 OwnerMask int NULL,
21 NextOwnerMask int NULL,
22 GroupMask int NULL,
23 EveryoneMask int NULL,
24 BaseMask int NULL,
25 PositionX float(53) NULL,
26 PositionY float(53) NULL,
27 PositionZ float(53) NULL,
28 GroupPositionX float(53) NULL,
29 GroupPositionY float(53) NULL,
30 GroupPositionZ float(53) NULL,
31 VelocityX float(53) NULL,
32 VelocityY float(53) NULL,
33 VelocityZ float(53) NULL,
34 AngularVelocityX float(53) NULL,
35 AngularVelocityY float(53) NULL,
36 AngularVelocityZ float(53) NULL,
37 AccelerationX float(53) NULL,
38 AccelerationY float(53) NULL,
39 AccelerationZ float(53) NULL,
40 RotationX float(53) NULL,
41 RotationY float(53) NULL,
42 RotationZ float(53) NULL,
43 RotationW float(53) NULL,
44 SitTargetOffsetX float(53) NULL,
45 SitTargetOffsetY float(53) NULL,
46 SitTargetOffsetZ float(53) NULL,
47 SitTargetOrientW float(53) NULL,
48 SitTargetOrientX float(53) NULL,
49 SitTargetOrientY float(53) NULL,
50 SitTargetOrientZ float(53) NULL
51 ) ON [PRIMARY]
52
53IF EXISTS(SELECT * FROM dbo.prims)
54 EXEC('INSERT INTO dbo.Tmp_prims (UUID, RegionUUID, ParentID, CreationDate, Name, SceneGroupID, Text, Description, SitName, TouchName, ObjectFlags, CreatorID, OwnerID, GroupID, LastOwnerID, OwnerMask, NextOwnerMask, GroupMask, EveryoneMask, BaseMask, PositionX, PositionY, PositionZ, GroupPositionX, GroupPositionY, GroupPositionZ, VelocityX, VelocityY, VelocityZ, AngularVelocityX, AngularVelocityY, AngularVelocityZ, AccelerationX, AccelerationY, AccelerationZ, RotationX, RotationY, RotationZ, RotationW, SitTargetOffsetX, SitTargetOffsetY, SitTargetOffsetZ, SitTargetOrientW, SitTargetOrientX, SitTargetOrientY, SitTargetOrientZ)
55 SELECT CONVERT(varchar(36), UUID), CONVERT(varchar(36), RegionUUID), ParentID, CreationDate, Name, CONVERT(varchar(36), SceneGroupID), Text, Description, SitName, TouchName, ObjectFlags, CONVERT(varchar(36), CreatorID), CONVERT(varchar(36), OwnerID), CONVERT(varchar(36), GroupID), CONVERT(varchar(36), LastOwnerID), OwnerMask, NextOwnerMask, GroupMask, EveryoneMask, BaseMask, PositionX, PositionY, PositionZ, GroupPositionX, GroupPositionY, GroupPositionZ, VelocityX, VelocityY, VelocityZ, AngularVelocityX, AngularVelocityY, AngularVelocityZ, AccelerationX, AccelerationY, AccelerationZ, RotationX, RotationY, RotationZ, RotationW, SitTargetOffsetX, SitTargetOffsetY, SitTargetOffsetZ, SitTargetOrientW, SitTargetOrientX, SitTargetOrientY, SitTargetOrientZ FROM dbo.prims WITH (HOLDLOCK TABLOCKX)')
56
57DROP TABLE dbo.prims
58
59EXECUTE sp_rename N'dbo.Tmp_prims', N'prims', 'OBJECT'
60
61ALTER TABLE dbo.prims ADD CONSTRAINT
62 PK__prims__10566F31 PRIMARY KEY CLUSTERED
63 (
64 UUID
65 ) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
66
67COMMIT \ No newline at end of file
diff --git a/OpenSim/Data/MSSQL/Resources/004_RegionStore.sql b/OpenSim/Data/MSSQL/Resources/004_RegionStore.sql
new file mode 100644
index 0000000..4e64901
--- /dev/null
+++ b/OpenSim/Data/MSSQL/Resources/004_RegionStore.sql
@@ -0,0 +1,40 @@
1BEGIN TRANSACTION
2
3CREATE TABLE dbo.Tmp_primitems
4 (
5 itemID varchar(36) NOT NULL,
6 primID varchar(36) NULL,
7 assetID varchar(36) NULL,
8 parentFolderID varchar(36) NULL,
9 invType int NULL,
10 assetType int NULL,
11 name varchar(255) NULL,
12 description varchar(255) NULL,
13 creationDate varchar(255) NULL,
14 creatorID varchar(36) NULL,
15 ownerID varchar(36) NULL,
16 lastOwnerID varchar(36) NULL,
17 groupID varchar(36) NULL,
18 nextPermissions int NULL,
19 currentPermissions int NULL,
20 basePermissions int NULL,
21 everyonePermissions int NULL,
22 groupPermissions int NULL
23 ) ON [PRIMARY]
24
25IF EXISTS(SELECT * FROM dbo.primitems)
26 EXEC('INSERT INTO dbo.Tmp_primitems (itemID, primID, assetID, parentFolderID, invType, assetType, name, description, creationDate, creatorID, ownerID, lastOwnerID, groupID, nextPermissions, currentPermissions, basePermissions, everyonePermissions, groupPermissions)
27 SELECT CONVERT(varchar(36), itemID), CONVERT(varchar(36), primID), CONVERT(varchar(36), assetID), CONVERT(varchar(36), parentFolderID), invType, assetType, name, description, creationDate, CONVERT(varchar(36), creatorID), CONVERT(varchar(36), ownerID), CONVERT(varchar(36), lastOwnerID), CONVERT(varchar(36), groupID), nextPermissions, currentPermissions, basePermissions, everyonePermissions, groupPermissions')
28
29DROP TABLE dbo.primitems
30
31EXECUTE sp_rename N'dbo.Tmp_primitems', N'primitems', 'OBJECT'
32
33ALTER TABLE dbo.primitems ADD CONSTRAINT
34 PK__primitems__0A688BB1 PRIMARY KEY CLUSTERED
35 (
36 itemID
37 ) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
38
39
40COMMIT
diff --git a/OpenSim/Data/MSSQL/Resources/005_RegionStore.sql b/OpenSim/Data/MSSQL/Resources/005_RegionStore.sql
new file mode 100644
index 0000000..74e9d85
--- /dev/null
+++ b/OpenSim/Data/MSSQL/Resources/005_RegionStore.sql
@@ -0,0 +1,49 @@
1BEGIN TRANSACTION
2
3CREATE TABLE dbo.Tmp_primshapes
4 (
5 UUID varchar(36) NOT NULL,
6 Shape int NULL,
7 ScaleX float(53) NULL,
8 ScaleY float(53) NULL,
9 ScaleZ float(53) NULL,
10 PCode int NULL,
11 PathBegin int NULL,
12 PathEnd int NULL,
13 PathScaleX int NULL,
14 PathScaleY int NULL,
15 PathShearX int NULL,
16 PathShearY int NULL,
17 PathSkew int NULL,
18 PathCurve int NULL,
19 PathRadiusOffset int NULL,
20 PathRevolutions int NULL,
21 PathTaperX int NULL,
22 PathTaperY int NULL,
23 PathTwist int NULL,
24 PathTwistBegin int NULL,
25 ProfileBegin int NULL,
26 ProfileEnd int NULL,
27 ProfileCurve int NULL,
28 ProfileHollow int NULL,
29 State int NULL,
30 Texture image NULL,
31 ExtraParams image NULL
32 ) ON [PRIMARY]
33 TEXTIMAGE_ON [PRIMARY]
34
35IF EXISTS(SELECT * FROM dbo.primshapes)
36 EXEC('INSERT INTO dbo.Tmp_primshapes (UUID, Shape, ScaleX, ScaleY, ScaleZ, PCode, PathBegin, PathEnd, PathScaleX, PathScaleY, PathShearX, PathShearY, PathSkew, PathCurve, PathRadiusOffset, PathRevolutions, PathTaperX, PathTaperY, PathTwist, PathTwistBegin, ProfileBegin, ProfileEnd, ProfileCurve, ProfileHollow, State, Texture, ExtraParams)
37 SELECT CONVERT(varchar(36), UUID), Shape, ScaleX, ScaleY, ScaleZ, PCode, PathBegin, PathEnd, PathScaleX, PathScaleY, PathShearX, PathShearY, PathSkew, PathCurve, PathRadiusOffset, PathRevolutions, PathTaperX, PathTaperY, PathTwist, PathTwistBegin, ProfileBegin, ProfileEnd, ProfileCurve, ProfileHollow, State, Texture, ExtraParams FROM dbo.primshapes WITH (HOLDLOCK TABLOCKX)')
38
39DROP TABLE dbo.primshapes
40
41EXECUTE sp_rename N'dbo.Tmp_primshapes', N'primshapes', 'OBJECT'
42
43ALTER TABLE dbo.primshapes ADD CONSTRAINT
44 PK__primshapes__0880433F PRIMARY KEY CLUSTERED
45 (
46 UUID
47 ) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
48
49COMMIT \ No newline at end of file
diff --git a/OpenSim/Data/MSSQL/Resources/006_RegionStore.sql b/OpenSim/Data/MSSQL/Resources/006_RegionStore.sql
new file mode 100644
index 0000000..0419c0c
--- /dev/null
+++ b/OpenSim/Data/MSSQL/Resources/006_RegionStore.sql
@@ -0,0 +1,36 @@
1BEGIN TRANSACTION
2
3ALTER TABLE prims ADD PayPrice int not null default 0
4ALTER TABLE prims ADD PayButton1 int not null default 0
5ALTER TABLE prims ADD PayButton2 int not null default 0
6ALTER TABLE prims ADD PayButton3 int not null default 0
7ALTER TABLE prims ADD PayButton4 int not null default 0
8ALTER TABLE prims ADD LoopedSound varchar(36) not null default '00000000-0000-0000-0000-000000000000';
9ALTER TABLE prims ADD LoopedSoundGain float not null default 0.0;
10ALTER TABLE prims ADD TextureAnimation image
11ALTER TABLE prims ADD OmegaX float not null default 0.0
12ALTER TABLE prims ADD OmegaY float not null default 0.0
13ALTER TABLE prims ADD OmegaZ float not null default 0.0
14ALTER TABLE prims ADD CameraEyeOffsetX float not null default 0.0
15ALTER TABLE prims ADD CameraEyeOffsetY float not null default 0.0
16ALTER TABLE prims ADD CameraEyeOffsetZ float not null default 0.0
17ALTER TABLE prims ADD CameraAtOffsetX float not null default 0.0
18ALTER TABLE prims ADD CameraAtOffsetY float not null default 0.0
19ALTER TABLE prims ADD CameraAtOffsetZ float not null default 0.0
20ALTER TABLE prims ADD ForceMouselook tinyint not null default 0
21ALTER TABLE prims ADD ScriptAccessPin int not null default 0
22ALTER TABLE prims ADD AllowedDrop tinyint not null default 0
23ALTER TABLE prims ADD DieAtEdge tinyint not null default 0
24ALTER TABLE prims ADD SalePrice int not null default 10
25ALTER TABLE prims ADD SaleType tinyint not null default 0
26
27ALTER TABLE primitems add flags integer not null default 0
28
29ALTER TABLE land ADD AuthbuyerID varchar(36) NOT NULL default '00000000-0000-0000-0000-000000000000'
30
31CREATE index prims_regionuuid on prims(RegionUUID)
32CREATE index prims_parentid on prims(ParentID)
33
34CREATE index primitems_primid on primitems(primID)
35
36COMMIT
diff --git a/OpenSim/Data/Migration.cs b/OpenSim/Data/Migration.cs
index ecd18ae..8e4cba3 100644
--- a/OpenSim/Data/Migration.cs
+++ b/OpenSim/Data/Migration.cs
@@ -103,7 +103,7 @@ namespace OpenSim.Data
103 private void Initialize() 103 private void Initialize()
104 { 104 {
105 // clever, eh, we figure out which migrations version we are 105 // clever, eh, we figure out which migrations version we are
106 int migration_version = FindVersion("migrations"); 106 int migration_version = FindVersion(_conn, "migrations");
107 107
108 if (migration_version > 0) 108 if (migration_version > 0)
109 return; 109 return;
@@ -119,7 +119,7 @@ namespace OpenSim.Data
119 public void Update() 119 public void Update()
120 { 120 {
121 int version = 0; 121 int version = 0;
122 version = FindVersion(_type); 122 version = FindVersion(_conn, _type);
123 123
124 SortedList<int, string> migrations = GetMigrationsAfter(version); 124 SortedList<int, string> migrations = GetMigrationsAfter(version);
125 if (migrations.Count < 1) 125 if (migrations.Count < 1)
@@ -170,7 +170,7 @@ namespace OpenSim.Data
170 170
171 public int Version 171 public int Version
172 { 172 {
173 get { return FindVersion(_type); } 173 get { return FindVersion(_conn, _type); }
174 set { 174 set {
175 if (Version < 1) 175 if (Version < 1)
176 { 176 {
@@ -183,10 +183,10 @@ namespace OpenSim.Data
183 } 183 }
184 } 184 }
185 185
186 private int FindVersion(string type) 186 protected virtual int FindVersion(DbConnection conn, string type)
187 { 187 {
188 int version = 0; 188 int version = 0;
189 DbCommand cmd = _conn.CreateCommand(); 189 DbCommand cmd = conn.CreateCommand();
190 try 190 try
191 { 191 {
192 cmd.CommandText = "select version from migrations where name='" + type + "' limit 1"; 192 cmd.CommandText = "select version from migrations where name='" + type + "' limit 1";