aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
authorSean Dague2007-08-27 22:03:21 +0000
committerSean Dague2007-08-27 22:03:21 +0000
commite92f2accadfa601aefc3c2106e7b589db797def0 (patch)
treeb43b0912964b6992b7fdceaa204d746687b54b04 /OpenSim
parentremove sqlite3-inventory, this db is autocreated now (diff)
downloadopensim-SC-e92f2accadfa601aefc3c2106e7b589db797def0.zip
opensim-SC-e92f2accadfa601aefc3c2106e7b589db797def0.tar.gz
opensim-SC-e92f2accadfa601aefc3c2106e7b589db797def0.tar.bz2
opensim-SC-e92f2accadfa601aefc3c2106e7b589db797def0.tar.xz
first pass implementation of sqlite storage for user data. This
isn't functional enough to use yet, but does compile. Should be ready for testing in another day or so.
Diffstat (limited to 'OpenSim')
-rw-r--r--OpenSim/Framework/Data.SQLite/SQLiteUserData.cs705
1 files changed, 705 insertions, 0 deletions
diff --git a/OpenSim/Framework/Data.SQLite/SQLiteUserData.cs b/OpenSim/Framework/Data.SQLite/SQLiteUserData.cs
new file mode 100644
index 0000000..84e58fa
--- /dev/null
+++ b/OpenSim/Framework/Data.SQLite/SQLiteUserData.cs
@@ -0,0 +1,705 @@
1/*
2* Copyright (c) Contributors, http://www.openmetaverse.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.IO;
30using libsecondlife;
31using OpenSim.Framework.Utilities;
32using System.Data;
33using System.Data.SqlTypes;
34using Mono.Data.SqliteClient;
35using OpenSim.Framework.Console;
36
37namespace OpenSim.Framework.Data.SQLite
38{
39 /// <summary>
40 /// A User storage interface for the DB4o database system
41 /// </summary>
42 public class SQLiteUserData : IUserData
43 {
44 /// <summary>
45 /// The database manager
46 /// </summary>
47
48 /// <summary>
49 /// Artificial constructor called upon plugin load
50 /// </summary>
51 private const string userSelect = "select * from users";
52 private DataSet ds;
53 private SqliteDataAdapter da;
54
55 public void Initialise()
56 {
57 SqliteConnection conn = new SqliteConnection("URI=file:userprofiles.db,version=3");
58 TestTables(conn);
59
60 ds = new DataSet();
61 da = new SqliteDataAdapter(new SqliteCommand(userSelect, conn));
62
63 ds.Tables.Add(createUsersTable());
64 ds.Tables.Add(createUserAgentsTable());
65
66 setupUserCommands(da, conn);
67 da.Fill(ds.Tables["users"]);
68
69 return;
70 }
71
72 /// <summary>
73 /// Loads a specified user profile from a UUID
74 /// </summary>
75 /// <param name="uuid">The users UUID</param>
76 /// <returns>A user profile</returns>
77 public UserProfileData getUserByUUID(LLUUID uuid)
78 {
79 DataRow row = ds.Tables["users"].Rows.Find(uuid);
80 if(row != null) {
81 return buildUserProfile(row);
82 } else {
83 return null;
84 }
85 }
86
87 /// <summary>
88 /// Returns a user by searching for its name
89 /// </summary>
90 /// <param name="name">The users account name</param>
91 /// <returns>A matching users profile</returns>
92 public UserProfileData getUserByName(string name)
93 {
94 return getUserByName(name.Split(' ')[0], name.Split(' ')[1]);
95 }
96
97 /// <summary>
98 /// Returns a user by searching for its name
99 /// </summary>
100 /// <param name="fname">The first part of the users account name</param>
101 /// <param name="lname">The second part of the users account name</param>
102 /// <returns>A matching users profile</returns>
103 public UserProfileData getUserByName(string fname, string lname)
104 {
105 string select = "surname = '" + lname + "' and username = '" + fname + "'";
106 DataRow[] rows = ds.Tables["users"].Select(select);
107 if(rows.Length > 0) {
108 return buildUserProfile(rows[0]);
109 } else {
110 return null;
111 }
112 }
113
114 /// <summary>
115 /// Returns a user by UUID direct
116 /// </summary>
117 /// <param name="uuid">The users account ID</param>
118 /// <returns>A matching users profile</returns>
119 public UserAgentData getAgentByUUID(LLUUID uuid)
120 {
121 try
122 {
123 return getUserByUUID(uuid).currentAgent;
124 }
125 catch (Exception)
126 {
127 return null;
128 }
129 }
130
131 /// <summary>
132 /// Returns a session by account name
133 /// </summary>
134 /// <param name="name">The account name</param>
135 /// <returns>The users session agent</returns>
136 public UserAgentData getAgentByName(string name)
137 {
138 return getAgentByName(name.Split(' ')[0], name.Split(' ')[1]);
139 }
140
141 /// <summary>
142 /// Returns a session by account name
143 /// </summary>
144 /// <param name="fname">The first part of the users account name</param>
145 /// <param name="lname">The second part of the users account name</param>
146 /// <returns>A user agent</returns>
147 public UserAgentData getAgentByName(string fname, string lname)
148 {
149 try
150 {
151 return getUserByName(fname,lname).currentAgent;
152 }
153 catch (Exception)
154 {
155 return null;
156 }
157 }
158
159 /// <summary>
160 /// Creates a new user profile
161 /// </summary>
162 /// <param name="user">The profile to add to the database</param>
163 public void addNewUserProfile(UserProfileData user)
164 {
165 DataTable users = ds.Tables["users"];
166 DataRow row = users.Rows.Find(user.UUID);
167 if (row == null)
168 {
169 row = users.NewRow();
170 fillUserRow(row, user);
171 users.Rows.Add(row);
172 }
173 else
174 {
175 fillUserRow(row, user);
176 }
177 }
178
179 /// <summary>
180 /// Creates a new user profile
181 /// </summary>
182 /// <param name="user">The profile to add to the database</param>
183 /// <returns>True on success, false on error</returns>
184 public bool updateUserProfile(UserProfileData user)
185 {
186 DataTable users = ds.Tables["users"];
187 DataRow row = users.Rows.Find(user.UUID);
188 if (row == null)
189 {
190 row = users.NewRow();
191 fillUserRow(row, user);
192 users.Rows.Add(row);
193 }
194 else
195 {
196 fillUserRow(row, user);
197 }
198 return true;
199 }
200
201
202
203 /// <summary>
204 /// Creates a new user agent
205 /// </summary>
206 /// <param name="agent">The agent to add to the database</param>
207 public void addNewUserAgent(UserAgentData agent)
208 {
209 // Do nothing. yet.
210 }
211
212 /// <summary>
213 /// Transfers money between two user accounts
214 /// </summary>
215 /// <param name="from">Starting account</param>
216 /// <param name="to">End account</param>
217 /// <param name="amount">The amount to move</param>
218 /// <returns>Success?</returns>
219 public bool moneyTransferRequest(LLUUID from, LLUUID to, uint amount)
220 {
221 return true;
222 }
223
224 /// <summary>
225 /// Transfers inventory between two accounts
226 /// </summary>
227 /// <remarks>Move to inventory server</remarks>
228 /// <param name="from">Senders account</param>
229 /// <param name="to">Recievers account</param>
230 /// <param name="item">Inventory item</param>
231 /// <returns>Success?</returns>
232 public bool inventoryTransferRequest(LLUUID from, LLUUID to, LLUUID item)
233 {
234 return true;
235 }
236
237 /// <summary>
238 /// Returns the name of the storage provider
239 /// </summary>
240 /// <returns>Storage provider name</returns>
241 public string getName()
242 {
243 return "Sqlite Userdata";
244 }
245
246 /// <summary>
247 /// Returns the version of the storage provider
248 /// </summary>
249 /// <returns>Storage provider version</returns>
250 public string getVersion()
251 {
252 return "0.1";
253 }
254
255 /***********************************************************************
256 *
257 * DataTable creation
258 *
259 **********************************************************************/
260 /***********************************************************************
261 *
262 * Database Definition Functions
263 *
264 * This should be db agnostic as we define them in ADO.NET terms
265 *
266 **********************************************************************/
267
268 private void createCol(DataTable dt, string name, System.Type type)
269 {
270 DataColumn col = new DataColumn(name, type);
271 dt.Columns.Add(col);
272 }
273
274 private DataTable createUsersTable()
275 {
276 DataTable users = new DataTable("users");
277
278 createCol(users, "UUID", typeof(System.String));
279 createCol(users, "username", typeof(System.String));
280 createCol(users, "surname", typeof(System.String));
281 createCol(users, "passwordHash", typeof(System.String));
282 createCol(users, "passwordSalt", typeof(System.String));
283
284 createCol(users, "homeRegion", typeof(System.UInt32));
285 createCol(users, "homeLocationX", typeof(System.Double));
286 createCol(users, "homeLocationY", typeof(System.Double));
287 createCol(users, "homeLocationZ", typeof(System.Double));
288 createCol(users, "homeLookAtX", typeof(System.Double));
289 createCol(users, "homeLookAtY", typeof(System.Double));
290 createCol(users, "homeLookAtZ", typeof(System.Double));
291 createCol(users, "created", typeof(System.Int32));
292 createCol(users, "lastLogin", typeof(System.Int32));
293 createCol(users, "rootInventoryFolderID", typeof(System.String));
294 createCol(users, "userInventoryURI", typeof(System.String));
295 createCol(users, "userAssetURI", typeof(System.String));
296 createCol(users, "profileCanDoMask", typeof(System.UInt32));
297 createCol(users, "profileWantDoMask", typeof(System.UInt32));
298 createCol(users, "profileAboutText", typeof(System.String));
299 createCol(users, "profileFirstText", typeof(System.String));
300 createCol(users, "profileImage", typeof(System.String));
301 createCol(users, "profileFirstImage", typeof(System.String));
302 // Add in contraints
303 users.PrimaryKey = new DataColumn[] { users.Columns["UUID"] };
304 return users;
305 }
306
307 private DataTable createUserAgentsTable()
308 {
309 DataTable ua = new DataTable("useragents");
310 // this is the UUID of the user
311 createCol(ua, "UUID", typeof(System.String));
312 createCol(ua, "agentIP", typeof(System.String));
313 createCol(ua, "agentPort", typeof(System.UInt32));
314 createCol(ua, "agentOnline", typeof(System.Boolean));
315 createCol(ua, "sessionID", typeof(System.String));
316 createCol(ua, "secureSessionID", typeof(System.String));
317 createCol(ua, "regionID", typeof(System.String));
318 createCol(ua, "loginTime", typeof(System.Int32));
319 createCol(ua, "logoutTime", typeof(System.Int32));
320 createCol(ua, "currentRegion", typeof(System.String));
321 createCol(ua, "currentHandle", typeof(System.UInt32));
322 // vectors
323 createCol(ua, "currentPosX", typeof(System.Double));
324 createCol(ua, "currentPosY", typeof(System.Double));
325 createCol(ua, "currentPosZ", typeof(System.Double));
326 // constraints
327 ua.PrimaryKey = new DataColumn[] { ua.Columns["UUID"] };
328
329 return ua;
330 }
331
332 /***********************************************************************
333 *
334 * Convert between ADO.NET <=> OpenSim Objects
335 *
336 * These should be database independant
337 *
338 **********************************************************************/
339
340 private UserProfileData buildUserProfile(DataRow row)
341 {
342 // TODO: this doesn't work yet because something more
343 // interesting has to be done to actually get these values
344 // back out. Not enough time to figure it out yet.
345 UserProfileData user = new UserProfileData();
346 user.UUID = new LLUUID((String)row["UUID"]);
347 user.username = (string)row["username"];
348 user.surname = (string)row["surname"];
349 user.passwordHash = (string)row["passwordHash"];
350 user.passwordSalt = (string)row["passwordSalt"];
351
352 user.homeRegion = Convert.ToUInt32(row["homeRegion"]);
353 user.homeLocation = new LLVector3(
354 Convert.ToSingle(row["homeLocationX"]),
355 Convert.ToSingle(row["homeLocationY"]),
356 Convert.ToSingle(row["homeLocationZ"])
357 );
358 user.homeLookAt = new LLVector3(
359 Convert.ToSingle(row["homeLookAtX"]),
360 Convert.ToSingle(row["homeLookAtY"]),
361 Convert.ToSingle(row["homeLookAtZ"])
362 );
363 user.created = Convert.ToInt32(row["created"]);
364 user.lastLogin = Convert.ToInt32(row["lastLogin"]);
365 user.rootInventoryFolderID = new LLUUID((string)row["rootInventoryFolderID"]);
366 user.userInventoryURI = (string)row["userInventoryURI"];
367 user.userAssetURI = (string)row["userAssetURI"];
368 user.profileCanDoMask = Convert.ToUInt32(row["profileCanDoMask"]);
369 user.profileWantDoMask = Convert.ToUInt32(row["profileWantDoMask"]);
370 user.profileAboutText = (string)row["profileAboutText"];
371 user.profileFirstText = (string)row["profileFirstText"];
372 user.profileImage = new LLUUID((string)row["profileImage"]);
373 user.profileFirstImage = new LLUUID((string)row["profileFirstImage"]);
374 return user;
375 }
376
377 private void fillUserRow(DataRow row, UserProfileData user)
378 {
379 row["UUID"] = user.UUID;
380 row["username"] = user.username;
381 row["surname"] = user.surname;
382 row["passwordHash"] = user.passwordHash;
383 row["passwordSalt"] = user.passwordSalt;
384
385
386 row["homeRegion"] = user.homeRegion;
387 row["homeLocationX"] = user.homeLocation.X;
388 row["homeLocationY"] = user.homeLocation.Y;
389 row["homeLocationZ"] = user.homeLocation.Z;
390 row["homeLookAtX"] = user.homeLookAt.X;
391 row["homeLookAtY"] = user.homeLookAt.Y;
392 row["homeLookAtZ"] = user.homeLookAt.Z;
393
394 row["created"] = user.created;
395 row["lastLogin"] = user.lastLogin;
396 row["rootInventoryFolderID"] = user.rootInventoryFolderID;
397 row["userInventoryURI"] = user.userInventoryURI;
398 row["userAssetURI"] = user.userAssetURI;
399 row["profileCanDoMask"] = user.profileCanDoMask;
400 row["profileWantDoMask"] = user.profileWantDoMask;
401 row["profileAboutText"] = user.profileAboutText;
402 row["profileFirstText"] = user.profileFirstText;
403 row["profileImage"] = user.profileImage;
404 row["profileFirstImage"] = user.profileFirstImage;
405 }
406
407// private PrimitiveBaseShape buildShape(DataRow row)
408// {
409// PrimitiveBaseShape s = new PrimitiveBaseShape();
410// s.Scale = new LLVector3(
411// Convert.ToSingle(row["ScaleX"]),
412// Convert.ToSingle(row["ScaleY"]),
413// Convert.ToSingle(row["ScaleZ"])
414// );
415// // paths
416// s.PCode = Convert.ToByte(row["PCode"]);
417// s.PathBegin = Convert.ToUInt16(row["PathBegin"]);
418// s.PathEnd = Convert.ToUInt16(row["PathEnd"]);
419// s.PathScaleX = Convert.ToByte(row["PathScaleX"]);
420// s.PathScaleY = Convert.ToByte(row["PathScaleY"]);
421// s.PathShearX = Convert.ToByte(row["PathShearX"]);
422// s.PathShearY = Convert.ToByte(row["PathShearY"]);
423// s.PathSkew = Convert.ToSByte(row["PathSkew"]);
424// s.PathCurve = Convert.ToByte(row["PathCurve"]);
425// s.PathRadiusOffset = Convert.ToSByte(row["PathRadiusOffset"]);
426// s.PathRevolutions = Convert.ToByte(row["PathRevolutions"]);
427// s.PathTaperX = Convert.ToSByte(row["PathTaperX"]);
428// s.PathTaperY = Convert.ToSByte(row["PathTaperY"]);
429// s.PathTwist = Convert.ToSByte(row["PathTwist"]);
430// s.PathTwistBegin = Convert.ToSByte(row["PathTwistBegin"]);
431// // profile
432// s.ProfileBegin = Convert.ToUInt16(row["ProfileBegin"]);
433// s.ProfileEnd = Convert.ToUInt16(row["ProfileEnd"]);
434// s.ProfileCurve = Convert.ToByte(row["ProfileCurve"]);
435// s.ProfileHollow = Convert.ToByte(row["ProfileHollow"]);
436// // text TODO: this isn't right] = but I'm not sure the right
437// // way to specify this as a blob atm
438// s.TextureEntry = (byte[])row["Texture"];
439// s.ExtraParams = (byte[])row["ExtraParams"];
440// // System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
441// // string texture = encoding.GetString((Byte[])row["Texture"]);
442// // if (!texture.StartsWith("<"))
443// // {
444// // //here so that we can still work with old format database files (ie from before I added xml serialization)
445// // LLObject.TextureEntry textureEntry = null;
446// // textureEntry = new LLObject.TextureEntry(new LLUUID(texture));
447// // s.TextureEntry = textureEntry.ToBytes();
448// // }
449// // else
450// // {
451// // TextureBlock textureEntry = TextureBlock.FromXmlString(texture);
452// // s.TextureEntry = textureEntry.TextureData;
453// // s.ExtraParams = textureEntry.ExtraParams;
454// // }
455
456// return s;
457// }
458
459// private void fillShapeRow(DataRow row, SceneObjectPart prim)
460// {
461// PrimitiveBaseShape s = prim.Shape;
462// row["UUID"] = prim.UUID;
463// // shape is an enum
464// row["Shape"] = 0;
465// // vectors
466// row["ScaleX"] = s.Scale.X;
467// row["ScaleY"] = s.Scale.Y;
468// row["ScaleZ"] = s.Scale.Z;
469// // paths
470// row["PCode"] = s.PCode;
471// row["PathBegin"] = s.PathBegin;
472// row["PathEnd"] = s.PathEnd;
473// row["PathScaleX"] = s.PathScaleX;
474// row["PathScaleY"] = s.PathScaleY;
475// row["PathShearX"] = s.PathShearX;
476// row["PathShearY"] = s.PathShearY;
477// row["PathSkew"] = s.PathSkew;
478// row["PathCurve"] = s.PathCurve;
479// row["PathRadiusOffset"] = s.PathRadiusOffset;
480// row["PathRevolutions"] = s.PathRevolutions;
481// row["PathTaperX"] = s.PathTaperX;
482// row["PathTaperY"] = s.PathTaperY;
483// row["PathTwist"] = s.PathTwist;
484// row["PathTwistBegin"] = s.PathTwistBegin;
485// // profile
486// row["ProfileBegin"] = s.ProfileBegin;
487// row["ProfileEnd"] = s.ProfileEnd;
488// row["ProfileCurve"] = s.ProfileCurve;
489// row["ProfileHollow"] = s.ProfileHollow;
490// // text TODO: this isn't right] = but I'm not sure the right
491// // way to specify this as a blob atm
492
493// // And I couldn't work out how to save binary data either
494// // seems that the texture colum is being treated as a string in the Datarow
495// // if you do a .getType() on it, it returns string, while the other columns return correct type
496// // MW[10-08-07]
497// // Added following xml hack but not really ideal , also ExtraParams isn't currently part of the database
498// // am a bit worried about adding it now as some people will have old format databases, so for now including that data in this xml data
499// // MW[17-08-07]
500// row["Texture"] = s.TextureEntry;
501// row["ExtraParams"] = s.ExtraParams;
502// // TextureBlock textureBlock = new TextureBlock(s.TextureEntry);
503// // textureBlock.ExtraParams = s.ExtraParams;
504// // System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
505// // row["Texture"] = encoding.GetBytes(textureBlock.ToXMLString());
506// }
507
508 /***********************************************************************
509 *
510 * SQL Statement Creation Functions
511 *
512 * These functions create SQL statements for update, insert, and create.
513 * They can probably be factored later to have a db independant
514 * portion and a db specific portion
515 *
516 **********************************************************************/
517
518 private SqliteCommand createInsertCommand(string table, DataTable dt)
519 {
520 /**
521 * This is subtle enough to deserve some commentary.
522 * Instead of doing *lots* and *lots of hardcoded strings
523 * for database definitions we'll use the fact that
524 * realistically all insert statements look like "insert
525 * into A(b, c) values(:b, :c) on the parameterized query
526 * front. If we just have a list of b, c, etc... we can
527 * generate these strings instead of typing them out.
528 */
529 string[] cols = new string[dt.Columns.Count];
530 for (int i = 0; i < dt.Columns.Count; i++) {
531 DataColumn col = dt.Columns[i];
532 cols[i] = col.ColumnName;
533 }
534
535 string sql = "insert into " + table + "(";
536 sql += String.Join(", ", cols);
537 // important, the first ':' needs to be here, the rest get added in the join
538 sql += ") values (:";
539 sql += String.Join(", :", cols);
540 sql += ")";
541 SqliteCommand cmd = new SqliteCommand(sql);
542
543 // this provides the binding for all our parameters, so
544 // much less code than it used to be
545 foreach (DataColumn col in dt.Columns)
546 {
547 cmd.Parameters.Add(createSqliteParameter(col.ColumnName, col.DataType));
548 }
549 return cmd;
550 }
551
552 private SqliteCommand createUpdateCommand(string table, string pk, DataTable dt)
553 {
554 string sql = "update " + table + " set ";
555 string subsql = "";
556 foreach (DataColumn col in dt.Columns)
557 {
558 if (subsql.Length > 0)
559 { // a map function would rock so much here
560 subsql += ", ";
561 }
562 subsql += col.ColumnName + "= :" + col.ColumnName;
563 }
564 sql += subsql;
565 sql += " where " + pk;
566 SqliteCommand cmd = new SqliteCommand(sql);
567
568 // this provides the binding for all our parameters, so
569 // much less code than it used to be
570
571 foreach (DataColumn col in dt.Columns)
572 {
573 cmd.Parameters.Add(createSqliteParameter(col.ColumnName, col.DataType));
574 }
575 return cmd;
576 }
577
578
579 private string defineTable(DataTable dt)
580 {
581 string sql = "create table " + dt.TableName + "(";
582 string subsql = "";
583 foreach (DataColumn col in dt.Columns)
584 {
585 if (subsql.Length > 0)
586 { // a map function would rock so much here
587 subsql += ",\n";
588 }
589 subsql += col.ColumnName + " " + sqliteType(col.DataType);
590 if(col == dt.PrimaryKey[0])
591 {
592 subsql += " primary key";
593 }
594 }
595 sql += subsql;
596 sql += ")";
597 return sql;
598 }
599
600 /***********************************************************************
601 *
602 * Database Binding functions
603 *
604 * These will be db specific due to typing, and minor differences
605 * in databases.
606 *
607 **********************************************************************/
608
609 ///<summary>
610 /// This is a convenience function that collapses 5 repetitive
611 /// lines for defining SqliteParameters to 2 parameters:
612 /// column name and database type.
613 ///
614 /// It assumes certain conventions like :param as the param
615 /// name to replace in parametrized queries, and that source
616 /// version is always current version, both of which are fine
617 /// for us.
618 ///</summary>
619 ///<returns>a built sqlite parameter</returns>
620 private SqliteParameter createSqliteParameter(string name, System.Type type)
621 {
622 SqliteParameter param = new SqliteParameter();
623 param.ParameterName = ":" + name;
624 param.DbType = dbtypeFromType(type);
625 param.SourceColumn = name;
626 param.SourceVersion = DataRowVersion.Current;
627 return param;
628 }
629
630 private void setupUserCommands(SqliteDataAdapter da, SqliteConnection conn)
631 {
632 da.InsertCommand = createInsertCommand("users", ds.Tables["users"]);
633 da.InsertCommand.Connection = conn;
634
635 da.UpdateCommand = createUpdateCommand("users", "UUID=:UUID", ds.Tables["users"]);
636 da.UpdateCommand.Connection = conn;
637
638 SqliteCommand delete = new SqliteCommand("delete from users where UUID = :UUID");
639 delete.Parameters.Add(createSqliteParameter("UUID", typeof(System.String)));
640 delete.Connection = conn;
641 da.DeleteCommand = delete;
642 }
643
644 private void InitDB(SqliteConnection conn)
645 {
646 string createUsers = defineTable(createUsersTable());
647 SqliteCommand pcmd = new SqliteCommand(createUsers, conn);
648 conn.Open();
649 pcmd.ExecuteNonQuery();
650 conn.Close();
651 }
652
653 private bool TestTables(SqliteConnection conn)
654 {
655 SqliteCommand cmd = new SqliteCommand(userSelect, conn);
656 SqliteDataAdapter pDa = new SqliteDataAdapter(cmd);
657 DataSet tmpDS = new DataSet();
658 try {
659 pDa.Fill(tmpDS, "users");
660 } catch (Mono.Data.SqliteClient.SqliteSyntaxException) {
661 MainLog.Instance.Verbose("DATASTORE", "SQLite Database doesn't exist... creating");
662 InitDB(conn);
663 }
664 return true;
665 }
666
667 /***********************************************************************
668 *
669 * Type conversion functions
670 *
671 **********************************************************************/
672
673 private DbType dbtypeFromType(Type type)
674 {
675 if (type == typeof(System.String)) {
676 return DbType.String;
677 } else if (type == typeof(System.Int32)) {
678 return DbType.Int32;
679 } else if (type == typeof(System.Double)) {
680 return DbType.Double;
681 } else if (type == typeof(System.Byte[])) {
682 return DbType.Binary;
683 } else {
684 return DbType.String;
685 }
686 }
687
688 // this is something we'll need to implement for each db
689 // slightly differently.
690 private string sqliteType(Type type)
691 {
692 if (type == typeof(System.String)) {
693 return "varchar(255)";
694 } else if (type == typeof(System.Int32)) {
695 return "integer";
696 } else if (type == typeof(System.Double)) {
697 return "float";
698 } else if (type == typeof(System.Byte[])) {
699 return "blob";
700 } else {
701 return "string";
702 }
703 }
704 }
705}