1 package com.quantum.model;
3 import java.sql.Connection;
4 import java.sql.DatabaseMetaData;
5 import java.sql.ResultSet;
6 import java.sql.SQLException;
7 import java.util.ArrayList;
8 import java.util.Collections;
9 import java.util.HashSet;
10 import java.util.List;
13 import com.quantum.adapters.DatabaseAdapter;
14 import com.quantum.sql.MultiSQLServer;
15 import com.quantum.sql.SQLResults;
20 public class Database {
22 private DatabaseAdapter databaseAdapter;
23 private Bookmark bookmark;
25 public Database(Bookmark bookmark) {
26 this.bookmark = bookmark;
27 this.databaseAdapter = bookmark.getAdapter();
30 private static final String[] ALL_TABLE_TYPES = {
33 Entity.SEQUENCE_TYPE };
35 private static final List STANDARD_TABLE_TYPES =
36 Collections.synchronizedList(new ArrayList());
39 for (int i = 0, length = (ALL_TABLE_TYPES == null) ? 0 : ALL_TABLE_TYPES.length;
42 STANDARD_TABLE_TYPES.add(ALL_TABLE_TYPES[i]);
46 public String[] getEntityTypes()
47 throws NotConnectedException, SQLException {
48 return getEntityTypes(this.bookmark.getConnection());
51 public String getUsername() throws NotConnectedException, SQLException {
52 return getMetaData().getUserName();
57 * <p>This method returns a list of entity types supported by the database
58 * adapter. This list will always be limited to Tables, Views and
61 * <p>Not all databases support all types. MySQL only supports
62 * Tables. Informix supports Tables and Views. Oracle and DB2 support
63 * Tables, Views and Sequences.</p>
67 * @throws SQLException
69 public String[] getEntityTypes(Connection connection) throws SQLException {
71 Set set = new HashSet();
72 if (this.databaseAdapter.getShowTableQuery(this.bookmark.getUsername()) != null) {
73 set.add(Entity.TABLE_TYPE);
74 } else if (this.databaseAdapter.getShowViewQuery(this.bookmark.getUsername()) != null) {
75 set.add(Entity.VIEW_TYPE);
76 } else if (this.databaseAdapter.getShowSequenceQuery(this.bookmark.getUsername()) != null) {
77 set.add(Entity.SEQUENCE_TYPE);
80 DatabaseMetaData metaData = connection.getMetaData();
81 ResultSet resultSet = metaData.getTableTypes();
82 while (resultSet.next()) {
83 String type = resultSet.getString("TABLE_TYPE");
85 // Informix, in particular, pads this with extra spaces
88 if (STANDARD_TABLE_TYPES.contains(type)) {
93 return (String[]) set.toArray(new String[set.size()]);
96 public String getInformation() throws SQLException {
98 DatabaseMetaData metaData = getMetaData();
100 return metaData == null ? null : metaData.getDatabaseProductName() + " "
101 + metaData.getDatabaseProductVersion();
102 } catch (NotConnectedException e) {
103 // TODO: think about this...
109 * Get a list of entities (tables, views, sequences) for a particular
110 * bookmark. This function is usually not redefined because it gives
111 * an external interface. You will usually redefine the getShowTableQuery(),
112 * getShowViewQuery(), etc.
115 * the bookmark that describes the database that is being accessed.
116 * @param passwordFinder -
117 * a utility class that knows how to obtain a password, if required
119 * the schema from which to extract
121 * the type ("VIEW", "TABLE", etc.) of entities to extract or null
122 * if all entity types should be extracted
124 * an array of entity objects representing the tables, views and sequences.
125 * @throws SQLException
127 public Entity[] getEntities(Bookmark bookmark, Schema schema, String type)
128 throws SQLException, NotConnectedException {
129 Connection connection = bookmark.getConnection();
130 Entity[] result = getEntities(bookmark, connection, schema, type);
131 return (result == null) ? new Entity[0] : result;
134 protected Entity[] getEntities(Bookmark bookmark, Connection connection, Schema schema, String type)
135 throws SQLException {
137 List list = new ArrayList();
138 String[] types = (type == null) ? ALL_TABLE_TYPES : new String[] { type };
140 for (int i = 0; i < types.length; i++) {
141 list.addAll(getEntitiesList(bookmark, connection, types[i], schema));
144 return (Entity[]) list.toArray(new Entity[list.size()]);
147 protected List getEntitiesList(Bookmark bookmark, Connection connection, String type, Schema schema)
148 throws SQLException {
150 String sql = getSQL(bookmark, type, schema);
151 List list = new ArrayList();
152 SQLResults results = null;
154 results = MultiSQLServer.getInstance().execute(connection, sql);
155 for (int i = 1, size = (results == null) ? 0 : results.getRowCount(); i <= size; i++) {
156 String schemaName = results.getColumnCount() == 1
157 ? schema.getName() : results.getElement(1, i).toString();
158 String tableName = results.getColumnCount() == 1
159 ? results.getElement(1, i).toString()
160 : results.getElement(2, i).toString();
161 if (tableName != null && tableName.length() > 0) {
162 Entity entity = EntityFactory.getInstance().create(
163 bookmark, schemaName, tableName, type);
164 if (entity != null) {
170 // If we have some results, we go back
171 if (results != null) return list;
172 // Else, we try the JDBC driver
173 DatabaseMetaData metaData = connection.getMetaData();
174 // getTables needs a null schema to get all the schemas. So we don't pass a "" schema, but a null one
175 ResultSet set = null;
176 if (metaData.supportsSchemasInTableDefinitions())
177 set = metaData.getTables(null, (schema != null) ? schema.getName() : null, "%", new String[] { type });
179 set = metaData.getTables(null, null, "%", new String[] { type });
182 String tempSchema = set.getString("TABLE_SCHEM");
183 tempSchema = (tempSchema == null) ? "" : tempSchema.trim();
184 String tableName = set.getString("TABLE_NAME");
185 tableName = (tableName == null) ? "" : tableName.trim();
187 if (tableName != null && tableName.length() > 0) {
188 Entity entity = EntityFactory.getInstance().create(bookmark, tempSchema, tableName, type);
189 if (entity != null) {
198 public DataType[] getTypes() throws NotConnectedException, SQLException {
199 DatabaseMetaData metaData = getMetaData();
200 List list = new ArrayList();
201 ResultSet results = metaData.getTypeInfo();
203 while (results.next()) {
204 String name = results.getString("TYPE_NAME");
205 int type = results.getInt("DATA_TYPE");
206 list.add(new DataType(type, name));
211 return (DataType[]) list.toArray(new DataType[list.size()]);
217 * @throws NotConnectedException
218 * @throws SQLException
220 private DatabaseMetaData getMetaData() throws NotConnectedException, SQLException {
221 Connection connection = this.bookmark.getConnection();
222 DatabaseMetaData metaData = connection.getMetaData();
226 private String getSQL(Bookmark bookmark, String type, Schema schema) {
227 if (Entity.TABLE_TYPE.equals(type)) {
228 return this.databaseAdapter.getShowTableQuery(schema.getName());
229 } else if (Entity.VIEW_TYPE.equals(type)) {
230 return this.databaseAdapter.getShowViewQuery(schema.getName());
231 } else if (Entity.SEQUENCE_TYPE.equals(type)) {
232 return this.databaseAdapter.getShowSequenceQuery(schema.getName());
238 public ForeignKey[] getExportedKeys(String schema, String entityName)
239 throws NotConnectedException, SQLException {
240 DatabaseMetaData metaData = getMetaData();
241 List list = new ArrayList();
242 return getForeignKeys(list, metaData.getExportedKeys(null, schema, entityName));
245 public ForeignKey[] getImportedKeys(String schema, String entityName)
246 throws NotConnectedException, SQLException {
247 DatabaseMetaData metaData = getMetaData();
248 List list = new ArrayList();
249 return getForeignKeys(list, metaData.getImportedKeys(null, schema, entityName));
256 * @throws SQLException
258 private ForeignKey[] getForeignKeys(List list, ResultSet resultSet) throws SQLException {
259 ForeignKeyImpl foreignKey = null;
261 int lowestKeySequence = Integer.MAX_VALUE;
263 while (resultSet.next()) {
264 int keySequence = resultSet.getInt("KEY_SEQ");
265 lowestKeySequence = Math.min(lowestKeySequence, keySequence);
267 if (keySequence == lowestKeySequence || foreignKey == null) {
268 foreignKey = new ForeignKeyImpl();
269 list.add(foreignKey);
270 foreignKey.setName(resultSet.getString("FK_NAME"));
271 foreignKey.setDeleteRule(resultSet.getShort("DELETE_RULE"));
272 foreignKey.setForeignEntitySchema(resultSet.getString("FKTABLE_SCHEM"));
273 foreignKey.setForeignEntityName(resultSet.getString("FKTABLE_NAME"));
274 foreignKey.setLocalEntitySchema(resultSet.getString("PKTABLE_SCHEM"));
275 foreignKey.setLocalEntityName(resultSet.getString("PKTABLE_NAME"));
278 foreignKey.addColumns(
279 resultSet.getString("PKCOLUMN_NAME"),
280 resultSet.getString("FKCOLUMN_NAME"));
282 return (ForeignKey[]) list.toArray(new ForeignKey[list.size()]);
290 * @throws SQLException
291 * @throws NotConnectedException
293 public Schema[] getSchemas() throws NotConnectedException, SQLException {
294 DatabaseMetaData metaData = getMetaData();
295 List list = new ArrayList();
296 ResultSet resultSet = metaData.getSchemas();
298 while (resultSet.next()) {
299 String schemaName = resultSet.getString("TABLE_SCHEM");
300 list.add(new Schema(schemaName));
302 return (Schema[]) list.toArray(new Schema[list.size()]);