summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Winkler2008-12-01 08:35:29 (EST)
committerStefan Winkler2008-12-01 08:35:29 (EST)
commit02cc960c39a9b50c5c70f797eb3759b9148a5639 (patch)
tree7cbc9d3bc4a6b9c7a0a272c18a11a8b571985718
parentfd25da3564204637c89de2dd122c25a2514cde7c (diff)
downloadcdo-02cc960c39a9b50c5c70f797eb3759b9148a5639.zip
cdo-02cc960c39a9b50c5c70f797eb3759b9148a5639.tar.gz
cdo-02cc960c39a9b50c5c70f797eb3759b9148a5639.tar.bz2
[244290] [DB] Trailing backslash is not escaped
https://bugs.eclipse.org/bugs/show_bug.cgi?id=244290
-rw-r--r--plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/jdbc/StatementJDBCDelegate.java3
-rw-r--r--plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/DBStoreTest.java68
-rw-r--r--plugins/org.eclipse.net4j.db.derby/src/org/eclipse/net4j/db/derby/DerbyAdapter.java48
-rw-r--r--plugins/org.eclipse.net4j.db.hsqldb/src/org/eclipse/net4j/db/hsqldb/HSQLDBAdapter.java51
-rw-r--r--plugins/org.eclipse.net4j.db.mysql/src/org/eclipse/net4j/db/mysql/MYSQLAdapter.java56
-rw-r--r--plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/DBType.java19
6 files changed, 223 insertions, 22 deletions
diff --git a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/jdbc/StatementJDBCDelegate.java b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/jdbc/StatementJDBCDelegate.java
index ec175f7..28b11a8 100644
--- a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/jdbc/StatementJDBCDelegate.java
+++ b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/jdbc/StatementJDBCDelegate.java
@@ -74,8 +74,7 @@ public class StatementJDBCDelegate extends AbstractJDBCDelegate
for (IAttributeMapping attributeMapping : attributeMappings)
{
builder.append(", ");
- Object value = attributeMapping.getRevisionValue(revision);
- attributeMapping.getField().appendValue(builder, value);
+ attributeMapping.appendValue(builder, revision);
}
}
diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/DBStoreTest.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/DBStoreTest.java
index 98e782b..f25e7db 100644
--- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/DBStoreTest.java
+++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/DBStoreTest.java
@@ -12,6 +12,7 @@ package org.eclipse.emf.cdo.tests;
import org.eclipse.emf.cdo.CDOSession;
import org.eclipse.emf.cdo.CDOTransaction;
+import org.eclipse.emf.cdo.CDOView;
import org.eclipse.emf.cdo.eresource.CDOResource;
import org.eclipse.emf.cdo.tests.model1.Company;
import org.eclipse.emf.cdo.tests.model1.Model1Factory;
@@ -34,4 +35,71 @@ public class DBStoreTest extends AbstractCDOTest
t.commit();
}
+
+ public void testStoreStringTrailingBackslash()
+ {
+ storeRetrieve("foobar\\");
+ }
+
+ public void testStoreStringContainingBackslash()
+ {
+ storeRetrieve("foo\\bar");
+ }
+
+ public void testStoreStringTrailingSingleQuote()
+ {
+ storeRetrieve("foobar'");
+ }
+
+ public void testStoreStringContainingSingleQuote()
+ {
+ storeRetrieve("foo'bar");
+ }
+
+ public void testStoreStringTrailingDoubleQuote()
+ {
+ storeRetrieve("foobar\"");
+ }
+
+ public void testStoreStringContainingDoubleQuote()
+ {
+ storeRetrieve("foo\"bar");
+ }
+
+ public void testStoreStringTrailingTwoSingleQuote()
+ {
+ storeRetrieve("foobar''");
+ }
+
+ public void testStoreStringContainingTwoSingleQuote()
+ {
+ storeRetrieve("foo''bar");
+ }
+
+ private void storeRetrieve(String s)
+ {
+ CDOSession session = openModel1Session();
+ CDOTransaction transaction = session.openTransaction();
+ CDOResource resource = transaction.getOrCreateResource("/test");
+
+ Company e = Model1Factory.eINSTANCE.createCompany();
+ e.setName(s);
+ // this escapes only the string!
+ // resulting string only contains one backslash
+
+ resource.getContents().add(e);
+ transaction.commit();
+
+ transaction.close();
+ session.close();
+ clearCache(getRepository().getRevisionManager());
+
+ session = openModel1Session();
+ CDOView view = session.openView();
+ resource = view.getResource("/test");
+
+ assertEquals(1, resource.getContents().size());
+ e = (Company)resource.getContents().get(0);
+ assertEquals(s, e.getName());
+ }
}
diff --git a/plugins/org.eclipse.net4j.db.derby/src/org/eclipse/net4j/db/derby/DerbyAdapter.java b/plugins/org.eclipse.net4j.db.derby/src/org/eclipse/net4j/db/derby/DerbyAdapter.java
index bf902aa..9b6d773 100644
--- a/plugins/org.eclipse.net4j.db.derby/src/org/eclipse/net4j/db/derby/DerbyAdapter.java
+++ b/plugins/org.eclipse.net4j.db.derby/src/org/eclipse/net4j/db/derby/DerbyAdapter.java
@@ -14,6 +14,8 @@ import org.eclipse.net4j.db.DBType;
import org.eclipse.net4j.db.ddl.IDBField;
import org.eclipse.net4j.spi.db.DBAdapter;
+import java.util.StringTokenizer;
+
/**
* @author Eike Stepper
* @since 2.0
@@ -71,16 +73,58 @@ public abstract class DerbyAdapter extends DBAdapter
@Override
public void appendValue(StringBuilder builder, IDBField field, Object value)
{
+ Object newValue = value;
if (value instanceof Boolean)
{
- value = (Boolean)value ? 1 : 0;
+ newValue = (Boolean)value ? 1 : 0;
+ }
+ else if (value instanceof String)
+ {
+ // Derby just adds one additional single quote for a single quote
+ String str = (String)value;
+ StringTokenizer tokenizer = new StringTokenizer(str, "\'", true); // split on single quote
+ StringBuilder newValueBuilder = new StringBuilder();
+
+ while (tokenizer.hasMoreTokens())
+ {
+ String current = tokenizer.nextToken();
+ if (current.length() == 0)
+ {
+ continue;
+ }
+
+ if (current.length() > 1) // >1 -> can not be token -> normal string
+ {
+ newValueBuilder.append(current);
+ }
+ else
+ { // length == 1
+ newValueBuilder.append(processEscape(current.charAt(0)));
+ }
+ }
+
+ newValue = newValueBuilder.toString();
+ }
+ else if (value instanceof Character)
+ {
+ newValue = processEscape((Character)value);
}
- super.appendValue(builder, field, value);
+ super.appendValue(builder, field, newValue);
}
public String[] getReservedWords()
{
return RESERVED_WORDS;
}
+
+ private Object processEscape(char c)
+ {
+ if (c == '\'') // one single quote -->
+ {
+ return "\'\'"; // results two single quotes
+ }
+
+ return c; // no escape character --> return as is
+ }
}
diff --git a/plugins/org.eclipse.net4j.db.hsqldb/src/org/eclipse/net4j/db/hsqldb/HSQLDBAdapter.java b/plugins/org.eclipse.net4j.db.hsqldb/src/org/eclipse/net4j/db/hsqldb/HSQLDBAdapter.java
index 5788945..fdda6df 100644
--- a/plugins/org.eclipse.net4j.db.hsqldb/src/org/eclipse/net4j/db/hsqldb/HSQLDBAdapter.java
+++ b/plugins/org.eclipse.net4j.db.hsqldb/src/org/eclipse/net4j/db/hsqldb/HSQLDBAdapter.java
@@ -19,6 +19,7 @@ import org.hsqldb.jdbcDriver;
import javax.sql.DataSource;
import java.sql.Driver;
+import java.util.StringTokenizer;
/**
* @author Eike Stepper
@@ -95,4 +96,54 @@ public class HSQLDBAdapter extends DBAdapter
{
return getSQL92ReservedWords();
}
+
+ @Override
+ public void appendValue(StringBuilder builder, IDBField field, Object value)
+ {
+ Object newValue = value;
+
+ if (value instanceof String)
+ {
+ // HSQLDB just adds one additional single quote for a single quote
+ String str = (String)value;
+ StringTokenizer tokenizer = new StringTokenizer(str, "\'", true); // split on single quote
+ StringBuilder newValueBuilder = new StringBuilder();
+
+ while (tokenizer.hasMoreTokens())
+ {
+ String current = tokenizer.nextToken();
+ if (current.length() == 0)
+ {
+ continue;
+ }
+
+ if (current.length() > 1) // >1 -> can not be token -> normal string
+ {
+ newValueBuilder.append(current);
+ }
+ else
+ { // length == 1
+ newValueBuilder.append(processEscape(current.charAt(0)));
+ }
+ }
+
+ newValue = newValueBuilder.toString();
+ }
+ else if (value instanceof Character)
+ {
+ newValue = processEscape((Character)value);
+ }
+
+ super.appendValue(builder, field, newValue);
+ }
+
+ private Object processEscape(char c)
+ {
+ if (c == '\'') // one single quote -->
+ {
+ return "\'\'"; // results two single quotes
+ }
+
+ return c; // no escape character --> return as is
+ }
}
diff --git a/plugins/org.eclipse.net4j.db.mysql/src/org/eclipse/net4j/db/mysql/MYSQLAdapter.java b/plugins/org.eclipse.net4j.db.mysql/src/org/eclipse/net4j/db/mysql/MYSQLAdapter.java
index 33e7b46..07e2983 100644
--- a/plugins/org.eclipse.net4j.db.mysql/src/org/eclipse/net4j/db/mysql/MYSQLAdapter.java
+++ b/plugins/org.eclipse.net4j.db.mysql/src/org/eclipse/net4j/db/mysql/MYSQLAdapter.java
@@ -21,6 +21,7 @@ import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
import javax.sql.DataSource;
import java.sql.SQLException;
+import java.util.StringTokenizer;
/**
* @author Eike Stepper
@@ -137,4 +138,59 @@ public class MYSQLAdapter extends DBAdapter
return super.isTypeIndexable(type);
}
}
+
+ @Override
+ public void appendValue(StringBuilder builder, IDBField field, Object value)
+ {
+ Object newValue = value;
+
+ if (value instanceof String)
+ {
+ // MySQL does Java-Style backslash-escaping
+ String str = (String)value;
+ StringTokenizer st = new StringTokenizer(str, "\\\'", true); // split on backslash or single quote
+ StringBuilder newValueBuilder = new StringBuilder();
+
+ while (st.hasMoreTokens())
+ {
+ String current = st.nextToken();
+ if (current.length() == 0)
+ {
+ continue;
+ }
+
+ if (current.length() > 1) // >1 -> can not be token -> normal string
+ {
+ newValueBuilder.append(current);
+ }
+ else
+ { // length == 1
+ newValueBuilder.append(processEscape(current.charAt(0)));
+ }
+ }
+
+ newValue = newValueBuilder.toString();
+ }
+ else if (value instanceof Character)
+ {
+ newValue = processEscape((Character)value);
+ }
+
+ super.appendValue(builder, field, newValue);
+ }
+
+ private Object processEscape(char c)
+ {
+ if (c == '\\') // one backslash -->
+ {
+ return "\\\\"; // results in two backslashes
+ }
+
+ if (c == '\'') // one single quote -->
+ {
+ return "\\'"; // results in backslash+single quote
+ }
+
+ return c; // no escape character --> return as is
+ }
}
diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/DBType.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/DBType.java
index 730dffc..0c45c7a 100644
--- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/DBType.java
+++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/DBType.java
@@ -115,24 +115,7 @@ public enum DBType
if (value instanceof String || value instanceof Character)
{
builder.append("'");
- if (value instanceof String)
- {
- String str = (String)value;
- for (int i = 0; i < str.length(); i++)
- {
- char c = str.charAt(i);
- builder.append(c);
- if (c == '\'')
- {
- builder.append(c);
- }
- }
- }
- else
- {
- builder.append(value);
- }
-
+ builder.append(value);
builder.append("'");
}
else