1 /***
2 * Redistribution and use of this software and associated documentation
3 * ("Software"), with or without modification, are permitted provided
4 * that the following conditions are met:
5 *
6 * 1. Redistributions of source code must retain copyright
7 * statements and notices. Redistributions must also contain a
8 * copy of this document.
9 *
10 * 2. Redistributions in binary form must reproduce the
11 * above copyright notice, this list of conditions and the
12 * following disclaimer in the documentation and/or other
13 * materials provided with the distribution.
14 *
15 * 3. The name "Exolab" must not be used to endorse or promote
16 * products derived from this Software without prior written
17 * permission of Exoffice Technologies. For written permission,
18 * please contact info@exolab.org.
19 *
20 * 4. Products derived from this Software may not be called "Exolab"
21 * nor may "Exolab" appear in their names without prior written
22 * permission of Exoffice Technologies. Exolab is a registered
23 * trademark of Exoffice Technologies.
24 *
25 * 5. Due credit should be given to the Exolab Project
26 * (http://www.exolab.org/).
27 *
28 * THIS SOFTWARE IS PROVIDED BY EXOFFICE TECHNOLOGIES AND CONTRIBUTORS
29 * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
30 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
31 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
32 * EXOFFICE TECHNOLOGIES OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
33 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
35 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
37 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
39 * OF THE POSSIBILITY OF SUCH DAMAGE.
40 *
41 * Copyright 2002-2003 (C) Exoffice Technologies Inc. All Rights Reserved.
42 *
43 * $Id: SchemaBrowser.java,v 1.5 2003/08/07 13:33:11 tanderson Exp $
44 */
45
46 package org.exolab.jms.tools.db;
47
48 import java.sql.Connection;
49 import java.sql.DatabaseMetaData;
50 import java.sql.PreparedStatement;
51 import java.sql.ResultSet;
52 import java.sql.ResultSetMetaData;
53 import java.sql.SQLException;
54
55 import org.apache.commons.logging.Log;
56 import org.apache.commons.logging.LogFactory;
57
58 import org.exolab.jms.persistence.PersistenceException;
59 import org.exolab.jms.persistence.SQLHelper;
60
61
62 /***
63 * This class provides methods for examining a database schema
64 *
65 * @version $Revision: 1.5 $ $Date: 2003/08/07 13:33:11 $
66 * @author <a href="mailto:tima@intalio.com">Tim Anderson</a>
67 */
68 public class SchemaBrowser {
69
70 /***
71 * The connection to the database
72 */
73 private Connection _connection = null;
74
75 /***
76 * The set of data types supported by the RDBMS
77 */
78 private TypeSet _types = null;
79
80 /***
81 * The type mapper, used to convert between the type requested by
82 * the schema, and those supported by the RDBMS
83 */
84 private TypeMapper _mapper = null;
85
86 /***
87 * The logger
88 */
89 private static final Log _log = LogFactory.getLog(SchemaBrowser.class);
90
91
92 /***
93 * Construct a new <code>SchemaBrowser</code>
94 *
95 * @param connection the JDBC connection
96 * @throws PersistenceException if database meta-data can't be obtained
97 */
98 public SchemaBrowser(Connection connection) throws PersistenceException {
99 _connection = connection;
100
101 // get the types supported by the database
102 _types = new TypeSet(_connection);
103 _mapper = new TypeMapper(_types);
104 }
105
106 /***
107 * Returns the schema for the specified table
108 *
109 * @param name the table name
110 * @return the schema for the table identified by <code>name</code>
111 * @throws PersistenceException if the named table doesn't exist, or the
112 * schema cannot be obtained
113 */
114 public Table getTable(String name) throws PersistenceException {
115 Table result = new Table();
116
117 result.setName(name);
118
119 // determine the column types. Another approach would be to use
120 // DatabaseMetaData.getColumns() - except that not all JDBC drivers
121 // seem to support this (e.g, Sybase)
122 PreparedStatement select = null;
123 try {
124 select = _connection.prepareStatement(
125 "select * from " + name + " where 1 = 0");
126 ResultSet set = select.executeQuery();
127 ResultSetMetaData metaData = set.getMetaData();
128
129 for (int i = 1; i <= metaData.getColumnCount(); ++i) {
130 String columnName = metaData.getColumnName(i);
131 int dataType = metaData.getColumnType(i);
132 long precision = metaData.getPrecision(i);
133 int nullable = metaData.isNullable(i);
134 String typeName = metaData.getColumnTypeName(i);
135 Type type = _mapper.getType(dataType, precision);
136 if (type == null) {
137 // this will only occur if the JDBC driver is buggy, as the
138 // database meta data is inconsistent with the column meta
139 // data
140 // Try and get the nearest precision equivalent
141 type = _types.getNearestType(dataType, precision);
142 if (type == null) {
143 // getColumns() refers to type not included in
144 // database meta data
145 throw new InvalidTypeException(
146 "JDBC driver error. Type=" + dataType
147 + ", precision=" + precision + "(SQL type="
148 + typeName + ") isn't supported by "
149 + "Connection.getMetaData().getTypeInfo(), but is "
150 + "referred to by "
151 + "Connection.getMetaData().getColumns()");
152 }
153 }
154
155 Attribute attribute = new Attribute();
156 attribute.setName(columnName);
157 attribute.setType(type.getSymbolicType());
158 if (nullable == DatabaseMetaData.columnNoNulls) {
159 attribute.setNot_null(true);
160 } else {
161 attribute.setNot_null(false);
162 }
163 result.addAttribute(attribute);
164 }
165 } catch (SQLException exception) {
166 throw new PersistenceException(
167 "Failed to determine the schema of table=" + name,
168 exception);
169 } finally {
170 SQLHelper.close(select);
171 }
172 return result;
173 }
174
175 /***
176 * Returns the {@link Type} for an {@link Attribute}
177 *
178 * @param attribute the attribute
179 * @return the type
180 * @throws PersistenceException if {@link Attribute#getType} is invalid, or
181 * the RDBMS doesn't support the type
182 */
183 public Type getType(Attribute attribute) throws PersistenceException {
184 Type result = null;
185 Type type = Type.getType(attribute.getType());
186 Type map = _mapper.getType(type.getType(), type.getPrecision());
187 if (map == null) {
188 throw new PersistenceException(
189 "Database does not support type=" + attribute.getType());
190 }
191
192 if (type.getType() != map.getType()) {
193 result = map;
194 } else {
195 boolean parameters = type.getParameters();
196 long precision = type.getPrecision();
197 if (precision <= map.getPrecision()) {
198 if (precision == -1) {
199 precision = map.getPrecision();
200 parameters = map.getParameters();
201 }
202 result = new Type(map.getType(), map.getName(),
203 precision, parameters);
204 } else {
205 throw new PersistenceException(
206 attribute.getName() + type + " exceeds precision for "
207 + map + " precision=" + map.getPrecision());
208 }
209 }
210 return result;
211 }
212
213 /***
214 * Returns true if a table exists
215 *
216 * @param table the name of the table
217 */
218 public boolean getTableExists(String table) throws PersistenceException {
219 boolean result = false;
220
221 String name = table;
222 ResultSet set = null;
223 try {
224 DatabaseMetaData metaData = _connection.getMetaData();
225 if (metaData.storesUpperCaseIdentifiers()) {
226 name = name.toUpperCase();
227 }
228
229 set = metaData.getTables(_connection.getCatalog(), null,
230 name, null);
231 if (set.next()) {
232 result = true;
233 }
234 } catch (SQLException exception) {
235 throw new PersistenceException("Failed to determine if table="
236 + table + " exists", exception);
237 } finally {
238 SQLHelper.close(set);
239 }
240 return result;
241 }
242
243 } //-- SchemaBrowser
This page was automatically generated by Maven