1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.dbunit.database.search;
23
24 import java.sql.Connection;
25 import java.sql.DatabaseMetaData;
26 import java.sql.ResultSet;
27 import java.sql.SQLException;
28 import java.util.SortedSet;
29 import java.util.TreeSet;
30
31 import org.dbunit.database.DatabaseConfig;
32 import org.dbunit.database.IDatabaseConnection;
33 import org.dbunit.database.IMetadataHandler;
34 import org.dbunit.dataset.NoSuchTableException;
35 import org.dbunit.util.QualifiedTableName;
36 import org.dbunit.util.SQLHelper;
37 import org.dbunit.util.search.AbstractNodesFilterSearchCallback;
38 import org.dbunit.util.search.IEdge;
39 import org.dbunit.util.search.SearchException;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
42
43
44
45
46
47
48
49
50
51 public abstract class AbstractMetaDataBasedSearchCallback extends AbstractNodesFilterSearchCallback {
52
53
54
55
56 private static final Logger logger = LoggerFactory.getLogger(AbstractMetaDataBasedSearchCallback.class);
57
58 private final IDatabaseConnection connection;
59
60
61
62
63
64 public AbstractMetaDataBasedSearchCallback(IDatabaseConnection connection) {
65 this.connection = connection;
66 }
67
68
69
70
71
72 public IDatabaseConnection getConnection() {
73 return connection;
74 }
75
76 protected static final int IMPORT = 0;
77 protected static final int EXPORT = 1;
78
79
80
81
82 protected static final int[] TABLENAME_INDEXES = { 3, 7 };
83 protected static final int[] SCHEMANAME_INDEXES = { 2, 6 };
84 protected static final int[] PK_INDEXES = { 4, 4 };
85 protected static final int[] FK_INDEXES = { 8, 8 };
86
87
88
89
90
91
92
93
94
95 protected SortedSet getNodesFromImportedKeys(Object node)
96 throws SearchException {
97 logger.debug("getNodesFromImportedKeys(node={}) - start", node);
98
99 return getNodes(IMPORT, node);
100 }
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115 protected SortedSet getNodesFromExportedKeys(Object node)
116 throws SearchException {
117 logger.debug("getNodesFromExportedKeys(node={}) - start", node);
118
119 return getNodes(EXPORT, node);
120 }
121
122
123
124
125
126
127
128
129
130 protected SortedSet getNodesFromImportAndExportKeys(Object node)
131 throws SearchException {
132 logger.debug("getNodesFromImportAndExportKeys(node={}) - start", node);
133
134 SortedSet importedNodes = getNodesFromImportedKeys( node );
135 SortedSet exportedNodes = getNodesFromExportedKeys( node );
136 importedNodes.addAll( exportedNodes );
137 return importedNodes;
138 }
139
140 private SortedSet getNodes(int type, Object node) throws SearchException {
141 if(logger.isDebugEnabled())
142 logger.debug("getNodes(type={}, node={}) - start", Integer.toString(type), node);
143
144 try {
145 Connection conn = this.connection.getConnection();
146 String schema = this.connection.getSchema();
147 DatabaseMetaData metaData = conn.getMetaData();
148 SortedSet edges = new TreeSet();
149 getNodes(type, node, conn, schema, metaData, edges);
150 return edges;
151 } catch (SQLException e) {
152 throw new SearchException(e);
153 } catch (NoSuchTableException e) {
154 throw new SearchException(e);
155 }
156 }
157
158 private void getNodes(int type, Object node, Connection conn,
159 String schema, DatabaseMetaData metaData, SortedSet edges)
160 throws SearchException, NoSuchTableException
161 {
162 if (logger.isDebugEnabled())
163 {
164 logger.debug("getNodes(type={}, node={}, conn={}, schema={}, metaData={}, edges={}) - start",
165 new Object[] {String.valueOf(type), node, conn, schema, metaData, edges});
166 logger.debug("Getting edges for node " + node);
167 }
168
169 if (!(node instanceof String)) {
170 throw new IllegalArgumentException("node '" + node + "' should be a String, not a "
171 + node.getClass().getName());
172 }
173 String tableName = (String) node;
174
175 QualifiedTableName qualifiedTableName = new QualifiedTableName(tableName, schema);
176 schema = qualifiedTableName.getSchema();
177 tableName = qualifiedTableName.getTable();
178
179 ResultSet rs = null;
180 try {
181 IMetadataHandler metadataHandler = (IMetadataHandler)
182 this.connection.getConfig().getProperty(DatabaseConfig.PROPERTY_METADATA_HANDLER);
183
184 if(!metadataHandler.tableExists(metaData, schema, tableName))
185 {
186 throw new NoSuchTableException("The table '"+tableName+"' does not exist in schema '"+schema+"'");
187 }
188
189 switch (type) {
190 case IMPORT:
191 rs = metaData.getImportedKeys(null, schema, tableName);
192 break;
193 case EXPORT:
194 rs = metaData.getExportedKeys(null, schema, tableName);
195 break;
196 }
197
198
199
200 DatabaseConfig dbConfig = this.connection.getConfig();
201 while (rs.next()) {
202 int index = TABLENAME_INDEXES[type];
203 int schemaindex = SCHEMANAME_INDEXES[type];
204 String dependentTableName = rs.getString(index);
205 String dependentSchemaName = rs.getString(schemaindex);
206 String pkColumn = rs.getString( PK_INDEXES[type] );
207 String fkColumn = rs.getString( FK_INDEXES[type] );
208
209
210 tableName = new QualifiedTableName(tableName, schema).getQualifiedNameIfEnabled(dbConfig);
211 dependentTableName = new QualifiedTableName(dependentTableName, dependentSchemaName).getQualifiedNameIfEnabled(dbConfig);
212
213 IEdge edge = newEdge(rs, type, tableName, dependentTableName, fkColumn, pkColumn );
214 if ( logger.isDebugEnabled() ) {
215 logger.debug("Adding edge " + edge);
216 }
217 edges.add(edge);
218 }
219 }
220 catch (SQLException e) {
221 throw new SearchException(e);
222 }
223 finally
224 {
225 try {
226 SQLHelper.close(rs);
227 } catch (SQLException e) {
228 throw new SearchException(e);
229 }
230 }
231 }
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246 protected static ForeignKeyRelationshipEdge createFKEdge(ResultSet rs, int type,
247 String from, String to, String fkColumn, String pkColumn)
248 throws SearchException {
249 if (logger.isDebugEnabled()) {
250 logger.debug("createFKEdge(rs={}, type={}, from={}, to={}, fkColumn={}, pkColumn={}) - start",
251 new Object[] {rs, String.valueOf(type), from, to, fkColumn, pkColumn});
252 }
253
254 return type == IMPORT ?
255 new ForeignKeyRelationshipEdge( from, to, fkColumn, pkColumn ) :
256 new ForeignKeyRelationshipEdge( to, from, fkColumn, pkColumn );
257 }
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274 protected IEdge newEdge(ResultSet rs, int type, String from, String to, String fkColumn, String pkColumn)
275 throws SearchException {
276 if (logger.isDebugEnabled()) {
277 logger.debug("newEdge(rs={}, type={}, from={}, to={}, fkColumn={}, pkColumn={}) - start",
278 new Object[] {rs, String.valueOf(type), from, to, fkColumn, pkColumn});
279 }
280
281 return createFKEdge( rs, type, from, to, fkColumn, pkColumn );
282 }
283 }