Applied Tony Rippy's patch for DDLUTILS-246: JdbcModelReader merges metadata between tables, with minor modifications
git-svn-id: https://svn.apache.org/repos/asf/db/ddlutils/trunk@1002945 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/src/main/java/org/apache/ddlutils/platform/DatabaseMetaDataWrapper.java b/src/main/java/org/apache/ddlutils/platform/DatabaseMetaDataWrapper.java
index 8e512a1..861a7e4 100644
--- a/src/main/java/org/apache/ddlutils/platform/DatabaseMetaDataWrapper.java
+++ b/src/main/java/org/apache/ddlutils/platform/DatabaseMetaDataWrapper.java
@@ -22,14 +22,15 @@
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
+import java.util.regex.Pattern;
/**
* Wrapper class for database meta data that stores additional info.
- *
- * @version $Revision: 329426 $
*/
public class DatabaseMetaDataWrapper
{
+ /** Matches the characters not allowed in search strings. */
+ private final Pattern searchStringPattern = Pattern.compile("[_%]");
/** The database meta data. */
private DatabaseMetaData _metaData;
/** The catalog to acess in the database. */
@@ -137,6 +138,49 @@
System.arraycopy(types, 0, _tableTypes, 0, types.length);
}
}
+
+ /**
+ * Escape a string literal so that it can be used as a search pattern.
+ *
+ * @param literalString The string to escape.
+ * @return A string that can be properly used as a search string.
+ * @throws SQLException If an error occurred retrieving the meta data
+ */
+ public String escapeForSearch(String literalString) throws SQLException
+ {
+ String escape = getMetaData().getSearchStringEscape();
+
+ if (escape == "")
+ {
+ // No escape string, so nothing to do...
+ return literalString;
+ }
+ else
+ {
+ // with Java 5, we would just use Matcher.quoteReplacement
+ StringBuffer quotedEscape = new StringBuffer();
+
+ for (int idx = 0; idx < escape.length(); idx++)
+ {
+ char c = escape.charAt(idx);
+
+ switch (c)
+ {
+ case '\\':
+ quotedEscape.append("\\\\");
+ break;
+ case '$':
+ quotedEscape.append("\\$");
+ break;
+ default:
+ quotedEscape.append(c);
+ }
+ }
+ quotedEscape.append("$0");
+
+ return searchStringPattern.matcher(literalString).replaceAll(quotedEscape.toString());
+ }
+ }
/**
* Convenience method to return the table meta data using the configured catalog,
diff --git a/src/main/java/org/apache/ddlutils/platform/JdbcModelReader.java b/src/main/java/org/apache/ddlutils/platform/JdbcModelReader.java
index 667b635..a21e8a8 100644
--- a/src/main/java/org/apache/ddlutils/platform/JdbcModelReader.java
+++ b/src/main/java/org/apache/ddlutils/platform/JdbcModelReader.java
@@ -773,7 +773,7 @@
try
{
- columnData = metaData.getColumns(tableName, getDefaultColumnPattern());
+ columnData = metaData.getColumns(metaData.escapeForSearch(tableName), getDefaultColumnPattern());
List columns = new ArrayList();
@@ -856,7 +856,7 @@
try
{
- pkData = metaData.getPrimaryKeys(tableName);
+ pkData = metaData.getPrimaryKeys(metaData.escapeForSearch(tableName));
while (pkData.next())
{
Map values = readColumns(pkData, getColumnsForPK());
@@ -897,7 +897,7 @@
try
{
- fkData = metaData.getForeignKeys(tableName);
+ fkData = metaData.getForeignKeys(metaData.escapeForSearch(tableName));
while (fkData.next())
{
@@ -1004,7 +1004,7 @@
try
{
- indexData = metaData.getIndices(tableName, false, false);
+ indexData = metaData.getIndices(metaData.escapeForSearch(tableName), false, false);
while (indexData.next())
{
@@ -1236,7 +1236,7 @@
tablePattern = tablePattern.toUpperCase();
}
- tableData = metaData.getTables(tablePattern);
+ tableData = metaData.getTables(metaData.escapeForSearch(tablePattern));
boolean found = false;
String schema = null;
@@ -1249,7 +1249,7 @@
if ((tableName != null) && (tableName.length() > 0))
{
schema = (String)values.get("TABLE_SCHEM");
- columnData = metaData.getColumns(tableName, getDefaultColumnPattern());
+ columnData = metaData.getColumns(metaData.escapeForSearch(tableName), getDefaultColumnPattern());
found = true;
while (found && columnData.next())
diff --git a/src/main/java/org/apache/ddlutils/platform/db2/Db2ModelReader.java b/src/main/java/org/apache/ddlutils/platform/db2/Db2ModelReader.java
index 00c50b5..4f86e61 100644
--- a/src/main/java/org/apache/ddlutils/platform/db2/Db2ModelReader.java
+++ b/src/main/java/org/apache/ddlutils/platform/db2/Db2ModelReader.java
@@ -233,7 +233,7 @@
try
{
- pkData = metaData.getPrimaryKeys(table.getName());
+ pkData = metaData.getPrimaryKeys(metaData.escapeForSearch(table.getName()));
while (pkData.next())
{
Map values = readColumns(pkData, getColumnsForPK());
diff --git a/src/main/java/org/apache/ddlutils/platform/firebird/FirebirdModelReader.java b/src/main/java/org/apache/ddlutils/platform/firebird/FirebirdModelReader.java
index afb282a..eeee0ed 100644
--- a/src/main/java/org/apache/ddlutils/platform/firebird/FirebirdModelReader.java
+++ b/src/main/java/org/apache/ddlutils/platform/firebird/FirebirdModelReader.java
@@ -106,7 +106,7 @@
}
else
{
- columnData = metaData.getColumns(tableName, getDefaultColumnPattern());
+ columnData = metaData.getColumns(metaData.escapeForSearch(tableName), getDefaultColumnPattern());
while (columnData.next())
{
@@ -221,7 +221,7 @@
}
else
{
- pkData = metaData.getPrimaryKeys(tableName);
+ pkData = metaData.getPrimaryKeys(metaData.escapeForSearch(tableName));
while (pkData.next())
{
Map values = readColumns(pkData, getColumnsForPK());
@@ -265,7 +265,7 @@
}
else
{
- fkData = metaData.getForeignKeys(tableName);
+ fkData = metaData.getForeignKeys(metaData.escapeForSearch(tableName));
while (fkData.next())
{
Map values = readColumns(fkData, getColumnsForFK());
@@ -410,7 +410,7 @@
tablePattern = tablePattern.toUpperCase();
}
- tableData = metaData.getTables(tablePattern);
+ tableData = metaData.getTables(metaData.escapeForSearch(tablePattern));
boolean found = false;
String schema = null;
@@ -434,7 +434,7 @@
}
else
{
- columnData = metaData.getColumns(tableName, getDefaultColumnPattern());
+ columnData = metaData.getColumns(metaData.escapeForSearch(tableName), getDefaultColumnPattern());
}
while (found && columnData.next())
diff --git a/src/main/java/org/apache/ddlutils/platform/interbase/InterbaseModelReader.java b/src/main/java/org/apache/ddlutils/platform/interbase/InterbaseModelReader.java
index 3f88258..135700c 100644
--- a/src/main/java/org/apache/ddlutils/platform/interbase/InterbaseModelReader.java
+++ b/src/main/java/org/apache/ddlutils/platform/interbase/InterbaseModelReader.java
@@ -109,7 +109,7 @@
}
else
{
- columnData = metaData.getColumns(tableName, getDefaultColumnPattern());
+ columnData = metaData.getColumns(metaData.escapeForSearch(tableName), getDefaultColumnPattern());
while (columnData.next())
{
@@ -303,7 +303,7 @@
}
else
{
- pkData = metaData.getPrimaryKeys(tableName);
+ pkData = metaData.getPrimaryKeys(metaData.escapeForSearch(tableName));
while (pkData.next())
{
Map values = readColumns(pkData, getColumnsForPK());
@@ -347,7 +347,7 @@
}
else
{
- fkData = metaData.getForeignKeys(tableName);
+ fkData = metaData.getForeignKeys(metaData.escapeForSearch(tableName));
while (fkData.next())
{
Map values = readColumns(fkData, getColumnsForFK());
@@ -449,7 +449,7 @@
tablePattern = tablePattern.toUpperCase();
}
- tableData = metaData.getTables(tablePattern);
+ tableData = metaData.getTables(metaData.escapeForSearch(tablePattern));
boolean found = false;
String schema = null;
@@ -473,7 +473,7 @@
}
else
{
- columnData = metaData.getColumns(tableName, getDefaultColumnPattern());
+ columnData = metaData.getColumns(metaData.escapeForSearch(tableName), getDefaultColumnPattern());
}
while (found && columnData.next())
diff --git a/src/main/java/org/apache/ddlutils/platform/mssql/MSSqlModelReader.java b/src/main/java/org/apache/ddlutils/platform/mssql/MSSqlModelReader.java
index c4aa27b..f385140 100644
--- a/src/main/java/org/apache/ddlutils/platform/mssql/MSSqlModelReader.java
+++ b/src/main/java/org/apache/ddlutils/platform/mssql/MSSqlModelReader.java
@@ -147,7 +147,7 @@
try
{
- pks = metaData.getPrimaryKeys(table.getName());
+ pks = metaData.getPrimaryKeys(metaData.escapeForSearch(table.getName()));
while (pks.next())
{
diff --git a/src/test/java/org/apache/ddlutils/platform/TestDatabaseMetaDataWrapper.java b/src/test/java/org/apache/ddlutils/platform/TestDatabaseMetaDataWrapper.java
new file mode 100644
index 0000000..4ab20ef
--- /dev/null
+++ b/src/test/java/org/apache/ddlutils/platform/TestDatabaseMetaDataWrapper.java
@@ -0,0 +1,77 @@
+package org.apache.ddlutils.platform;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.sql.DatabaseMetaData;
+import org.apache.ddlutils.TestBase;
+
+/**
+ * Tests for the utility methods in the {@link DatabaseMetaDataWrapper} class.
+ */
+public class TestDatabaseMetaDataWrapper extends TestBase
+{
+ /**
+ * Helper method to create a proxied DatabaseMetaData instance using the given invocation handler.
+ *
+ * @param handler The handler
+ * @return The proxy object
+ */
+ private DatabaseMetaData createMockDatabaseMetaData(final InvocationHandler handler)
+ {
+ return (DatabaseMetaData)Proxy.newProxyInstance(getClass().getClassLoader(),
+ new Class[] { DatabaseMetaData.class },
+ handler);
+ }
+
+ /**
+ * Tests the {@link DatabaseMetaDataWrapper#escapeForSearch(String)} method (see DDLUTILS-246).
+ */
+ public void testEscapeSearchString() throws Exception
+ {
+ DatabaseMetaData metaData = createMockDatabaseMetaData(new InvocationHandler()
+ {
+ /**
+ * {@inheritDoc}
+ */
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
+ {
+ if ("getSearchStringEscape".equals(method.getName()))
+ {
+ return "\\";
+ }
+ else
+ {
+ throw new UnsupportedOperationException();
+ }
+ }
+ });
+
+ DatabaseMetaDataWrapper wrapper = new DatabaseMetaDataWrapper();
+
+ wrapper.setMetaData(metaData);
+
+ assertEquals("FOOMATIC", wrapper.escapeForSearch("FOOMATIC"));
+ assertEquals("FOO\\_MATIC", wrapper.escapeForSearch("FOO_MATIC"));
+ assertEquals("FOO\\%MATIC", wrapper.escapeForSearch("FOO%MATIC"));
+ }
+}