3 // Christian Hergert <chris@mosaix.net>
4 // Daniel Morgan <danielmorgan@verizon.net>
5 // Ben Motmans <ben.motmans@gmail.com>
7 // Copyright (C) 2005 Mosaix Communications, Inc.
8 // Copyright (C) 2005 Daniel Morgan
9 // Copyright (c) 2007 Ben Motmans
11 // Permission is hereby granted, free of charge, to any person obtaining a copy
12 // of this software and associated documentation files (the "Software"), to deal
13 // in the Software without restriction, including without limitation the rights
14 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 // copies of the Software, and to permit persons to whom the Software is
16 // furnished to do so, subject to the following conditions:
18 // The above copyright notice and this permission notice shall be included in
19 // all copies or substantial portions of the Software.
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
32 using FirebirdSql
.Data
.Firebird
;
33 using System
.Collections
.Generic
;
34
namespace MonoDevelop
.Database
.Sql
37 // http://firebird.sourceforge.net/index.php?op=devel&sub=netprovider&id=examples
38 // http://www.alberton.info/firebird_sql_meta_info.html
39 public class FirebirdSchemaProvider
: AbstractSchemaProvider
41 public FirebirdSchemaProvider (IConnectionProvider connectionProvider
)
42 : base (connectionProvider
)
46 public override bool SupportsSchemaType (Type type
)
48 if (type
== typeof(TableSchema
))
50 else if (type
== typeof(ViewSchema
))
52 else if (type
== typeof(ProcedureSchema
))
54 else if (type
== typeof(AggregateSchema
))
56 else if (type
== typeof(GroupSchema
))
58 else if (type
== typeof(UserSchema
))
60 else if (type
== typeof(LanguageSchema
))
62 else if (type
== typeof(OperatorSchema
))
64 else if (type
== typeof(RoleSchema
))
66 else if (type
== typeof(SequenceSchema
))
68 else if (type
== typeof(DataTypeSchema
))
70 else if (type
== typeof(TriggerSchema
))
72 else if (type
== typeof(ColumnSchema
))
74 else if (type
== typeof(ConstraintSchema
))
76 else if (type
== typeof(RuleSchema
))
82 public override ICollection
<TableSchema
> GetTables ()
84 CheckConnectionState ();
85 List
<TableSchema
> tables
= new List
<TableSchema
> ();
87 IDbCommand command
= connectionProvider
.CreateCommand (
88 "SELECT RDB$RELATION_NAME, RDB$SYSTEM_FLAG, RDB$OWNER_NAME, RDB$DESCRIPTION FROM RDB$RELATIONS "+
89 "WHERE RDB$VIEW_BLR IS NULL;"
93 using (IDataReader r
= command
.ExecuteReader()) {
95 TableSchema table
= new TableSchema (this);
97 table
.Name
= r
.GetString (0);
98 table
.IsSystemTable
= (!r
.IsDBNull (1) && r
.GetInt32 (1) != 0);
99 table
.OwnerName
= r
.GetString (2);
100 table
.Comment
= r
.GetString (3);
106 connectionProvider
.Close (command
.Connection
);
112 public override ICollection
<ColumnSchema
> GetTableColumns (TableSchema table
)
114 return GetTableOrViewColumns (table
.Name
);
117 public override ICollection
<ViewSchema
> GetViews ()
119 CheckConnectionState ();
120 List
<ViewSchema
> views
= new List
<ViewSchema
> ();
122 IDbCommand command
= connectionProvider
.CreateCommand (
123 "SELECT RDB$RELATION_NAME, RDB$SYSTEM_FLAG, RDB$OWNER_NAME, RDB$DESCRIPTION, RDB$VIEW_SOURCE FROM RDB$RELATIONS "+
124 "WHERE RDB$VIEW_SOURCE IS NOT NULL;"
127 using (IDataReader r
= command
.ExecuteReader()) {
129 ViewSchema view
= new ViewSchema (this);
131 view
.Name
= r
.GetString (0);
132 view
.IsSystemView
= (!r
.IsDBNull (1) && r
.GetInt32 (1) != 0);
133 view
.OwnerName
= r
.GetString (2);
134 view
.Comment
= r
.GetString (3);
135 //TODO: view.Definition = 4 (ascii blob)
141 connectionProvider
.Close (command
.Connection
);
146 public override ICollection
<ColumnSchema
> GetViewColumns (ViewSchema view
)
148 return GetTableOrViewColumns (view
.Name
);
151 public override ICollection
<ProcedureSchema
> GetProcedures ()
153 CheckConnectionState ();
154 List
<ProcedureSchema
> procedures
= new List
<ProcedureSchema
> ();
156 IDbCommand command
= connectionProvider
.CreateCommand (
157 "SELECT RDB$PROCEDURE_NAME, RDB$SYSTEM_FLAG, RDB$OWNER_NAME, RDB$DESCRIPTION, RDB$PROCEDURE_SOURCE FROM RDB$PROCEDURES;"
161 using (IDataReader r
= command
.ExecuteReader()) {
163 ProcedureSchema procedure
= new ProcedureSchema (this);
165 procedure
.Name
= r
.GetString (0);
166 procedure
.IsSystemProcedure
= (!r
.IsDBNull (1) && r
.GetInt32 (1) != 0);
167 procedure
.OwnerName
= r
.GetString (2);
168 procedure
.Comment
= r
.GetString (3);
169 //TODO: procedure.Definition = 4 (ascii blob)
171 procedures
.Add (procedure
);
175 connectionProvider
.Close (command
.Connection
);
181 public override ICollection
<ColumnSchema
> GetProcedureColumns (ProcedureSchema procedure
)
183 CheckConnectionState ();
184 List
<ColumnSchema
> columns
= new List
<ColumnSchema
> ();
186 IDbCommand command
= connectionProvider
.CreateCommand (
187 "SELECT RDB$PARAMETER_NAME, RDB$PARAMETER_NUMBER, RDB$DESCRIPTION, RDB$SYSTEM_FLAG "
188 + "FROM RDB$PROCEDURE_PARAMETERS "
189 + "WHERE RDB$PROCEDURE_NAME = '" + procedure
.Name
+ "' "
190 + "AND RDB$PARAMETER_TYPE = 1 "
195 using (IDataReader r
= command
.ExecuteReader()) {
197 ColumnSchema column
= new ColumnSchema (this);
199 column
.Name
= r
.GetString (0);
200 column
.OwnerName
= procedure
.Name
;
201 column
.Comment
= r
.GetString (2);
204 columns
.Add (column
);
208 connectionProvider
.Close (command
.Connection
);
214 public override ICollection
<ParameterSchema
> GetProcedureParameters (ProcedureSchema procedure
)
216 CheckConnectionState ();
217 List
<ParameterSchema
> parameters
= new List
<ParameterSchema
> ();
219 IDbCommand command
= connectionProvider
.CreateCommand (
220 "SELECT RDB$PARAMETER_NAME, RDB$PARAMETER_NUMBER, RDB$DESCRIPTION, RDB$SYSTEM_FLAG "
221 + "FROM RDB$PROCEDURE_PARAMETERS "
222 + "WHERE RDB$PROCEDURE_NAME = '" + procedure
.Name
+ "' "
223 + "AND RDB$PARAMETER_TYPE = 0 "
228 using (IDataReader r
= command
.ExecuteReader()) {
230 ParameterSchema parameter
= new ParameterSchema (this);
232 parameter
.Name
= r
.GetString (0);
233 parameter
.OwnerName
= procedure
.Name
;
234 parameter
.Comment
= r
.GetString (2);
237 parameters
.Add (parameter
);
241 connectionProvider
.Close (command
.Connection
);
248 public override ICollection
<ConstraintSchema
> GetTableConstraints (TableSchema table
)
250 CheckConnectionState ();
251 List
<ConstraintSchema
> constraints
= new List
<ConstraintSchema
> ();
253 IDbCommand command
= connectionProvider
.CreateCommand ("SHOW TABLE STATUS FROM `" + table
.OwnerName
+ "`;");
255 using (IDataReader r
= command
.ExecuteReader()) {
256 // ConstraintSchema constraint = new ConstraintSchema (this);
257 // constraint.PrimaryKey = pkColumn;
258 // constraint.ForeignKey = fkColumn;
260 // constraints.Add (constraint);
263 connectionProvider
.Close (command
.Connection
);
269 public override ICollection
<UserSchema
> GetUsers ()
271 CheckConnectionState ();
272 List
<UserSchema
> users
= new List
<UserSchema
> ();
274 IDbCommand command
= connectionProvider
.CreateCommand ("SELECT DISTINCT RDB$USER FROM RDB$USER_PRIVILEGES;");
276 using (IDataReader r
= command
.ExecuteReader ()) {
278 UserSchema user
= new UserSchema (this);
279 user
.Name
= r
.GetString (0);
284 connectionProvider
.Close (command
.Connection
);
290 public override ICollection
<TriggerSchema
> GetTriggers ()
292 CheckConnectionState ();
293 List
<TriggerSchema
> triggers
= new List
<TriggerSchema
> ();
295 IDbCommand command
= connectionProvider
.CreateCommand ("SELECT RDB$TRIGGER_NAME, RDB$RELATION_NAME, RDB$TRIGGER_TYPE FROM RDB$TRIGGERS;");
297 using (IDataReader r
= command
.ExecuteReader ()) {
299 TriggerSchema trigger
= new TriggerSchema (this);
300 trigger
.Name
= r
.GetString (0);
301 //TODO: table and type
302 triggers
.Add (trigger
);
306 connectionProvider
.Close (command
.Connection
);
313 public override DataTypeSchema
GetDataType (string name
)
316 throw new ArgumentNullException ("name");
317 name
= name
.ToUpper ();
319 DataTypeSchema dts
= new DataTypeSchema (this);
333 private ICollection
<ColumnSchema
> GetTableOrViewColumns (string name
)
335 CheckConnectionState ();
336 List
<ColumnSchema
> columns
= new List
<ColumnSchema
> ();
338 IDbCommand command
= connectionProvider
.CreateCommand (
339 "SELECT r.RDB$FIELD_NAME AS field_name, r.RDB$DESCRIPTION AS field_description, "
340 + "r.RDB$DEFAULT_VALUE AS field_default_value, r.RDB$NULL_FLAG AS field_not_null_constraint, "
341 + "f.RDB$FIELD_LENGTH AS field_length, f.RDB$FIELD_PRECISION AS field_precision, "
342 + "f.RDB$FIELD_SCALE AS field_scale, "
343 + "CASE f.RDB$FIELD_TYPE WHEN 261 THEN 'BLOB' WHEN 14 THEN 'CHAR' WHEN 40 THEN 'CSTRING' "
344 + "WHEN 11 THEN 'D_FLOAT' WHEN 27 THEN 'DOUBLE' WHEN 10 THEN 'FLOAT' WHEN 16 THEN 'INT64' "
345 + "WHEN 8 THEN 'INTEGER' WHEN 9 THEN 'QUAD' WHEN 7 THEN 'SMALLINT' WHEN 12 THEN 'DATE' "
346 + "WHEN 13 THEN 'TIME' WHEN 35 THEN 'TIMESTAMP' WHEN 37 THEN 'VARCHAR' ELSE 'UNKNOWN' "
347 + "END AS field_type, f.RDB$FIELD_SUB_TYPE AS field_subtype, "
348 + "coll.RDB$COLLATION_NAME AS field_collation, cset.RDB$CHARACTER_SET_NAME AS field_charset "
349 + "FROM RDB$RELATION_FIELDS r LEFT JOIN RDB$FIELDS f ON r.RDB$FIELD_SOURCE = f.RDB$FIELD_NAME "
350 + "LEFT JOIN RDB$COLLATIONS coll ON f.RDB$COLLATION_ID = coll.RDB$COLLATION_ID "
351 + "LEFT JOIN RDB$CHARACTER_SETS cset ON f.RDB$CHARACTER_SET_ID = cset.RDB$CHARACTER_SET_ID "
352 + "WHERE r.RDB$RELATION_NAME='" + name
+ "' ORDER BY r.RDB$FIELD_POSITION;"
355 using (IDataReader r
= command
.ExecuteReader()) {
357 ColumnSchema column
= new ColumnSchema (this);
359 column
.Name
= r
.GetString (0);
360 column
.DataTypeName
= r
.GetString (8);
361 column
.NotNull
= (!r
.IsDBNull (3) && r
.GetInt32 (3) == 1);
362 column
.Default
= r
.GetString (2);
363 column
.Comment
= r
.GetString (1);
364 column
.OwnerName
= name
;
365 column
.Length
= r
.GetInt32 (4);
366 column
.Precision
= r
.GetInt32 (5);
367 column
.Scale
= r
.GetInt32 (6);
369 columns
.Add (column
);
373 connectionProvider
.Close (command
.Connection
);