OpenSim
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros
MySQLRegionData.cs
Go to the documentation of this file.
1 /*
2  * Copyright (c) Contributors, http://opensimulator.org/
3  * See CONTRIBUTORS.TXT for a full list of copyright holders.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  * * Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * * Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * * Neither the name of the OpenSimulator Project nor the
13  * names of its contributors may be used to endorse or promote products
14  * derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 using System;
29 using System.Collections;
30 using System.Collections.Generic;
31 using System.Data;
32 using System.Reflection;
33 using MySql.Data.MySqlClient;
34 using OpenMetaverse;
35 using OpenSim.Framework;
36 using OpenSim.Data;
38 
39 namespace OpenSim.Data.MySQL
40 {
42  {
43  private string m_Realm;
44  private List<string> m_ColumnNames;
45  //private string m_connectionString;
46 
47  protected virtual Assembly Assembly
48  {
49  get { return GetType().Assembly; }
50  }
51 
52  public MySqlRegionData(string connectionString, string realm)
53  : base(connectionString)
54  {
55  m_Realm = realm;
56  m_connectionString = connectionString;
57 
58  using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
59  {
60  dbcon.Open();
61  Migration m = new Migration(dbcon, Assembly, "GridStore");
62  m.Update();
63  }
64  }
65 
66  public List<RegionData> Get(string regionName, UUID scopeID)
67  {
68  string command = "select * from `"+m_Realm+"` where regionName like ?regionName";
69  if (scopeID != UUID.Zero)
70  command += " and ScopeID = ?scopeID";
71 
72  command += " order by regionName";
73 
74  using (MySqlCommand cmd = new MySqlCommand(command))
75  {
76  cmd.Parameters.AddWithValue("?regionName", regionName);
77  cmd.Parameters.AddWithValue("?scopeID", scopeID.ToString());
78 
79  return RunCommand(cmd);
80  }
81  }
82 
83  public RegionData Get(int posX, int posY, UUID scopeID)
84  {
85 /* fixed size regions
86  string command = "select * from `"+m_Realm+"` where locX = ?posX and locY = ?posY";
87  if (scopeID != UUID.Zero)
88  command += " and ScopeID = ?scopeID";
89 
90  using (MySqlCommand cmd = new MySqlCommand(command))
91  {
92  cmd.Parameters.AddWithValue("?posX", posX.ToString());
93  cmd.Parameters.AddWithValue("?posY", posY.ToString());
94  cmd.Parameters.AddWithValue("?scopeID", scopeID.ToString());
95 
96  List<RegionData> ret = RunCommand(cmd);
97  if (ret.Count == 0)
98  return null;
99 
100  return ret[0];
101  }
102 */
103  // extend database search for maximum region size area
104  string command = "select * from `" + m_Realm + "` where locX between ?startX and ?endX and locY between ?startY and ?endY";
105  if (scopeID != UUID.Zero)
106  command += " and ScopeID = ?scopeID";
107 
108  int startX = posX - (int)Constants.MaximumRegionSize;
109  int startY = posY - (int)Constants.MaximumRegionSize;
110  int endX = posX;
111  int endY = posY;
112 
113  List<RegionData> ret;
114  using (MySqlCommand cmd = new MySqlCommand(command))
115  {
116  cmd.Parameters.AddWithValue("?startX", startX.ToString());
117  cmd.Parameters.AddWithValue("?startY", startY.ToString());
118  cmd.Parameters.AddWithValue("?endX", endX.ToString());
119  cmd.Parameters.AddWithValue("?endY", endY.ToString());
120  cmd.Parameters.AddWithValue("?scopeID", scopeID.ToString());
121 
122  ret = RunCommand(cmd);
123  }
124 
125  if (ret.Count == 0)
126  return null;
127 
128  // find the first that contains pos
129  RegionData rg = null;
130  foreach (RegionData r in ret)
131  {
132  if (posX >= r.posX && posX < r.posX + r.sizeX
133  && posY >= r.posY && posY < r.posY + r.sizeY)
134  {
135  rg = r;
136  break;
137  }
138  }
139 
140  return rg;
141  }
142 
143  public RegionData Get(UUID regionID, UUID scopeID)
144  {
145  string command = "select * from `"+m_Realm+"` where uuid = ?regionID";
146  if (scopeID != UUID.Zero)
147  command += " and ScopeID = ?scopeID";
148 
149  using (MySqlCommand cmd = new MySqlCommand(command))
150  {
151  cmd.Parameters.AddWithValue("?regionID", regionID.ToString());
152  cmd.Parameters.AddWithValue("?scopeID", scopeID.ToString());
153 
154  List<RegionData> ret = RunCommand(cmd);
155  if (ret.Count == 0)
156  return null;
157 
158  return ret[0];
159  }
160  }
161 
162  public List<RegionData> Get(int startX, int startY, int endX, int endY, UUID scopeID)
163  {
164 /* fix size regions
165  string command = "select * from `"+m_Realm+"` where locX between ?startX and ?endX and locY between ?startY and ?endY";
166  if (scopeID != UUID.Zero)
167  command += " and ScopeID = ?scopeID";
168 
169  using (MySqlCommand cmd = new MySqlCommand(command))
170  {
171  cmd.Parameters.AddWithValue("?startX", startX.ToString());
172  cmd.Parameters.AddWithValue("?startY", startY.ToString());
173  cmd.Parameters.AddWithValue("?endX", endX.ToString());
174  cmd.Parameters.AddWithValue("?endY", endY.ToString());
175  cmd.Parameters.AddWithValue("?scopeID", scopeID.ToString());
176 
177  return RunCommand(cmd);
178  }
179  */
180  string command = "select * from `" + m_Realm + "` where locX between ?startX and ?endX and locY between ?startY and ?endY";
181  if (scopeID != UUID.Zero)
182  command += " and ScopeID = ?scopeID";
183 
184  int qstartX = startX - (int)Constants.MaximumRegionSize;
185  int qstartY = startY - (int)Constants.MaximumRegionSize;
186 
187  List<RegionData> dbret;
188  using (MySqlCommand cmd = new MySqlCommand(command))
189  {
190  cmd.Parameters.AddWithValue("?startX", qstartX.ToString());
191  cmd.Parameters.AddWithValue("?startY", qstartY.ToString());
192  cmd.Parameters.AddWithValue("?endX", endX.ToString());
193  cmd.Parameters.AddWithValue("?endY", endY.ToString());
194  cmd.Parameters.AddWithValue("?scopeID", scopeID.ToString());
195 
196  dbret = RunCommand(cmd);
197  }
198 
199  List<RegionData> ret = new List<RegionData>();
200 
201  if (dbret.Count == 0)
202  return ret;
203 
204  foreach (RegionData r in dbret)
205  {
206  if (r.posX + r.sizeX > startX && r.posX <= endX
207  && r.posY + r.sizeX > startY && r.posY <= endY)
208  ret.Add(r);
209  }
210  return ret;
211  }
212 
213  public List<RegionData> RunCommand(MySqlCommand cmd)
214  {
215  List<RegionData> retList = new List<RegionData>();
216 
217  using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
218  {
219  dbcon.Open();
220  cmd.Connection = dbcon;
221 
222  using (IDataReader result = cmd.ExecuteReader())
223  {
224  while (result.Read())
225  {
226  RegionData ret = new RegionData();
227  ret.Data = new Dictionary<string, object>();
228 
229  ret.RegionID = DBGuid.FromDB(result["uuid"]);
230  ret.ScopeID = DBGuid.FromDB(result["ScopeID"]);
231 
232  ret.RegionName = result["regionName"].ToString();
233  ret.posX = Convert.ToInt32(result["locX"]);
234  ret.posY = Convert.ToInt32(result["locY"]);
235  ret.sizeX = Convert.ToInt32(result["sizeX"]);
236  ret.sizeY = Convert.ToInt32(result["sizeY"]);
237 
238  CheckColumnNames(result);
239 
240  foreach (string s in m_ColumnNames)
241  {
242  if (s == "uuid")
243  continue;
244  if (s == "ScopeID")
245  continue;
246  if (s == "regionName")
247  continue;
248  if (s == "locX")
249  continue;
250  if (s == "locY")
251  continue;
252 
253  object value = result[s];
254  if (value is DBNull)
255  ret.Data[s] = null;
256  else
257  ret.Data[s] = result[s].ToString();
258  }
259 
260  retList.Add(ret);
261  }
262  }
263  }
264 
265  return retList;
266  }
267 
268  private void CheckColumnNames(IDataReader result)
269  {
270  if (m_ColumnNames != null)
271  return;
272 
273  List<string> columnNames = new List<string>();
274 
275  DataTable schemaTable = result.GetSchemaTable();
276  foreach (DataRow row in schemaTable.Rows)
277  {
278  if (row["ColumnName"] != null)
279  columnNames.Add(row["ColumnName"].ToString());
280  }
281 
282  m_ColumnNames = columnNames;
283  }
284 
285  public bool Store(RegionData data)
286  {
287  if (data.Data.ContainsKey("uuid"))
288  data.Data.Remove("uuid");
289  if (data.Data.ContainsKey("ScopeID"))
290  data.Data.Remove("ScopeID");
291  if (data.Data.ContainsKey("regionName"))
292  data.Data.Remove("regionName");
293  if (data.Data.ContainsKey("posX"))
294  data.Data.Remove("posX");
295  if (data.Data.ContainsKey("posY"))
296  data.Data.Remove("posY");
297  if (data.Data.ContainsKey("sizeX"))
298  data.Data.Remove("sizeX");
299  if (data.Data.ContainsKey("sizeY"))
300  data.Data.Remove("sizeY");
301  if (data.Data.ContainsKey("locX"))
302  data.Data.Remove("locX");
303  if (data.Data.ContainsKey("locY"))
304  data.Data.Remove("locY");
305 
306  if (data.RegionName.Length > 128)
307  data.RegionName = data.RegionName.Substring(0, 128);
308 
309  string[] fields = new List<string>(data.Data.Keys).ToArray();
310 
311  using (MySqlCommand cmd = new MySqlCommand())
312  {
313  string update = "update `" + m_Realm + "` set locX=?posX, locY=?posY, sizeX=?sizeX, sizeY=?sizeY";
314  foreach (string field in fields)
315  {
316  update += ", ";
317  update += "`" + field + "` = ?" + field;
318 
319  cmd.Parameters.AddWithValue("?" + field, data.Data[field]);
320  }
321 
322  update += " where uuid = ?regionID";
323 
324  if (data.ScopeID != UUID.Zero)
325  update += " and ScopeID = ?scopeID";
326 
327  cmd.CommandText = update;
328  cmd.Parameters.AddWithValue("?regionID", data.RegionID.ToString());
329  cmd.Parameters.AddWithValue("?regionName", data.RegionName);
330  cmd.Parameters.AddWithValue("?scopeID", data.ScopeID.ToString());
331  cmd.Parameters.AddWithValue("?posX", data.posX.ToString());
332  cmd.Parameters.AddWithValue("?posY", data.posY.ToString());
333  cmd.Parameters.AddWithValue("?sizeX", data.sizeX.ToString());
334  cmd.Parameters.AddWithValue("?sizeY", data.sizeY.ToString());
335 
336  if (ExecuteNonQuery(cmd) < 1)
337  {
338  string insert = "insert into `" + m_Realm + "` (`uuid`, `ScopeID`, `locX`, `locY`, `sizeX`, `sizeY`, `regionName`, `" +
339  String.Join("`, `", fields) +
340  "`) values ( ?regionID, ?scopeID, ?posX, ?posY, ?sizeX, ?sizeY, ?regionName, ?" + String.Join(", ?", fields) + ")";
341 
342  cmd.CommandText = insert;
343 
344  if (ExecuteNonQuery(cmd) < 1)
345  {
346  return false;
347  }
348  }
349  }
350 
351  return true;
352  }
353 
354  public bool SetDataItem(UUID regionID, string item, string value)
355  {
356  using (MySqlCommand cmd = new MySqlCommand("update `" + m_Realm + "` set `" + item + "` = ?" + item + " where uuid = ?UUID"))
357  {
358  cmd.Parameters.AddWithValue("?" + item, value);
359  cmd.Parameters.AddWithValue("?UUID", regionID.ToString());
360 
361  if (ExecuteNonQuery(cmd) > 0)
362  return true;
363  }
364 
365  return false;
366  }
367 
368  public bool Delete(UUID regionID)
369  {
370  using (MySqlCommand cmd = new MySqlCommand("delete from `" + m_Realm + "` where uuid = ?UUID"))
371  {
372  cmd.Parameters.AddWithValue("?UUID", regionID.ToString());
373 
374  if (ExecuteNonQuery(cmd) > 0)
375  return true;
376  }
377 
378  return false;
379  }
380 
381  public List<RegionData> GetDefaultRegions(UUID scopeID)
382  {
383  return Get((int)RegionFlags.DefaultRegion, scopeID);
384  }
385 
386  public List<RegionData> GetDefaultHypergridRegions(UUID scopeID)
387  {
388  return Get((int)RegionFlags.DefaultHGRegion, scopeID);
389  }
390 
391  public List<RegionData> GetFallbackRegions(UUID scopeID, int x, int y)
392  {
393  List<RegionData> regions = Get((int)RegionFlags.FallbackRegion, scopeID);
394  RegionDataDistanceCompare distanceComparer = new RegionDataDistanceCompare(x, y);
395  regions.Sort(distanceComparer);
396  return regions;
397  }
398 
399  public List<RegionData> GetHyperlinks(UUID scopeID)
400  {
401  return Get((int)RegionFlags.Hyperlink, scopeID);
402  }
403 
404  private List<RegionData> Get(int regionFlags, UUID scopeID)
405  {
406  string command = "select * from `" + m_Realm + "` where (flags & " + regionFlags.ToString() + ") <> 0";
407  if (scopeID != UUID.Zero)
408  command += " and ScopeID = ?scopeID";
409 
410  using (MySqlCommand cmd = new MySqlCommand(command))
411  {
412  cmd.Parameters.AddWithValue("?scopeID", scopeID.ToString());
413 
414  return RunCommand(cmd);
415  }
416  }
417  }
418 }
List< RegionData > GetHyperlinks(UUID scopeID)
bool SetDataItem(UUID regionID, string item, string value)
A database interface class to a user profile storage system
int posX
The position in meters of this region.
Definition: IRegionData.cs:44
const uint MaximumRegionSize
Definition: Constants.cs:39
RegionData Get(UUID regionID, UUID scopeID)
An interface for connecting to the authentication datastore
Definition: IRegionData.cs:70
List< RegionData > Get(int startX, int startY, int endX, int endY, UUID scopeID)
List< RegionData > GetDefaultRegions(UUID scopeID)
List< RegionData > GetFallbackRegions(UUID scopeID, int x, int y)
MySqlRegionData(string connectionString, string realm)
int posY
The position in meters of this region.
Definition: IRegionData.cs:49
Dictionary< string, object > Data
Definition: IRegionData.cs:64
RegionFlags
Region flags used internally by OpenSimulator to store installation specific information about region...
Definition: RegionFlags.cs:40
OpenSim.Framework.RegionFlags RegionFlags
List< RegionData > Get(string regionName, UUID scopeID)
List< RegionData > RunCommand(MySqlCommand cmd)
List< RegionData > GetDefaultHypergridRegions(UUID scopeID)
RegionData Get(int posX, int posY, UUID scopeID)