diff options
author | Sean Dague | 2007-08-22 21:09:38 +0000 |
---|---|---|
committer | Sean Dague | 2007-08-22 21:09:38 +0000 |
commit | 1fa2d487aa89bea9cc5f03b6bb5ed88b319243c7 (patch) | |
tree | 5d289ee859b4a03a281d33e9380ea8fa643f3f74 | |
parent | Debug shows how many bytes (total) a script (assembly) uses after compile and... (diff) | |
download | opensim-SC-1fa2d487aa89bea9cc5f03b6bb5ed88b319243c7.zip opensim-SC-1fa2d487aa89bea9cc5f03b6bb5ed88b319243c7.tar.gz opensim-SC-1fa2d487aa89bea9cc5f03b6bb5ed88b319243c7.tar.bz2 opensim-SC-1fa2d487aa89bea9cc5f03b6bb5ed88b319243c7.tar.xz |
Bit of refactoring of the sqlite storage code to build the
data definition in ado.net objects up front. This makes auto
generating the sql commands work a lot more reliably.
-rw-r--r-- | OpenSim/Region/Storage/OpenSim.DataStore.MonoSqlite/MonoSqliteDataStore.cs | 237 |
1 files changed, 187 insertions, 50 deletions
diff --git a/OpenSim/Region/Storage/OpenSim.DataStore.MonoSqlite/MonoSqliteDataStore.cs b/OpenSim/Region/Storage/OpenSim.DataStore.MonoSqlite/MonoSqliteDataStore.cs index aa90eac..2d52a2a 100644 --- a/OpenSim/Region/Storage/OpenSim.DataStore.MonoSqlite/MonoSqliteDataStore.cs +++ b/OpenSim/Region/Storage/OpenSim.DataStore.MonoSqlite/MonoSqliteDataStore.cs | |||
@@ -52,17 +52,16 @@ namespace OpenSim.DataStore.MonoSqliteStorage | |||
52 | // We fill the data set, now we've got copies in memory for the information | 52 | // We fill the data set, now we've got copies in memory for the information |
53 | // TODO: see if the linkage actually holds. | 53 | // TODO: see if the linkage actually holds. |
54 | // primDa.FillSchema(ds, SchemaType.Source, "PrimSchema"); | 54 | // primDa.FillSchema(ds, SchemaType.Source, "PrimSchema"); |
55 | try { | 55 | TestPrimsTable(conn); |
56 | primDa.Fill(ds, "prims"); | 56 | |
57 | } catch (Mono.Data.SqliteClient.SqliteSyntaxException) { | 57 | ds.Tables.Add(createPrimTable()); |
58 | InitDB(conn); | 58 | DataTable prims = ds.Tables["prims"]; |
59 | primDa.Fill(ds, "prims"); | 59 | primDa.Fill(prims); |
60 | } | 60 | MainLog.Instance.Verbose(ds.GetXmlSchema()); |
61 | 61 | ||
62 | shapeDa.Fill(ds, "primshapes"); | 62 | shapeDa.Fill(ds, "primshapes"); |
63 | ds.AcceptChanges(); | 63 | ds.AcceptChanges(); |
64 | 64 | ||
65 | DataTable prims = ds.Tables["prims"]; | ||
66 | prims.PrimaryKey = new DataColumn[] { prims.Columns["UUID"] }; | 65 | prims.PrimaryKey = new DataColumn[] { prims.Columns["UUID"] }; |
67 | setupPrimCommands(primDa, conn); | 66 | setupPrimCommands(primDa, conn); |
68 | 67 | ||
@@ -85,18 +84,32 @@ namespace OpenSim.DataStore.MonoSqliteStorage | |||
85 | /// for us. | 84 | /// for us. |
86 | ///</summary> | 85 | ///</summary> |
87 | ///<returns>a built sqlite parameter</returns> | 86 | ///<returns>a built sqlite parameter</returns> |
88 | private SqliteParameter createSqliteParameter(string name, DbType type) | 87 | private SqliteParameter createSqliteParameter(string name, System.Type type) |
89 | { | 88 | { |
90 | SqliteParameter param = new SqliteParameter(); | 89 | SqliteParameter param = new SqliteParameter(); |
91 | param.ParameterName = ":" + name; | 90 | param.ParameterName = ":" + name; |
92 | param.DbType = type; | 91 | param.DbType = dbtypeFromType(type); |
93 | param.SourceColumn = name; | 92 | param.SourceColumn = name; |
94 | param.SourceVersion = DataRowVersion.Current; | 93 | param.SourceVersion = DataRowVersion.Current; |
95 | return param; | 94 | return param; |
96 | } | 95 | } |
97 | 96 | ||
97 | private DbType dbtypeFromType(Type type) | ||
98 | { | ||
99 | if (type == typeof(System.String)) { | ||
100 | return DbType.String; | ||
101 | } else if (type == typeof(System.Int32)) { | ||
102 | return DbType.Int32; | ||
103 | } else if (type == typeof(System.Double)) { | ||
104 | return DbType.Double; | ||
105 | } else if (type == typeof(System.Byte[])) { | ||
106 | return DbType.Binary; | ||
107 | } else { | ||
108 | return DbType.String; | ||
109 | } | ||
110 | } | ||
98 | 111 | ||
99 | private SqliteCommand createInsertCommand(string table, Dictionary<string, DbType> defs) | 112 | private SqliteCommand createInsertCommand(string table, DataTable dt) |
100 | { | 113 | { |
101 | /** | 114 | /** |
102 | * This is subtle enough to deserve some commentary. | 115 | * This is subtle enough to deserve some commentary. |
@@ -107,8 +120,11 @@ namespace OpenSim.DataStore.MonoSqliteStorage | |||
107 | * front. If we just have a list of b, c, etc... we can | 120 | * front. If we just have a list of b, c, etc... we can |
108 | * generate these strings instead of typing them out. | 121 | * generate these strings instead of typing them out. |
109 | */ | 122 | */ |
110 | string[] cols = new string[defs.Keys.Count]; | 123 | string[] cols = new string[dt.Columns.Count]; |
111 | defs.Keys.CopyTo(cols, 0); | 124 | for (int i = 0; i < dt.Columns.Count; i++) { |
125 | DataColumn col = dt.Columns[i]; | ||
126 | cols[i] = col.ColumnName; | ||
127 | } | ||
112 | 128 | ||
113 | string sql = "insert into " + table + "("; | 129 | string sql = "insert into " + table + "("; |
114 | sql += String.Join(", ", cols); | 130 | sql += String.Join(", ", cols); |
@@ -120,24 +136,28 @@ namespace OpenSim.DataStore.MonoSqliteStorage | |||
120 | 136 | ||
121 | // this provides the binding for all our parameters, so | 137 | // this provides the binding for all our parameters, so |
122 | // much less code than it used to be | 138 | // much less code than it used to be |
123 | foreach (KeyValuePair<string, DbType> kvp in defs) | 139 | foreach (DataColumn col in dt.Columns) |
124 | { | 140 | { |
125 | cmd.Parameters.Add(createSqliteParameter(kvp.Key, kvp.Value)); | 141 | cmd.Parameters.Add(createSqliteParameter(col.ColumnName, col.DataType)); |
126 | } | 142 | } |
143 | // foreach (KeyValuePair<string, DbType> kvp in defs) | ||
144 | // { | ||
145 | // cmd.Parameters.Add(createSqliteParameter(kvp.Key, kvp.Value)); | ||
146 | // } | ||
127 | return cmd; | 147 | return cmd; |
128 | } | 148 | } |
129 | 149 | ||
130 | private SqliteCommand createUpdateCommand(string table, string pk, Dictionary<string, DbType> defs) | 150 | private SqliteCommand createUpdateCommand(string table, string pk, DataTable dt) |
131 | { | 151 | { |
132 | string sql = "update " + table + " set "; | 152 | string sql = "update " + table + " set "; |
133 | string subsql = ""; | 153 | string subsql = ""; |
134 | foreach (string key in defs.Keys) | 154 | foreach (DataColumn col in dt.Columns) |
135 | { | 155 | { |
136 | if (subsql.Length > 0) | 156 | if (subsql.Length > 0) |
137 | { // a map function would rock so much here | 157 | { // a map function would rock so much here |
138 | subsql += ", "; | 158 | subsql += ", "; |
139 | } | 159 | } |
140 | subsql += key + "= :" + key; | 160 | subsql += col.ColumnName + "= :" + col.ColumnName; |
141 | } | 161 | } |
142 | sql += subsql; | 162 | sql += subsql; |
143 | sql += " where " + pk; | 163 | sql += " where " + pk; |
@@ -145,41 +165,38 @@ namespace OpenSim.DataStore.MonoSqliteStorage | |||
145 | 165 | ||
146 | // this provides the binding for all our parameters, so | 166 | // this provides the binding for all our parameters, so |
147 | // much less code than it used to be | 167 | // much less code than it used to be |
148 | foreach (KeyValuePair<string, DbType> kvp in defs) | 168 | |
169 | foreach (DataColumn col in dt.Columns) | ||
149 | { | 170 | { |
150 | cmd.Parameters.Add(createSqliteParameter(kvp.Key, kvp.Value)); | 171 | cmd.Parameters.Add(createSqliteParameter(col.ColumnName, col.DataType)); |
151 | } | 172 | } |
152 | return cmd; | 173 | return cmd; |
153 | } | 174 | } |
154 | 175 | ||
155 | private void setupPrimCommands(SqliteDataAdapter da, SqliteConnection conn) | 176 | private void setupPrimCommands(SqliteDataAdapter da, SqliteConnection conn) |
156 | { | 177 | { |
157 | Dictionary<string, DbType> primDataDefs = createPrimDataDefs(); | 178 | da.InsertCommand = createInsertCommand("prims", ds.Tables["prims"]); |
158 | |||
159 | da.InsertCommand = createInsertCommand("prims", primDataDefs); | ||
160 | da.InsertCommand.Connection = conn; | 179 | da.InsertCommand.Connection = conn; |
161 | 180 | ||
162 | da.UpdateCommand = createUpdateCommand("prims", "UUID=:UUID", primDataDefs); | 181 | da.UpdateCommand = createUpdateCommand("prims", "UUID=:UUID", ds.Tables["prims"]); |
163 | da.UpdateCommand.Connection = conn; | 182 | da.UpdateCommand.Connection = conn; |
164 | 183 | ||
165 | SqliteCommand delete = new SqliteCommand("delete from prims where UUID = :UUID"); | 184 | SqliteCommand delete = new SqliteCommand("delete from prims where UUID = :UUID"); |
166 | delete.Parameters.Add(createSqliteParameter("UUID", DbType.String)); | 185 | delete.Parameters.Add(createSqliteParameter("UUID", typeof(System.String))); |
167 | delete.Connection = conn; | 186 | delete.Connection = conn; |
168 | da.DeleteCommand = delete; | 187 | da.DeleteCommand = delete; |
169 | } | 188 | } |
170 | 189 | ||
171 | private void setupShapeCommands(SqliteDataAdapter da, SqliteConnection conn) | 190 | private void setupShapeCommands(SqliteDataAdapter da, SqliteConnection conn) |
172 | { | 191 | { |
173 | Dictionary<string, DbType> shapeDataDefs = createShapeDataDefs(); | 192 | da.InsertCommand = createInsertCommand("primshapes", ds.Tables["primshapes"]); |
174 | |||
175 | da.InsertCommand = createInsertCommand("primshapes", shapeDataDefs); | ||
176 | da.InsertCommand.Connection = conn; | 193 | da.InsertCommand.Connection = conn; |
177 | 194 | ||
178 | da.UpdateCommand = createUpdateCommand("primshapes", "UUID=:UUID", shapeDataDefs); | 195 | da.UpdateCommand = createUpdateCommand("primshapes", "UUID=:UUID", ds.Tables["primshapes"]); |
179 | da.UpdateCommand.Connection = conn; | 196 | da.UpdateCommand.Connection = conn; |
180 | 197 | ||
181 | SqliteCommand delete = new SqliteCommand("delete from primshapes where UUID = :UUID"); | 198 | SqliteCommand delete = new SqliteCommand("delete from primshapes where UUID = :UUID"); |
182 | delete.Parameters.Add(createSqliteParameter("UUID", DbType.String)); | 199 | delete.Parameters.Add(createSqliteParameter("UUID", typeof(System.String))); |
183 | delete.Connection = conn; | 200 | delete.Connection = conn; |
184 | da.DeleteCommand = delete; | 201 | da.DeleteCommand = delete; |
185 | } | 202 | } |
@@ -578,8 +595,8 @@ namespace OpenSim.DataStore.MonoSqliteStorage | |||
578 | 595 | ||
579 | private void InitDB(SqliteConnection conn) | 596 | private void InitDB(SqliteConnection conn) |
580 | { | 597 | { |
581 | string createPrims = defineTable("prims", "UUID", createPrimDataDefs()); | 598 | string createPrims = defineTable(createPrimTable()); |
582 | string createShapes = defineTable("primshapes", "UUID", createShapeDataDefs()); | 599 | string createShapes = defineTable(createShapeTable()); |
583 | 600 | ||
584 | SqliteCommand pcmd = new SqliteCommand(createPrims, conn); | 601 | SqliteCommand pcmd = new SqliteCommand(createPrims, conn); |
585 | SqliteCommand scmd = new SqliteCommand(createShapes, conn); | 602 | SqliteCommand scmd = new SqliteCommand(createShapes, conn); |
@@ -589,18 +606,18 @@ namespace OpenSim.DataStore.MonoSqliteStorage | |||
589 | conn.Close(); | 606 | conn.Close(); |
590 | } | 607 | } |
591 | 608 | ||
592 | private string defineTable(string name, string primkey, Dictionary<string, DbType> cols) | 609 | private string defineTable(DataTable dt) |
593 | { | 610 | { |
594 | string sql = "create table " + name + "("; | 611 | string sql = "create table " + dt.TableName + "("; |
595 | string subsql = ""; | 612 | string subsql = ""; |
596 | foreach (string key in cols.Keys) | 613 | foreach (DataColumn col in dt.Columns) |
597 | { | 614 | { |
598 | if (subsql.Length > 0) | 615 | if (subsql.Length > 0) |
599 | { // a map function would rock so much here | 616 | { // a map function would rock so much here |
600 | subsql += ",\n"; | 617 | subsql += ",\n"; |
601 | } | 618 | } |
602 | subsql += key + " " + sqliteType(cols[key]); | 619 | subsql += col.ColumnName + " " + sqliteType(col.DataType); |
603 | if(key == primkey) | 620 | if(col == dt.PrimaryKey[0]) |
604 | { | 621 | { |
605 | subsql += " primary key"; | 622 | subsql += " primary key"; |
606 | } | 623 | } |
@@ -610,29 +627,108 @@ namespace OpenSim.DataStore.MonoSqliteStorage | |||
610 | return sql; | 627 | return sql; |
611 | } | 628 | } |
612 | 629 | ||
613 | private string sqliteType(DbType type) | 630 | private string sqliteType(Type type) |
614 | { | 631 | { |
615 | switch(type) { | 632 | if (type == typeof(System.String)) { |
616 | case DbType.String: | ||
617 | return "varchar(255)"; | 633 | return "varchar(255)"; |
618 | 634 | } else if (type == typeof(System.Int32)) { | |
619 | case DbType.Int32: | ||
620 | return "integer"; | 635 | return "integer"; |
621 | 636 | } else if (type == typeof(System.Double)) { | |
622 | case DbType.Double: | ||
623 | return "float"; | 637 | return "float"; |
624 | 638 | } else if (type == typeof(System.Byte[])) { | |
625 | case DbType.Binary: | ||
626 | return "blob"; | 639 | return "blob"; |
627 | 640 | } else { | |
628 | default: | 641 | return "string"; |
629 | return "varchar(255)"; | ||
630 | } | 642 | } |
631 | } | 643 | } |
632 | 644 | ||
645 | private bool TestPrimsTable(SqliteConnection conn) | ||
646 | { | ||
647 | SqliteCommand primSelectCmd = new SqliteCommand(primSelect, conn); | ||
648 | SqliteDataAdapter da = new SqliteDataAdapter(primSelectCmd); | ||
649 | DataSet tmp = new DataSet(); | ||
650 | try { | ||
651 | da.Fill(tmp, "prims"); | ||
652 | } catch (Mono.Data.SqliteClient.SqliteSyntaxException) { | ||
653 | MainLog.Instance.Verbose("SQLite Database does exist... creating"); | ||
654 | InitDB(conn); | ||
655 | } | ||
656 | |||
657 | // Dictionary<string, DbType> defs = createPrimDataDefs(); | ||
658 | // // da.FillSchema(ds, SchemaType.Mapped, "prims"); | ||
659 | da.Fill(tmp, "prims"); | ||
660 | MainLog.Instance.Verbose("DATASTORE", "Filled prims..."); | ||
661 | // DataTable prims = ds.Tables["prims"]; | ||
662 | // foreach (DataColumn col in prims.Columns) | ||
663 | // { | ||
664 | // MainLog.Instance.Verbose("Found: " + col); | ||
665 | // } | ||
666 | // return true; | ||
667 | return true; | ||
668 | } | ||
669 | |||
633 | /// Methods after this point are big data definition | 670 | /// Methods after this point are big data definition |
634 | /// methods, and aren't really interesting unless you are | 671 | /// methods, and aren't really interesting unless you are |
635 | /// adjusting the schema. | 672 | /// adjusting the schema. |
673 | |||
674 | private void createCol(DataTable dt, string name, System.Type type) | ||
675 | { | ||
676 | DataColumn col = new DataColumn(name, type); | ||
677 | dt.Columns.Add(col); | ||
678 | } | ||
679 | |||
680 | private DataTable createPrimTable() | ||
681 | { | ||
682 | DataTable prims = new DataTable("prims"); | ||
683 | |||
684 | createCol(prims, "UUID", typeof(System.String)); | ||
685 | createCol(prims, "ParentID", typeof(System.Int32)); | ||
686 | createCol(prims, "CreationDate", typeof(System.Int32)); | ||
687 | createCol(prims, "Name", typeof(System.String)); | ||
688 | createCol(prims, "SceneGroupID", typeof(System.String)); | ||
689 | // various text fields | ||
690 | createCol(prims, "Text", typeof(System.String)); | ||
691 | createCol(prims, "Description", typeof(System.String)); | ||
692 | createCol(prims, "SitName", typeof(System.String)); | ||
693 | createCol(prims, "TouchName", typeof(System.String)); | ||
694 | // permissions | ||
695 | createCol(prims, "CreatorID", typeof(System.String)); | ||
696 | createCol(prims, "OwnerID", typeof(System.String)); | ||
697 | createCol(prims, "GroupID", typeof(System.String)); | ||
698 | createCol(prims, "LastOwnerID", typeof(System.String)); | ||
699 | createCol(prims, "OwnerMask", typeof(System.Int32)); | ||
700 | createCol(prims, "NextOwnerMask", typeof(System.Int32)); | ||
701 | createCol(prims, "GroupMask", typeof(System.Int32)); | ||
702 | createCol(prims, "EveryoneMask", typeof(System.Int32)); | ||
703 | createCol(prims, "BaseMask", typeof(System.Int32)); | ||
704 | // vectors | ||
705 | createCol(prims, "PositionX", typeof(System.Double)); | ||
706 | createCol(prims, "PositionY", typeof(System.Double)); | ||
707 | createCol(prims, "PositionZ", typeof(System.Double)); | ||
708 | createCol(prims, "GroupPositionX", typeof(System.Double)); | ||
709 | createCol(prims, "GroupPositionY", typeof(System.Double)); | ||
710 | createCol(prims, "GroupPositionZ", typeof(System.Double)); | ||
711 | createCol(prims, "VelocityX", typeof(System.Double)); | ||
712 | createCol(prims, "VelocityY", typeof(System.Double)); | ||
713 | createCol(prims, "VelocityZ", typeof(System.Double)); | ||
714 | createCol(prims, "AngularVelocityX", typeof(System.Double)); | ||
715 | createCol(prims, "AngularVelocityY", typeof(System.Double)); | ||
716 | createCol(prims, "AngularVelocityZ", typeof(System.Double)); | ||
717 | createCol(prims, "AccelerationX", typeof(System.Double)); | ||
718 | createCol(prims, "AccelerationY", typeof(System.Double)); | ||
719 | createCol(prims, "AccelerationZ", typeof(System.Double)); | ||
720 | // quaternions | ||
721 | createCol(prims, "RotationX", typeof(System.Double)); | ||
722 | createCol(prims, "RotationY", typeof(System.Double)); | ||
723 | createCol(prims, "RotationZ", typeof(System.Double)); | ||
724 | createCol(prims, "RotationW", typeof(System.Double)); | ||
725 | |||
726 | // Add in contraints | ||
727 | prims.PrimaryKey = new DataColumn[] { prims.Columns["UUID"] }; | ||
728 | |||
729 | return prims; | ||
730 | } | ||
731 | |||
636 | private Dictionary<string, DbType> createPrimDataDefs() | 732 | private Dictionary<string, DbType> createPrimDataDefs() |
637 | { | 733 | { |
638 | Dictionary<string, DbType> data = new Dictionary<string, DbType>(); | 734 | Dictionary<string, DbType> data = new Dictionary<string, DbType>(); |
@@ -680,6 +776,47 @@ namespace OpenSim.DataStore.MonoSqliteStorage | |||
680 | return data; | 776 | return data; |
681 | } | 777 | } |
682 | 778 | ||
779 | |||
780 | private DataTable createShapeTable() | ||
781 | { | ||
782 | DataTable shapes = new DataTable("primshapes"); | ||
783 | createCol(shapes, "UUID", typeof(System.String)); | ||
784 | // shape is an enum | ||
785 | createCol(shapes, "Shape", typeof(System.Int32)); | ||
786 | // vectors | ||
787 | createCol(shapes, "ScaleX", typeof(System.Double)); | ||
788 | createCol(shapes, "ScaleY", typeof(System.Double)); | ||
789 | createCol(shapes, "ScaleZ", typeof(System.Double)); | ||
790 | // paths | ||
791 | createCol(shapes, "PCode", typeof(System.Int32)); | ||
792 | createCol(shapes, "PathBegin", typeof(System.Int32)); | ||
793 | createCol(shapes, "PathEnd", typeof(System.Int32)); | ||
794 | createCol(shapes, "PathScaleX", typeof(System.Int32)); | ||
795 | createCol(shapes, "PathScaleY", typeof(System.Int32)); | ||
796 | createCol(shapes, "PathShearX", typeof(System.Int32)); | ||
797 | createCol(shapes, "PathShearY", typeof(System.Int32)); | ||
798 | createCol(shapes, "PathSkew", typeof(System.Int32)); | ||
799 | createCol(shapes, "PathCurve", typeof(System.Int32)); | ||
800 | createCol(shapes, "PathRadiusOffset", typeof(System.Int32)); | ||
801 | createCol(shapes, "PathRevolutions", typeof(System.Int32)); | ||
802 | createCol(shapes, "PathTaperX", typeof(System.Int32)); | ||
803 | createCol(shapes, "PathTaperY", typeof(System.Int32)); | ||
804 | createCol(shapes, "PathTwist", typeof(System.Int32)); | ||
805 | createCol(shapes, "PathTwistBegin", typeof(System.Int32)); | ||
806 | // profile | ||
807 | createCol(shapes, "ProfileBegin", typeof(System.Int32)); | ||
808 | createCol(shapes, "ProfileEnd", typeof(System.Int32)); | ||
809 | createCol(shapes, "ProfileCurve", typeof(System.Int32)); | ||
810 | createCol(shapes, "ProfileHollow", typeof(System.Int32)); | ||
811 | // text TODO: this isn't right, but I'm not sure the right | ||
812 | // way to specify this as a blob atm | ||
813 | createCol(shapes, "Texture", typeof(System.Byte[])); | ||
814 | |||
815 | shapes.PrimaryKey = new DataColumn[] { shapes.Columns["UUID"] }; | ||
816 | |||
817 | return shapes; | ||
818 | } | ||
819 | |||
683 | private Dictionary<string, DbType> createShapeDataDefs() | 820 | private Dictionary<string, DbType> createShapeDataDefs() |
684 | { | 821 | { |
685 | Dictionary<string, DbType> data = new Dictionary<string, DbType>(); | 822 | Dictionary<string, DbType> data = new Dictionary<string, DbType>(); |