aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/Storage/OpenSim.DataStore.MonoSqlite/MonoSqliteDataStore.cs743
1 files changed, 394 insertions, 349 deletions
diff --git a/OpenSim/Region/Storage/OpenSim.DataStore.MonoSqlite/MonoSqliteDataStore.cs b/OpenSim/Region/Storage/OpenSim.DataStore.MonoSqlite/MonoSqliteDataStore.cs
index fb4f53f..87df8fb 100644
--- a/OpenSim/Region/Storage/OpenSim.DataStore.MonoSqlite/MonoSqliteDataStore.cs
+++ b/OpenSim/Region/Storage/OpenSim.DataStore.MonoSqlite/MonoSqliteDataStore.cs
@@ -31,6 +31,11 @@ namespace OpenSim.DataStore.MonoSqliteStorage
31 private SqliteDataAdapter primDa; 31 private SqliteDataAdapter primDa;
32 private SqliteDataAdapter shapeDa; 32 private SqliteDataAdapter shapeDa;
33 33
34 /***********************************************************************
35 *
36 * Public Interface Functions
37 *
38 **********************************************************************/
34 public void Initialise(string dbfile, string dbname) 39 public void Initialise(string dbfile, string dbname)
35 { 40 {
36 string connectionString = "URI=file:" + dbfile + ",version=3"; 41 string connectionString = "URI=file:" + dbfile + ",version=3";
@@ -65,129 +70,276 @@ namespace OpenSim.DataStore.MonoSqliteStorage
65 return; 70 return;
66 } 71 }
67 72
68 ///<summary> 73 public void StoreObject(SceneObjectGroup obj, LLUUID regionUUID)
69 /// This is a convenience function that collapses 5 repetitive
70 /// lines for defining SqliteParameters to 2 parameters:
71 /// column name and database type.
72 ///
73 /// It assumes certain conventions like :param as the param
74 /// name to replace in parametrized queries, and that source
75 /// version is always current version, both of which are fine
76 /// for us.
77 ///</summary>
78 ///<returns>a built sqlite parameter</returns>
79 private SqliteParameter createSqliteParameter(string name, System.Type type)
80 { 74 {
81 SqliteParameter param = new SqliteParameter(); 75 foreach (SceneObjectPart prim in obj.Children.Values)
82 param.ParameterName = ":" + name; 76 {
83 param.DbType = dbtypeFromType(type); 77 addPrim(prim, obj.UUID);
84 param.SourceColumn = name; 78 }
85 param.SourceVersion = DataRowVersion.Current; 79
86 return param; 80 // MainLog.Instance.Verbose("Attempting to do database update....");
81 primDa.Update(ds, "prims");
82 shapeDa.Update(ds, "primshapes");
83 // MainLog.Instance.Verbose("Dump of prims:", ds.GetXml());
87 } 84 }
88 85
89 private DbType dbtypeFromType(Type type) 86 public void RemoveObject(LLUUID obj, LLUUID regionUUID)
90 { 87 {
91 if (type == typeof(System.String)) { 88 DataTable prims = ds.Tables["prims"];
92 return DbType.String; 89 DataTable shapes = ds.Tables["primshapes"];
93 } else if (type == typeof(System.Int32)) { 90
94 return DbType.Int32; 91 string selectExp = "SceneGroupID = '" + obj.ToString() + "'";
95 } else if (type == typeof(System.Double)) { 92 DataRow[] primRows = prims.Select(selectExp);
96 return DbType.Double; 93 foreach (DataRow row in primRows)
97 } else if (type == typeof(System.Byte[])) { 94 {
98 return DbType.Binary; 95 LLUUID uuid = new LLUUID((string)row["UUID"]);
99 } else { 96 DataRow shapeRow = shapes.Rows.Find(uuid);
100 return DbType.String; 97 if (shapeRow != null)
98 {
99 shapeRow.Delete();
100 }
101 row.Delete();
101 } 102 }
103
104 primDa.Update(ds, "prims");
105 shapeDa.Update(ds, "primshapes");
102 } 106 }
103 107
104 private SqliteCommand createInsertCommand(string table, DataTable dt) 108 public List<SceneObjectGroup> LoadObjects(LLUUID regionUUID)
105 { 109 {
106 /** 110 Dictionary<LLUUID, SceneObjectGroup> createdObjects = new Dictionary<LLUUID, SceneObjectGroup>();
107 * This is subtle enough to deserve some commentary. 111 List<SceneObjectGroup> retvals = new List<SceneObjectGroup>();
108 * Instead of doing *lots* and *lots of hardcoded strings
109 * for database definitions we'll use the fact that
110 * realistically all insert statements look like "insert
111 * into A(b, c) values(:b, :c) on the parameterized query
112 * front. If we just have a list of b, c, etc... we can
113 * generate these strings instead of typing them out.
114 */
115 string[] cols = new string[dt.Columns.Count];
116 for (int i = 0; i < dt.Columns.Count; i++) {
117 DataColumn col = dt.Columns[i];
118 cols[i] = col.ColumnName;
119 }
120 112
121 string sql = "insert into " + table + "("; 113 DataTable prims = ds.Tables["prims"];
122 sql += String.Join(", ", cols); 114 DataTable shapes = ds.Tables["primshapes"];
123 // important, the first ':' needs to be here, the rest get added in the join
124 sql += ") values (:";
125 sql += String.Join(", :", cols);
126 sql += ")";
127 SqliteCommand cmd = new SqliteCommand(sql);
128 115
129 // this provides the binding for all our parameters, so 116 foreach (DataRow primRow in prims.Rows)
130 // much less code than it used to be
131 foreach (DataColumn col in dt.Columns)
132 { 117 {
133 cmd.Parameters.Add(createSqliteParameter(col.ColumnName, col.DataType)); 118 string uuid = (string)primRow["UUID"];
119 string objID = (string)primRow["SceneGroupID"];
120 if (uuid == objID) //is new SceneObjectGroup ?
121 {
122 SceneObjectGroup group = new SceneObjectGroup();
123 SceneObjectPart prim = buildPrim(primRow);
124 DataRow shapeRow = shapes.Rows.Find(prim.UUID);
125 if (shapeRow != null)
126 {
127 prim.Shape = buildShape(shapeRow);
128 }
129 else
130 {
131 Console.WriteLine("No shape found for prim in storage, so setting default box shape");
132 prim.Shape = BoxShape.Default;
133 }
134 group.AddPart(prim);
135 group.RootPart = prim;
136
137 createdObjects.Add(group.UUID, group);
138 retvals.Add(group);
139 }
140 else
141 {
142 SceneObjectPart prim = buildPrim(primRow);
143 DataRow shapeRow = shapes.Rows.Find(prim.UUID);
144 if (shapeRow != null)
145 {
146 prim.Shape = buildShape(shapeRow);
147 }
148 else
149 {
150 Console.WriteLine("No shape found for prim in storage, so setting default box shape");
151 prim.Shape = BoxShape.Default;
152 }
153 createdObjects[new LLUUID(objID)].AddPart(prim);
154 }
134 } 155 }
135 return cmd; 156
157 MainLog.Instance.Verbose("DATASTORE", "Sqlite - LoadObjects found " + prims.Rows.Count + " primitives");
158
159 return retvals;
136 } 160 }
137 161
138 private SqliteCommand createUpdateCommand(string table, string pk, DataTable dt) 162 public void StoreTerrain(double[,] ter)
139 { 163 {
140 string sql = "update " + table + " set "; 164
141 string subsql = ""; 165 }
142 foreach (DataColumn col in dt.Columns) 166
167 public double[,] LoadTerrain()
168 {
169 return null;
170 }
171
172 public void RemoveLandObject(uint id)
173 {
174
175 }
176
177 public void StoreParcel(Land parcel)
178 {
179
180 }
181
182 public List<Land> LoadLandObjects()
183 {
184 return new List<Land>();
185 }
186
187 public void Shutdown()
188 {
189 // TODO: DataSet commit
190 }
191
192 public class TextureBlock
193 {
194 public byte[] TextureData;
195 public byte[] ExtraParams = new byte[1];
196
197 public TextureBlock(byte[] data)
143 { 198 {
144 if (subsql.Length > 0) 199 TextureData = data;
145 { // a map function would rock so much here
146 subsql += ", ";
147 }
148 subsql += col.ColumnName + "= :" + col.ColumnName;
149 } 200 }
150 sql += subsql;
151 sql += " where " + pk;
152 SqliteCommand cmd = new SqliteCommand(sql);
153 201
154 // this provides the binding for all our parameters, so 202 public TextureBlock()
155 // much less code than it used to be 203 {
156 204
157 foreach (DataColumn col in dt.Columns) 205 }
206
207 public string ToXMLString()
158 { 208 {
159 cmd.Parameters.Add(createSqliteParameter(col.ColumnName, col.DataType)); 209 StringWriter sw = new StringWriter();
210 XmlTextWriter writer = new XmlTextWriter(sw);
211 XmlSerializer serializer = new XmlSerializer(typeof(TextureBlock));
212 serializer.Serialize(writer, this);
213 return sw.ToString();
214 }
215
216 public static TextureBlock FromXmlString(string xmlData)
217 {
218 TextureBlock textureEntry = null;
219 StringReader sr = new StringReader(xmlData);
220 XmlTextReader reader = new XmlTextReader(sr);
221 XmlSerializer serializer = new XmlSerializer(typeof(TextureBlock));
222 textureEntry = (TextureBlock)serializer.Deserialize(reader);
223 reader.Close();
224 sr.Close();
225 return textureEntry;
160 } 226 }
161 return cmd;
162 } 227 }
163 228
164 private void setupPrimCommands(SqliteDataAdapter da, SqliteConnection conn) 229 /***********************************************************************
230 *
231 * Database Definition Functions
232 *
233 * This should be db agnostic as we define them in ADO.NET terms
234 *
235 **********************************************************************/
236
237 private void createCol(DataTable dt, string name, System.Type type)
165 { 238 {
166 da.InsertCommand = createInsertCommand("prims", ds.Tables["prims"]); 239 DataColumn col = new DataColumn(name, type);
167 da.InsertCommand.Connection = conn; 240 dt.Columns.Add(col);
241 }
168 242
169 da.UpdateCommand = createUpdateCommand("prims", "UUID=:UUID", ds.Tables["prims"]); 243 private DataTable createPrimTable()
170 da.UpdateCommand.Connection = conn; 244 {
245 DataTable prims = new DataTable("prims");
171 246
172 SqliteCommand delete = new SqliteCommand("delete from prims where UUID = :UUID"); 247 createCol(prims, "UUID", typeof(System.String));
173 delete.Parameters.Add(createSqliteParameter("UUID", typeof(System.String))); 248 createCol(prims, "ParentID", typeof(System.Int32));
174 delete.Connection = conn; 249 createCol(prims, "CreationDate", typeof(System.Int32));
175 da.DeleteCommand = delete; 250 createCol(prims, "Name", typeof(System.String));
251 createCol(prims, "SceneGroupID", typeof(System.String));
252 // various text fields
253 createCol(prims, "Text", typeof(System.String));
254 createCol(prims, "Description", typeof(System.String));
255 createCol(prims, "SitName", typeof(System.String));
256 createCol(prims, "TouchName", typeof(System.String));
257 // permissions
258 createCol(prims, "CreatorID", typeof(System.String));
259 createCol(prims, "OwnerID", typeof(System.String));
260 createCol(prims, "GroupID", typeof(System.String));
261 createCol(prims, "LastOwnerID", typeof(System.String));
262 createCol(prims, "OwnerMask", typeof(System.Int32));
263 createCol(prims, "NextOwnerMask", typeof(System.Int32));
264 createCol(prims, "GroupMask", typeof(System.Int32));
265 createCol(prims, "EveryoneMask", typeof(System.Int32));
266 createCol(prims, "BaseMask", typeof(System.Int32));
267 // vectors
268 createCol(prims, "PositionX", typeof(System.Double));
269 createCol(prims, "PositionY", typeof(System.Double));
270 createCol(prims, "PositionZ", typeof(System.Double));
271 createCol(prims, "GroupPositionX", typeof(System.Double));
272 createCol(prims, "GroupPositionY", typeof(System.Double));
273 createCol(prims, "GroupPositionZ", typeof(System.Double));
274 createCol(prims, "VelocityX", typeof(System.Double));
275 createCol(prims, "VelocityY", typeof(System.Double));
276 createCol(prims, "VelocityZ", typeof(System.Double));
277 createCol(prims, "AngularVelocityX", typeof(System.Double));
278 createCol(prims, "AngularVelocityY", typeof(System.Double));
279 createCol(prims, "AngularVelocityZ", typeof(System.Double));
280 createCol(prims, "AccelerationX", typeof(System.Double));
281 createCol(prims, "AccelerationY", typeof(System.Double));
282 createCol(prims, "AccelerationZ", typeof(System.Double));
283 // quaternions
284 createCol(prims, "RotationX", typeof(System.Double));
285 createCol(prims, "RotationY", typeof(System.Double));
286 createCol(prims, "RotationZ", typeof(System.Double));
287 createCol(prims, "RotationW", typeof(System.Double));
288
289 // Add in contraints
290 prims.PrimaryKey = new DataColumn[] { prims.Columns["UUID"] };
291
292 return prims;
176 } 293 }
177 294
178 private void setupShapeCommands(SqliteDataAdapter da, SqliteConnection conn) 295 private DataTable createShapeTable()
179 { 296 {
180 da.InsertCommand = createInsertCommand("primshapes", ds.Tables["primshapes"]); 297 DataTable shapes = new DataTable("primshapes");
181 da.InsertCommand.Connection = conn; 298 createCol(shapes, "UUID", typeof(System.String));
299 // shape is an enum
300 createCol(shapes, "Shape", typeof(System.Int32));
301 // vectors
302 createCol(shapes, "ScaleX", typeof(System.Double));
303 createCol(shapes, "ScaleY", typeof(System.Double));
304 createCol(shapes, "ScaleZ", typeof(System.Double));
305 // paths
306 createCol(shapes, "PCode", typeof(System.Int32));
307 createCol(shapes, "PathBegin", typeof(System.Int32));
308 createCol(shapes, "PathEnd", typeof(System.Int32));
309 createCol(shapes, "PathScaleX", typeof(System.Int32));
310 createCol(shapes, "PathScaleY", typeof(System.Int32));
311 createCol(shapes, "PathShearX", typeof(System.Int32));
312 createCol(shapes, "PathShearY", typeof(System.Int32));
313 createCol(shapes, "PathSkew", typeof(System.Int32));
314 createCol(shapes, "PathCurve", typeof(System.Int32));
315 createCol(shapes, "PathRadiusOffset", typeof(System.Int32));
316 createCol(shapes, "PathRevolutions", typeof(System.Int32));
317 createCol(shapes, "PathTaperX", typeof(System.Int32));
318 createCol(shapes, "PathTaperY", typeof(System.Int32));
319 createCol(shapes, "PathTwist", typeof(System.Int32));
320 createCol(shapes, "PathTwistBegin", typeof(System.Int32));
321 // profile
322 createCol(shapes, "ProfileBegin", typeof(System.Int32));
323 createCol(shapes, "ProfileEnd", typeof(System.Int32));
324 createCol(shapes, "ProfileCurve", typeof(System.Int32));
325 createCol(shapes, "ProfileHollow", typeof(System.Int32));
326 // text TODO: this isn't right, but I'm not sure the right
327 // way to specify this as a blob atm
328 createCol(shapes, "Texture", typeof(System.Byte[]));
329 createCol(shapes, "ExtraParams", typeof(System.Byte[]));
182 330
183 da.UpdateCommand = createUpdateCommand("primshapes", "UUID=:UUID", ds.Tables["primshapes"]); 331 shapes.PrimaryKey = new DataColumn[] { shapes.Columns["UUID"] };
184 da.UpdateCommand.Connection = conn;
185 332
186 SqliteCommand delete = new SqliteCommand("delete from primshapes where UUID = :UUID"); 333 return shapes;
187 delete.Parameters.Add(createSqliteParameter("UUID", typeof(System.String)));
188 delete.Connection = conn;
189 da.DeleteCommand = delete;
190 } 334 }
335
336 /***********************************************************************
337 *
338 * Convert between ADO.NET <=> OpenSim Objects
339 *
340 * These should be database independant
341 *
342 **********************************************************************/
191 343
192 private SceneObjectPart buildPrim(DataRow row) 344 private SceneObjectPart buildPrim(DataRow row)
193 { 345 {
@@ -424,163 +576,157 @@ namespace OpenSim.DataStore.MonoSqliteStorage
424 fillShapeRow(shapeRow, prim); 576 fillShapeRow(shapeRow, prim);
425 } 577 }
426 } 578 }
579
580 /***********************************************************************
581 *
582 * SQL Statement Creation Functions
583 *
584 * These functions create SQL statements for update, insert, and create.
585 * They can probably be factored later to have a db independant
586 * portion and a db specific portion
587 *
588 **********************************************************************/
427 589
428 public void StoreObject(SceneObjectGroup obj, LLUUID regionUUID) 590 private SqliteCommand createInsertCommand(string table, DataTable dt)
429 { 591 {
430 foreach (SceneObjectPart prim in obj.Children.Values) 592 /**
431 { 593 * This is subtle enough to deserve some commentary.
432 addPrim(prim, obj.UUID); 594 * Instead of doing *lots* and *lots of hardcoded strings
595 * for database definitions we'll use the fact that
596 * realistically all insert statements look like "insert
597 * into A(b, c) values(:b, :c) on the parameterized query
598 * front. If we just have a list of b, c, etc... we can
599 * generate these strings instead of typing them out.
600 */
601 string[] cols = new string[dt.Columns.Count];
602 for (int i = 0; i < dt.Columns.Count; i++) {
603 DataColumn col = dt.Columns[i];
604 cols[i] = col.ColumnName;
433 } 605 }
434 606
435 // MainLog.Instance.Verbose("Attempting to do database update...."); 607 string sql = "insert into " + table + "(";
436 primDa.Update(ds, "prims"); 608 sql += String.Join(", ", cols);
437 shapeDa.Update(ds, "primshapes"); 609 // important, the first ':' needs to be here, the rest get added in the join
438 // MainLog.Instance.Verbose("Dump of prims:", ds.GetXml()); 610 sql += ") values (:";
611 sql += String.Join(", :", cols);
612 sql += ")";
613 SqliteCommand cmd = new SqliteCommand(sql);
614
615 // this provides the binding for all our parameters, so
616 // much less code than it used to be
617 foreach (DataColumn col in dt.Columns)
618 {
619 cmd.Parameters.Add(createSqliteParameter(col.ColumnName, col.DataType));
620 }
621 return cmd;
439 } 622 }
440 623
441 public void RemoveObject(LLUUID obj, LLUUID regionUUID) 624 private SqliteCommand createUpdateCommand(string table, string pk, DataTable dt)
442 { 625 {
443 DataTable prims = ds.Tables["prims"]; 626 string sql = "update " + table + " set ";
444 DataTable shapes = ds.Tables["primshapes"]; 627 string subsql = "";
445 628 foreach (DataColumn col in dt.Columns)
446 string selectExp = "SceneGroupID = '" + obj.ToString() + "'";
447 DataRow[] primRows = prims.Select(selectExp);
448 foreach (DataRow row in primRows)
449 { 629 {
450 LLUUID uuid = new LLUUID((string)row["UUID"]); 630 if (subsql.Length > 0)
451 DataRow shapeRow = shapes.Rows.Find(uuid); 631 { // a map function would rock so much here
452 if (shapeRow != null) 632 subsql += ", ";
453 {
454 shapeRow.Delete();
455 } 633 }
456 row.Delete(); 634 subsql += col.ColumnName + "= :" + col.ColumnName;
457 } 635 }
636 sql += subsql;
637 sql += " where " + pk;
638 SqliteCommand cmd = new SqliteCommand(sql);
458 639
459 primDa.Update(ds, "prims"); 640 // this provides the binding for all our parameters, so
460 shapeDa.Update(ds, "primshapes"); 641 // much less code than it used to be
642
643 foreach (DataColumn col in dt.Columns)
644 {
645 cmd.Parameters.Add(createSqliteParameter(col.ColumnName, col.DataType));
646 }
647 return cmd;
461 } 648 }
462 649
463 public List<SceneObjectGroup> LoadObjects(LLUUID regionUUID)
464 {
465 Dictionary<LLUUID, SceneObjectGroup> createdObjects = new Dictionary<LLUUID, SceneObjectGroup>();
466 List<SceneObjectGroup> retvals = new List<SceneObjectGroup>();
467 650
468 DataTable prims = ds.Tables["prims"]; 651 private string defineTable(DataTable dt)
469 DataTable shapes = ds.Tables["primshapes"]; 652 {
470 653 string sql = "create table " + dt.TableName + "(";
471 foreach (DataRow primRow in prims.Rows) 654 string subsql = "";
655 foreach (DataColumn col in dt.Columns)
472 { 656 {
473 string uuid = (string)primRow["UUID"]; 657 if (subsql.Length > 0)
474 string objID = (string)primRow["SceneGroupID"]; 658 { // a map function would rock so much here
475 if (uuid == objID) //is new SceneObjectGroup ? 659 subsql += ",\n";
476 {
477 SceneObjectGroup group = new SceneObjectGroup();
478 SceneObjectPart prim = buildPrim(primRow);
479 DataRow shapeRow = shapes.Rows.Find(prim.UUID);
480 if (shapeRow != null)
481 {
482 prim.Shape = buildShape(shapeRow);
483 }
484 else
485 {
486 Console.WriteLine("No shape found for prim in storage, so setting default box shape");
487 prim.Shape = BoxShape.Default;
488 }
489 group.AddPart(prim);
490 group.RootPart = prim;
491
492 createdObjects.Add(group.UUID, group);
493 retvals.Add(group);
494 } 660 }
495 else 661 subsql += col.ColumnName + " " + sqliteType(col.DataType);
662 if(col == dt.PrimaryKey[0])
496 { 663 {
497 SceneObjectPart prim = buildPrim(primRow); 664 subsql += " primary key";
498 DataRow shapeRow = shapes.Rows.Find(prim.UUID);
499 if (shapeRow != null)
500 {
501 prim.Shape = buildShape(shapeRow);
502 }
503 else
504 {
505 Console.WriteLine("No shape found for prim in storage, so setting default box shape");
506 prim.Shape = BoxShape.Default;
507 }
508 createdObjects[new LLUUID(objID)].AddPart(prim);
509 } 665 }
510 } 666 }
511 667 sql += subsql;
512 MainLog.Instance.Verbose("DATASTORE", "Sqlite - LoadObjects found " + prims.Rows.Count + " primitives"); 668 sql += ")";
513 669 return sql;
514 return retvals;
515 }
516
517 public void StoreTerrain(double[,] ter)
518 {
519
520 } 670 }
521 671
522 public double[,] LoadTerrain() 672 /***********************************************************************
523 { 673 *
524 return null; 674 * Database Binding functions
525 } 675 *
676 * These will be db specific due to typing, and minor differences
677 * in databases.
678 *
679 **********************************************************************/
526 680
527 public void RemoveLandObject(uint id) 681 ///<summary>
682 /// This is a convenience function that collapses 5 repetitive
683 /// lines for defining SqliteParameters to 2 parameters:
684 /// column name and database type.
685 ///
686 /// It assumes certain conventions like :param as the param
687 /// name to replace in parametrized queries, and that source
688 /// version is always current version, both of which are fine
689 /// for us.
690 ///</summary>
691 ///<returns>a built sqlite parameter</returns>
692 private SqliteParameter createSqliteParameter(string name, System.Type type)
528 { 693 {
529 694 SqliteParameter param = new SqliteParameter();
695 param.ParameterName = ":" + name;
696 param.DbType = dbtypeFromType(type);
697 param.SourceColumn = name;
698 param.SourceVersion = DataRowVersion.Current;
699 return param;
530 } 700 }
531 701
532 public void StoreParcel(Land parcel) 702 private void setupPrimCommands(SqliteDataAdapter da, SqliteConnection conn)
533 { 703 {
704 da.InsertCommand = createInsertCommand("prims", ds.Tables["prims"]);
705 da.InsertCommand.Connection = conn;
534 706
535 } 707 da.UpdateCommand = createUpdateCommand("prims", "UUID=:UUID", ds.Tables["prims"]);
536 708 da.UpdateCommand.Connection = conn;
537 public List<Land> LoadLandObjects()
538 {
539 return new List<Land>();
540 }
541 709
542 public void Shutdown() 710 SqliteCommand delete = new SqliteCommand("delete from prims where UUID = :UUID");
543 { 711 delete.Parameters.Add(createSqliteParameter("UUID", typeof(System.String)));
544 // TODO: DataSet commit 712 delete.Connection = conn;
713 da.DeleteCommand = delete;
545 } 714 }
546 715
547 public class TextureBlock 716 private void setupShapeCommands(SqliteDataAdapter da, SqliteConnection conn)
548 { 717 {
549 public byte[] TextureData; 718 da.InsertCommand = createInsertCommand("primshapes", ds.Tables["primshapes"]);
550 public byte[] ExtraParams = new byte[1]; 719 da.InsertCommand.Connection = conn;
551
552 public TextureBlock(byte[] data)
553 {
554 TextureData = data;
555 }
556
557 public TextureBlock()
558 {
559
560 }
561 720
562 public string ToXMLString() 721 da.UpdateCommand = createUpdateCommand("primshapes", "UUID=:UUID", ds.Tables["primshapes"]);
563 { 722 da.UpdateCommand.Connection = conn;
564 StringWriter sw = new StringWriter();
565 XmlTextWriter writer = new XmlTextWriter(sw);
566 XmlSerializer serializer = new XmlSerializer(typeof(TextureBlock));
567 serializer.Serialize(writer, this);
568 return sw.ToString();
569 }
570 723
571 public static TextureBlock FromXmlString(string xmlData) 724 SqliteCommand delete = new SqliteCommand("delete from primshapes where UUID = :UUID");
572 { 725 delete.Parameters.Add(createSqliteParameter("UUID", typeof(System.String)));
573 TextureBlock textureEntry = null; 726 delete.Connection = conn;
574 StringReader sr = new StringReader(xmlData); 727 da.DeleteCommand = delete;
575 XmlTextReader reader = new XmlTextReader(sr);
576 XmlSerializer serializer = new XmlSerializer(typeof(TextureBlock));
577 textureEntry = (TextureBlock)serializer.Deserialize(reader);
578 reader.Close();
579 sr.Close();
580 return textureEntry;
581 }
582 } 728 }
583 729
584 private void InitDB(SqliteConnection conn) 730 private void InitDB(SqliteConnection conn)
585 { 731 {
586 string createPrims = defineTable(createPrimTable()); 732 string createPrims = defineTable(createPrimTable());
@@ -594,42 +740,6 @@ namespace OpenSim.DataStore.MonoSqliteStorage
594 conn.Close(); 740 conn.Close();
595 } 741 }
596 742
597 private string defineTable(DataTable dt)
598 {
599 string sql = "create table " + dt.TableName + "(";
600 string subsql = "";
601 foreach (DataColumn col in dt.Columns)
602 {
603 if (subsql.Length > 0)
604 { // a map function would rock so much here
605 subsql += ",\n";
606 }
607 subsql += col.ColumnName + " " + sqliteType(col.DataType);
608 if(col == dt.PrimaryKey[0])
609 {
610 subsql += " primary key";
611 }
612 }
613 sql += subsql;
614 sql += ")";
615 return sql;
616 }
617
618 private string sqliteType(Type type)
619 {
620 if (type == typeof(System.String)) {
621 return "varchar(255)";
622 } else if (type == typeof(System.Int32)) {
623 return "integer";
624 } else if (type == typeof(System.Double)) {
625 return "float";
626 } else if (type == typeof(System.Byte[])) {
627 return "blob";
628 } else {
629 return "string";
630 }
631 }
632
633 private bool TestTables(SqliteConnection conn) 743 private bool TestTables(SqliteConnection conn)
634 { 744 {
635 SqliteCommand primSelectCmd = new SqliteCommand(primSelect, conn); 745 SqliteCommand primSelectCmd = new SqliteCommand(primSelect, conn);
@@ -664,107 +774,42 @@ namespace OpenSim.DataStore.MonoSqliteStorage
664 return true; 774 return true;
665 } 775 }
666 776
667 /// Methods after this point are big data definition 777 /***********************************************************************
668 /// methods, and aren't really interesting unless you are 778 *
669 /// adjusting the schema. 779 * Type conversion functions
670 780 *
671 private void createCol(DataTable dt, string name, System.Type type) 781 **********************************************************************/
672 { 782
673 DataColumn col = new DataColumn(name, type); 783 private DbType dbtypeFromType(Type type)
674 dt.Columns.Add(col);
675 }
676
677 private DataTable createPrimTable()
678 { 784 {
679 DataTable prims = new DataTable("prims"); 785 if (type == typeof(System.String)) {
680 786 return DbType.String;
681 createCol(prims, "UUID", typeof(System.String)); 787 } else if (type == typeof(System.Int32)) {
682 createCol(prims, "ParentID", typeof(System.Int32)); 788 return DbType.Int32;
683 createCol(prims, "CreationDate", typeof(System.Int32)); 789 } else if (type == typeof(System.Double)) {
684 createCol(prims, "Name", typeof(System.String)); 790 return DbType.Double;
685 createCol(prims, "SceneGroupID", typeof(System.String)); 791 } else if (type == typeof(System.Byte[])) {
686 // various text fields 792 return DbType.Binary;
687 createCol(prims, "Text", typeof(System.String)); 793 } else {
688 createCol(prims, "Description", typeof(System.String)); 794 return DbType.String;
689 createCol(prims, "SitName", typeof(System.String)); 795 }
690 createCol(prims, "TouchName", typeof(System.String));
691 // permissions
692 createCol(prims, "CreatorID", typeof(System.String));
693 createCol(prims, "OwnerID", typeof(System.String));
694 createCol(prims, "GroupID", typeof(System.String));
695 createCol(prims, "LastOwnerID", typeof(System.String));
696 createCol(prims, "OwnerMask", typeof(System.Int32));
697 createCol(prims, "NextOwnerMask", typeof(System.Int32));
698 createCol(prims, "GroupMask", typeof(System.Int32));
699 createCol(prims, "EveryoneMask", typeof(System.Int32));
700 createCol(prims, "BaseMask", typeof(System.Int32));
701 // vectors
702 createCol(prims, "PositionX", typeof(System.Double));
703 createCol(prims, "PositionY", typeof(System.Double));
704 createCol(prims, "PositionZ", typeof(System.Double));
705 createCol(prims, "GroupPositionX", typeof(System.Double));
706 createCol(prims, "GroupPositionY", typeof(System.Double));
707 createCol(prims, "GroupPositionZ", typeof(System.Double));
708 createCol(prims, "VelocityX", typeof(System.Double));
709 createCol(prims, "VelocityY", typeof(System.Double));
710 createCol(prims, "VelocityZ", typeof(System.Double));
711 createCol(prims, "AngularVelocityX", typeof(System.Double));
712 createCol(prims, "AngularVelocityY", typeof(System.Double));
713 createCol(prims, "AngularVelocityZ", typeof(System.Double));
714 createCol(prims, "AccelerationX", typeof(System.Double));
715 createCol(prims, "AccelerationY", typeof(System.Double));
716 createCol(prims, "AccelerationZ", typeof(System.Double));
717 // quaternions
718 createCol(prims, "RotationX", typeof(System.Double));
719 createCol(prims, "RotationY", typeof(System.Double));
720 createCol(prims, "RotationZ", typeof(System.Double));
721 createCol(prims, "RotationW", typeof(System.Double));
722
723 // Add in contraints
724 prims.PrimaryKey = new DataColumn[] { prims.Columns["UUID"] };
725
726 return prims;
727 } 796 }
728 797
729 private DataTable createShapeTable() 798 // this is something we'll need to implement for each db
799 // slightly differently.
800 private string sqliteType(Type type)
730 { 801 {
731 DataTable shapes = new DataTable("primshapes"); 802 if (type == typeof(System.String)) {
732 createCol(shapes, "UUID", typeof(System.String)); 803 return "varchar(255)";
733 // shape is an enum 804 } else if (type == typeof(System.Int32)) {
734 createCol(shapes, "Shape", typeof(System.Int32)); 805 return "integer";
735 // vectors 806 } else if (type == typeof(System.Double)) {
736 createCol(shapes, "ScaleX", typeof(System.Double)); 807 return "float";
737 createCol(shapes, "ScaleY", typeof(System.Double)); 808 } else if (type == typeof(System.Byte[])) {
738 createCol(shapes, "ScaleZ", typeof(System.Double)); 809 return "blob";
739 // paths 810 } else {
740 createCol(shapes, "PCode", typeof(System.Int32)); 811 return "string";
741 createCol(shapes, "PathBegin", typeof(System.Int32)); 812 }
742 createCol(shapes, "PathEnd", typeof(System.Int32));
743 createCol(shapes, "PathScaleX", typeof(System.Int32));
744 createCol(shapes, "PathScaleY", typeof(System.Int32));
745 createCol(shapes, "PathShearX", typeof(System.Int32));
746 createCol(shapes, "PathShearY", typeof(System.Int32));
747 createCol(shapes, "PathSkew", typeof(System.Int32));
748 createCol(shapes, "PathCurve", typeof(System.Int32));
749 createCol(shapes, "PathRadiusOffset", typeof(System.Int32));
750 createCol(shapes, "PathRevolutions", typeof(System.Int32));
751 createCol(shapes, "PathTaperX", typeof(System.Int32));
752 createCol(shapes, "PathTaperY", typeof(System.Int32));
753 createCol(shapes, "PathTwist", typeof(System.Int32));
754 createCol(shapes, "PathTwistBegin", typeof(System.Int32));
755 // profile
756 createCol(shapes, "ProfileBegin", typeof(System.Int32));
757 createCol(shapes, "ProfileEnd", typeof(System.Int32));
758 createCol(shapes, "ProfileCurve", typeof(System.Int32));
759 createCol(shapes, "ProfileHollow", typeof(System.Int32));
760 // text TODO: this isn't right, but I'm not sure the right
761 // way to specify this as a blob atm
762 createCol(shapes, "Texture", typeof(System.Byte[]));
763 createCol(shapes, "ExtraParams", typeof(System.Byte[]));
764
765 shapes.PrimaryKey = new DataColumn[] { shapes.Columns["UUID"] };
766
767 return shapes;
768 } 813 }
769 } 814 }
770} 815}