29 using System.Collections.Generic;
31 using System.Reflection;
34 using OpenSim.Framework;
35 using OpenSim.Region.Framework.Interfaces;
39 namespace OpenSim.Data.PGSQL
41 public class PGSQLGenericTableHandler<T> :
PGSqlFramework where T : class, new()
43 private static readonly ILog m_log =
44 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48 protected Dictionary<string, FieldInfo> m_Fields =
49 new Dictionary<string, FieldInfo>();
51 protected Dictionary<string, string> m_FieldTypes =
new Dictionary<string, string>();
53 protected List<string> m_ColumnNames = null;
55 protected FieldInfo m_DataField = null;
57 protected virtual Assembly Assembly
59 get {
return GetType().Assembly; }
63 string realm,
string storeName)
64 : base(connectionString)
68 m_ConnectionString = connectionString;
70 if (storeName !=
String.Empty)
72 using (NpgsqlConnection conn =
new NpgsqlConnection(m_ConnectionString))
83 FieldInfo[] fields = t.GetFields(BindingFlags.Public |
84 BindingFlags.Instance |
85 BindingFlags.DeclaredOnly);
89 if (fields.Length == 0)
92 foreach (FieldInfo f
in fields)
102 private void LoadFieldTypes()
104 m_FieldTypes =
new Dictionary<string, string>();
106 string query = string.Format(
@"select column_name,data_type
107 from INFORMATION_SCHEMA.COLUMNS
108 where table_name = lower('{0}');
111 using (NpgsqlConnection conn =
new NpgsqlConnection(m_ConnectionString))
112 using (NpgsqlCommand cmd =
new NpgsqlCommand(query, conn))
115 using (NpgsqlDataReader rdr = cmd.ExecuteReader())
120 m_FieldTypes.Add((string)rdr[0], (
string)rdr[1]);
126 private
void CheckColumnNames(NpgsqlDataReader reader)
128 if (m_ColumnNames != null)
131 m_ColumnNames =
new List<string>();
133 DataTable schemaTable = reader.GetSchemaTable();
135 foreach (DataRow row
in schemaTable.Rows)
137 if (row[
"ColumnName"] != null &&
138 (!m_Fields.ContainsKey(row[
"ColumnName"].ToString())))
139 m_ColumnNames.Add(row[
"ColumnName"].ToString());
145 private List<string> GetConstraints()
147 List<string> constraints =
new List<string>();
148 string query = string.Format(
@"SELECT kcu.column_name
149 FROM information_schema.table_constraints tc
150 LEFT JOIN information_schema.key_column_usage kcu
151 ON tc.constraint_catalog = kcu.constraint_catalog
152 AND tc.constraint_schema = kcu.constraint_schema
153 AND tc.constraint_name = kcu.constraint_name
155 LEFT JOIN information_schema.referential_constraints rc
156 ON tc.constraint_catalog = rc.constraint_catalog
157 AND tc.constraint_schema = rc.constraint_schema
158 AND tc.constraint_name = rc.constraint_name
160 LEFT JOIN information_schema.constraint_column_usage ccu
161 ON rc.unique_constraint_catalog = ccu.constraint_catalog
162 AND rc.unique_constraint_schema = ccu.constraint_schema
163 AND rc.unique_constraint_name = ccu.constraint_name
165 where tc.table_name = lower('{0}')
166 and lower(tc.constraint_type) in ('primary key')
167 and kcu.column_name is not null
170 using (NpgsqlConnection conn =
new NpgsqlConnection(m_ConnectionString))
171 using (NpgsqlCommand cmd =
new NpgsqlCommand(query, conn))
174 using (NpgsqlDataReader rdr = cmd.ExecuteReader())
179 constraints.Add((string)rdr[0]);
186 public virtual T[]
Get(
string field,
string key)
188 return Get(
new string[] { field },
new string[] { key });
191 public virtual T[]
Get(
string[] fields,
string[] keys)
193 if (fields.Length != keys.Length)
196 List<string> terms =
new List<string>();
198 using (NpgsqlConnection conn =
new NpgsqlConnection(m_ConnectionString))
199 using (NpgsqlCommand cmd =
new NpgsqlCommand())
202 for (
int i = 0; i < fields.Length; i++)
204 if ( m_FieldTypes.ContainsKey(fields[i]) )
205 cmd.Parameters.Add(m_database.CreateParameter(fields[i], keys[i], m_FieldTypes[fields[i]]));
207 cmd.Parameters.Add(m_database.CreateParameter(fields[i], keys[i]));
209 terms.Add(
" \"" + fields[i] +
"\" = :" + fields[i]);
212 string where = String.Join(
" AND ", terms.ToArray());
214 string query = String.Format(
"SELECT * FROM {0} WHERE {1}",
217 cmd.Connection = conn;
218 cmd.CommandText = query;
226 List<T> result =
new List<T>();
227 if (cmd.Connection == null)
229 cmd.Connection =
new NpgsqlConnection(m_connectionString);
233 cmd.Connection.Open();
235 using (NpgsqlDataReader reader = cmd.ExecuteReader())
240 CheckColumnNames(reader);
242 while (reader.Read())
246 foreach (
string name
in m_Fields.Keys)
248 if (m_Fields[name].GetValue(row) is
bool)
250 int v = Convert.ToInt32(reader[name]);
251 m_Fields[name].SetValue(row, v != 0 ?
true :
false);
253 else if (m_Fields[name].GetValue(row) is
UUID)
255 UUID uuid = UUID.Zero;
257 UUID.TryParse(reader[name].ToString(), out uuid);
258 m_Fields[name].SetValue(row, uuid);
260 else if (m_Fields[name].GetValue(row) is int)
262 int v = Convert.ToInt32(reader[name]);
263 m_Fields[name].SetValue(row, v);
267 m_Fields[name].SetValue(row, reader[name]);
271 if (m_DataField != null)
273 Dictionary<string, string> data =
274 new Dictionary<string, string>();
276 foreach (
string col
in m_ColumnNames)
278 data[col] = reader[col].ToString();
280 if (data[col] == null)
281 data[col] = String.Empty;
284 m_DataField.SetValue(row, data);
289 return result.ToArray();
293 public virtual T[]
Get(
string where)
295 using (NpgsqlConnection conn =
new NpgsqlConnection(m_ConnectionString))
296 using (NpgsqlCommand cmd =
new NpgsqlCommand())
299 string query = String.Format(
"SELECT * FROM {0} WHERE {1}",
301 cmd.Connection = conn;
302 cmd.CommandText = query;
310 public virtual T[]
Get(
string where, NpgsqlParameter parameter)
312 using (NpgsqlConnection conn =
new NpgsqlConnection(m_ConnectionString))
313 using (NpgsqlCommand cmd =
new NpgsqlCommand())
316 string query = String.Format(
"SELECT * FROM {0} WHERE {1}",
318 cmd.Connection = conn;
319 cmd.CommandText = query;
322 cmd.Parameters.Add(parameter);
331 List<string> constraintFields = GetConstraints();
332 List<KeyValuePair<string, string>> constraints =
new List<KeyValuePair<string, string>>();
334 using (NpgsqlConnection conn =
new NpgsqlConnection(m_ConnectionString))
335 using (NpgsqlCommand cmd =
new NpgsqlCommand())
338 StringBuilder query =
new StringBuilder();
339 List<String> names =
new List<String>();
340 List<String> values =
new List<String>();
342 foreach (FieldInfo fi
in m_Fields.Values)
345 values.Add(
":" + fi.Name);
349 if (fi.GetValue(row) == null)
350 throw new NullReferenceException(
352 "[PGSQL GENERIC TABLE HANDLER]: Trying to store field {0} for {1} which is unexpectedly null",
355 if (constraintFields.Count > 0 && constraintFields.Contains(fi.Name))
357 constraints.Add(
new KeyValuePair<string, string>(fi.Name, fi.GetValue(row).ToString() ));
359 if (m_FieldTypes.ContainsKey(fi.Name))
360 cmd.Parameters.Add(m_database.CreateParameter(fi.Name, fi.GetValue(row), m_FieldTypes[fi.Name]));
362 cmd.Parameters.Add(m_database.CreateParameter(fi.Name, fi.GetValue(row)));
365 if (m_DataField != null)
367 Dictionary<string, string> data =
368 (Dictionary<string, string>)m_DataField.GetValue(row);
370 foreach (KeyValuePair<string, string> kvp
in data)
372 if (constraintFields.Count > 0 && constraintFields.Contains(kvp.Key))
374 constraints.Add(
new KeyValuePair<string, string>(kvp.Key, kvp.Key));
377 values.Add(
":" + kvp.Key);
379 if (m_FieldTypes.ContainsKey(kvp.Key))
380 cmd.Parameters.Add(m_database.CreateParameter(
"" + kvp.Key, kvp.Value, m_FieldTypes[kvp.Key]));
382 cmd.Parameters.Add(m_database.CreateParameter(
"" + kvp.Key, kvp.Value));
387 query.AppendFormat(
"UPDATE {0} SET ", m_Realm);
389 for (i = 0; i < names.Count - 1; i++)
391 query.AppendFormat(
"\"{0}\" = {1}, ", names[i], values[i]);
393 query.AppendFormat(
"\"{0}\" = {1} ", names[i], values[i]);
394 if (constraints.Count > 0)
396 List<string> terms =
new List<string>();
397 for (
int j = 0; j < constraints.Count; j++)
399 terms.Add(String.Format(
" \"{0}\" = :{0}", constraints[j].Key));
401 string where = String.Join(
" AND ", terms.ToArray());
402 query.AppendFormat(
" WHERE {0} ", where);
405 cmd.Connection = conn;
406 cmd.CommandText = query.ToString();
409 if (cmd.ExecuteNonQuery() > 0)
418 query =
new StringBuilder();
419 query.AppendFormat(
"INSERT INTO {0} (\"", m_Realm);
420 query.Append(String.Join(
"\",\"", names.ToArray()));
421 query.Append(
"\") values (" + String.Join(
",", values.ToArray()) +
")");
422 cmd.Connection = conn;
423 cmd.CommandText = query.ToString();
429 if (cmd.ExecuteNonQuery() > 0)
439 return Delete(
new string[] { field },
new string[] { key });
442 public virtual bool Delete(
string[] fields,
string[] keys)
444 if (fields.Length != keys.Length)
447 List<string> terms =
new List<string>();
449 using (NpgsqlConnection conn =
new NpgsqlConnection(m_ConnectionString))
450 using (NpgsqlCommand cmd =
new NpgsqlCommand())
452 for (
int i = 0; i < fields.Length; i++)
454 if (m_FieldTypes.ContainsKey(fields[i]))
455 cmd.Parameters.Add(m_database.CreateParameter(fields[i], keys[i], m_FieldTypes[fields[i]]));
457 cmd.Parameters.Add(m_database.CreateParameter(fields[i], keys[i]));
459 terms.Add(
" \"" + fields[i] +
"\" = :" + fields[i]);
462 string where = String.Join(
" AND ", terms.ToArray());
464 string query = String.Format(
"DELETE FROM {0} WHERE {1}", m_Realm, where);
466 cmd.Connection = conn;
467 cmd.CommandText = query;
470 if (cmd.ExecuteNonQuery() > 0)
480 return GetCount(
new string[] { field },
new string[] { key });
483 public long GetCount(
string[] fields,
string[] keys)
485 if (fields.Length != keys.Length)
488 List<string> terms =
new List<string>();
490 using (NpgsqlCommand cmd =
new NpgsqlCommand())
492 for (
int i = 0; i < fields.Length; i++)
494 cmd.Parameters.AddWithValue(fields[i], keys[i]);
495 terms.Add(
"\"" + fields[i] +
"\" = :" + fields[i]);
498 string where = String.Join(
" and ", terms.ToArray());
500 string query = String.Format(
"select count(*) from {0} where {1}",
503 cmd.CommandText = query;
505 Object result = DoQueryScalar(cmd);
507 return Convert.ToInt64(result);
513 using (NpgsqlCommand cmd =
new NpgsqlCommand())
515 string query = String.Format(
"select count(*) from {0} where {1}",
518 cmd.CommandText = query;
520 object result = DoQueryScalar(cmd);
522 return Convert.ToInt64(result);
528 using (NpgsqlConnection dbcon =
new NpgsqlConnection(m_ConnectionString))
531 cmd.Connection = dbcon;
533 return cmd.ExecuteScalar();
virtual T[] Get(string[] fields, string[] keys)
long GetCount(string field, string key)
string m_ConnectionString
virtual T[] Get(string where, NpgsqlParameter parameter)
virtual T[] Get(string where)
virtual bool Delete(string field, string key)
T[] DoQuery(NpgsqlCommand cmd)
PGSQLGenericTableHandler(string connectionString, string realm, string storeName)
OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString key
long GetCount(string where)
A management class for the MS SQL Storage Engine
virtual T[] Get(string field, string key)
A database interface class to a user profile storage system
long GetCount(string[] fields, string[] keys)
virtual bool Store(T row)
virtual bool Delete(string[] fields, string[] keys)
object DoQueryScalar(NpgsqlCommand cmd)