OpenSim
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros
SQLiteGenericTableHandler.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.Generic;
30 using System.Data;
31 using System.Reflection;
32 using log4net;
33 #if CSharpSqlite
34  using Community.CsharpSqlite.Sqlite;
35 #else
36  using Mono.Data.Sqlite;
37 #endif
38 using OpenMetaverse;
39 using OpenSim.Framework;
40 using OpenSim.Region.Framework.Interfaces;
41 
42 namespace OpenSim.Data.SQLite
43 {
44  public class SQLiteGenericTableHandler<T> : SQLiteFramework where T: class, new()
45  {
46 // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47 
48  protected Dictionary<string, FieldInfo> m_Fields =
49  new Dictionary<string, FieldInfo>();
50 
51  protected List<string> m_ColumnNames = null;
52  protected string m_Realm;
53  protected FieldInfo m_DataField = null;
54 
55  protected static SqliteConnection m_Connection;
56  private static bool m_initialized;
57 
58  protected virtual Assembly Assembly
59  {
60  get { return GetType().Assembly; }
61  }
62 
63  public SQLiteGenericTableHandler(string connectionString,
64  string realm, string storeName) : base(connectionString)
65  {
66  m_Realm = realm;
67 
68  if (!m_initialized)
69  {
70  m_Connection = new SqliteConnection(connectionString);
71  //Console.WriteLine(string.Format("OPENING CONNECTION FOR {0} USING {1}", storeName, connectionString));
72  m_Connection.Open();
73 
74  if (storeName != String.Empty)
75  {
76  //SqliteConnection newConnection =
77  // (SqliteConnection)((ICloneable)m_Connection).Clone();
78  //newConnection.Open();
79 
80  //Migration m = new Migration(newConnection, Assembly, storeName);
81  Migration m = new Migration(m_Connection, Assembly, storeName);
82  m.Update();
83  //newConnection.Close();
84  //newConnection.Dispose();
85  }
86 
87  m_initialized = true;
88  }
89 
90  Type t = typeof(T);
91  FieldInfo[] fields = t.GetFields(BindingFlags.Public |
92  BindingFlags.Instance |
93  BindingFlags.DeclaredOnly);
94 
95  if (fields.Length == 0)
96  return;
97 
98  foreach (FieldInfo f in fields)
99  {
100  if (f.Name != "Data")
101  m_Fields[f.Name] = f;
102  else
103  m_DataField = f;
104  }
105  }
106 
107  private void CheckColumnNames(IDataReader reader)
108  {
109  if (m_ColumnNames != null)
110  return;
111 
112  m_ColumnNames = new List<string>();
113 
114  DataTable schemaTable = reader.GetSchemaTable();
115  foreach (DataRow row in schemaTable.Rows)
116  {
117  if (row["ColumnName"] != null &&
118  (!m_Fields.ContainsKey(row["ColumnName"].ToString())))
119  m_ColumnNames.Add(row["ColumnName"].ToString());
120  }
121  }
122 
123  public virtual T[] Get(string field, string key)
124  {
125  return Get(new string[] { field }, new string[] { key });
126  }
127 
128  public virtual T[] Get(string[] fields, string[] keys)
129  {
130  if (fields.Length != keys.Length)
131  return new T[0];
132 
133  List<string> terms = new List<string>();
134 
135  using (SqliteCommand cmd = new SqliteCommand())
136  {
137  for (int i = 0 ; i < fields.Length ; i++)
138  {
139  cmd.Parameters.Add(new SqliteParameter(":" + fields[i], keys[i]));
140  terms.Add("`" + fields[i] + "` = :" + fields[i]);
141  }
142 
143  string where = String.Join(" and ", terms.ToArray());
144 
145  string query = String.Format("select * from {0} where {1}",
146  m_Realm, where);
147 
148  cmd.CommandText = query;
149 
150  return DoQuery(cmd);
151  }
152  }
153 
154  protected T[] DoQuery(SqliteCommand cmd)
155  {
156  IDataReader reader = ExecuteReader(cmd, m_Connection);
157  if (reader == null)
158  return new T[0];
159 
160  CheckColumnNames(reader);
161 
162  List<T> result = new List<T>();
163 
164  while (reader.Read())
165  {
166  T row = new T();
167 
168  foreach (string name in m_Fields.Keys)
169  {
170  if (m_Fields[name].GetValue(row) is bool)
171  {
172  int v = Convert.ToInt32(reader[name]);
173  m_Fields[name].SetValue(row, v != 0 ? true : false);
174  }
175  else if (m_Fields[name].GetValue(row) is UUID)
176  {
177  UUID uuid = UUID.Zero;
178 
179  UUID.TryParse(reader[name].ToString(), out uuid);
180  m_Fields[name].SetValue(row, uuid);
181  }
182  else if (m_Fields[name].GetValue(row) is int)
183  {
184  int v = Convert.ToInt32(reader[name]);
185  m_Fields[name].SetValue(row, v);
186  }
187  else
188  {
189  m_Fields[name].SetValue(row, reader[name]);
190  }
191  }
192 
193  if (m_DataField != null)
194  {
195  Dictionary<string, string> data =
196  new Dictionary<string, string>();
197 
198  foreach (string col in m_ColumnNames)
199  {
200  data[col] = reader[col].ToString();
201  if (data[col] == null)
202  data[col] = String.Empty;
203  }
204 
205  m_DataField.SetValue(row, data);
206  }
207 
208  result.Add(row);
209  }
210 
211  //CloseCommand(cmd);
212 
213  return result.ToArray();
214  }
215 
216  public virtual T[] Get(string where)
217  {
218  using (SqliteCommand cmd = new SqliteCommand())
219  {
220  string query = String.Format("select * from {0} where {1}",
221  m_Realm, where);
222 
223  cmd.CommandText = query;
224 
225  return DoQuery(cmd);
226  }
227  }
228 
229  public virtual bool Store(T row)
230  {
231  using (SqliteCommand cmd = new SqliteCommand())
232  {
233  string query = "";
234  List<String> names = new List<String>();
235  List<String> values = new List<String>();
236 
237  foreach (FieldInfo fi in m_Fields.Values)
238  {
239  names.Add(fi.Name);
240  values.Add(":" + fi.Name);
241  cmd.Parameters.Add(new SqliteParameter(":" + fi.Name, fi.GetValue(row).ToString()));
242  }
243 
244  if (m_DataField != null)
245  {
246  Dictionary<string, string> data =
247  (Dictionary<string, string>)m_DataField.GetValue(row);
248 
249  foreach (KeyValuePair<string, string> kvp in data)
250  {
251  names.Add(kvp.Key);
252  values.Add(":" + kvp.Key);
253  cmd.Parameters.Add(new SqliteParameter(":" + kvp.Key, kvp.Value));
254  }
255  }
256 
257  query = String.Format("replace into {0} (`", m_Realm) + String.Join("`,`", names.ToArray()) + "`) values (" + String.Join(",", values.ToArray()) + ")";
258 
259  cmd.CommandText = query;
260 
261  if (ExecuteNonQuery(cmd, m_Connection) > 0)
262  return true;
263  }
264 
265  return false;
266  }
267 
268  public virtual bool Delete(string field, string key)
269  {
270  return Delete(new string[] { field }, new string[] { key });
271  }
272 
273  public virtual bool Delete(string[] fields, string[] keys)
274  {
275  if (fields.Length != keys.Length)
276  return false;
277 
278  List<string> terms = new List<string>();
279 
280  using (SqliteCommand cmd = new SqliteCommand())
281  {
282  for (int i = 0 ; i < fields.Length ; i++)
283  {
284  cmd.Parameters.Add(new SqliteParameter(":" + fields[i], keys[i]));
285  terms.Add("`" + fields[i] + "` = :" + fields[i]);
286  }
287 
288  string where = String.Join(" and ", terms.ToArray());
289 
290  string query = String.Format("delete from {0} where {1}", m_Realm, where);
291 
292  cmd.CommandText = query;
293 
294  return ExecuteNonQuery(cmd, m_Connection) > 0;
295  }
296  }
297  }
298 }
SQLiteGenericTableHandler(string connectionString, string realm, string storeName)
OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString key
Definition: ICM_Api.cs:31
virtual T[] Get(string[] fields, string[] keys)
A database interface class to a user profile storage system
virtual bool Delete(string[] fields, string[] keys)