48bd7d059fbe3d5b349bd850050d0c60d189da18
[mono.git] / mcs / class / FirebirdSql.Data.Firebird / FirebirdSql.Data.Firebird / DbSchema / FbDbSchema.cs
1 /*
2  *      Firebird ADO.NET Data provider for .NET and Mono 
3  * 
4  *         The contents of this file are subject to the Initial 
5  *         Developer's Public License Version 1.0 (the "License"); 
6  *         you may not use this file except in compliance with the 
7  *         License. You may obtain a copy of the License at 
8  *         http://www.firebirdsql.org/index.php?op=doc&id=idpl
9  *
10  *         Software distributed under the License is distributed on 
11  *         an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either 
12  *         express or implied. See the License for the specific 
13  *         language governing rights and limitations under the License.
14  * 
15  *      Copyright (c) 2002, 2005 Carlos Guzman Alvarez
16  *      All Rights Reserved.
17  */
18
19 using System;
20 using System.Data;
21 using System.Globalization;
22 using System.Text;
23 using System.Text.RegularExpressions;
24 using System.Collections;
25
26 namespace FirebirdSql.Data.Firebird.DbSchema
27 {
28         internal abstract class FbDbSchema
29         {
30                 #region Fields
31
32                 private string schemaName;
33
34                 #endregion
35
36                 #region Constructors
37
38                 public FbDbSchema(string schemaName)
39                 {
40                         this.schemaName = schemaName;
41                 }
42
43                 #endregion
44
45                 #region Abstract Methods
46
47                 protected abstract StringBuilder GetCommandText(object[] restrictions);
48
49                 #endregion
50
51                 #region Methods
52
53                 public virtual DataTable GetSchema(FbConnection connection, object[] restrictions)
54                 {
55                         restrictions = this.ParseRestrictions(restrictions);
56
57                         FbCommand               command = this.BuildCommand(connection, restrictions);
58                         FbDataAdapter   adapter = new FbDataAdapter(command);
59                         DataSet                 dataSet = new DataSet(this.schemaName);
60
61                         try
62                         {
63                                 adapter.Fill(dataSet, this.schemaName);
64                         }
65                         catch (Exception ex)
66                         {
67                                 throw new FbException(ex.Message);
68                         }
69                         finally
70                         {
71                                 adapter.Dispose();
72                                 command.Dispose();
73                         }
74
75                         TrimStringFields(dataSet.Tables[this.schemaName]);
76
77                         return this.ProcessResult(dataSet.Tables[this.schemaName]);
78                 }
79
80                 #endregion
81
82                 #region Protected Methods
83
84                 protected FbCommand BuildCommand(FbConnection connection, object[] restrictions)
85                 {
86                         DataView collections = FbMetaDataCollections.GetSchema().DefaultView;
87                         collections.RowFilter = "CollectionName = '" + this.schemaName + "'";
88
89                         if (collections.Count == 0)
90                         {
91                                 throw new NotSupportedException("Unsupported collection name.");
92                         }
93
94                         if (restrictions != null &&
95                                 restrictions.Length > (int)collections[0]["NumberOfRestrictions"])
96                         {
97                                 throw new InvalidOperationException("The number of specified restrictions is not valid.");
98                         }
99
100                         DataView restriction = FbRestrictions.GetSchema().DefaultView;
101                         restriction.RowFilter = "CollectionName = '" + this.schemaName + "'";
102
103                         if (restriction.Count != (int)collections[0]["NumberOfRestrictions"])
104                         {
105                                 throw new InvalidOperationException("Incorrect restriction definitions.");
106                         }
107
108                         StringBuilder builder = this.GetCommandText(restrictions);
109                         FbCommand schema = connection.CreateCommand();
110
111                         schema.CommandText = builder.ToString();
112
113                         if (connection.InnerConnection.HasActiveTransaction)
114                         {
115                                 schema.Transaction = connection.InnerConnection.ActiveTransaction;
116                         }
117
118                         if (restrictions != null && restrictions.Length > 0)
119                         {
120                                 // Add parameters
121                                 int index = 0;
122
123                                 for (int i = 0; i < restrictions.Length; i++)
124                                 {
125                                         string rname = restriction[i]["RestrictionDefault"].ToString().ToLower(CultureInfo.CurrentCulture);
126                                         if (restrictions[i] != null &&
127                                                 !rname.EndsWith("_catalog") &&
128                                                 !rname.EndsWith("_schema") &&
129                                                 rname != "table_type")
130                                         {
131                                                 string pname = String.Format(CultureInfo.CurrentCulture, "@p{0}", index++);
132
133                                                 FbParameter p = schema.Parameters.Add(pname, restrictions[i].ToString());
134                                                 p.FbDbType = FbDbType.VarChar;
135                                                 p.Size = 255;
136                                         }
137                                 }
138                         }
139
140                         return schema;
141                 }
142
143                 protected virtual DataTable ProcessResult(DataTable schema)
144                 {
145                         return schema;
146                 }
147
148                 protected virtual object[] ParseRestrictions(object[] restrictions)
149                 {
150                         return restrictions;
151                 }
152
153                 #endregion
154
155                 #region Private Static Methods
156
157                 private static void TrimStringFields(DataTable schema)
158                 {
159                         schema.BeginLoadData();
160
161                         foreach (DataRow row in schema.Rows)
162                         {
163                                 for (int i = 0; i < schema.Columns.Count; i++)
164                                 {
165                                         if (schema.Columns[i].DataType == typeof(System.String))
166                                         {
167                                                 row[schema.Columns[i]] = row[schema.Columns[i]].ToString().Trim();
168                                         }
169                                 }
170                         }
171
172                         schema.EndLoadData();
173                         schema.AcceptChanges();
174                 }
175
176                 #endregion
177         }
178 }