Index: jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/GQLTest.java =================================================================== --- jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/GQLTest.java (revision 1205781) +++ jackrabbit-core/src/test/java/org/apache/jackrabbit/core/integration/GQLTest.java (working copy) @@ -139,6 +139,18 @@ checkResultWithRetries(stmt, "jcr:content", new Node[]{file1}); } + /** + * Test for JCR-3157 + */ + public void testApostrophe() throws RepositoryException { + Node n1 = testRootNode.addNode("node1"); + n1.setProperty("text", "let's go"); + superuser.save(); + String stmt = createStatement("\"let's go\""); + RowIterator rows = GQL.execute(stmt, superuser); + checkResult(rows, new Node[]{n1}); + } + public void testExcludeTerm() throws RepositoryException { Node n1 = testRootNode.addNode("node1"); n1.setProperty("text", "foo"); Index: jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/query/GQL.java =================================================================== --- jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/query/GQL.java (revision 1205781) +++ jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/query/GQL.java (working copy) @@ -712,7 +712,6 @@ value.append(c); break; } - case '\'': case '~': case '^': case '[': @@ -961,11 +960,13 @@ } } buffer.append(", '"); + // properly escape apostrophe. See JCR-3157 + String escapedValue = value.replaceAll("'", "\\\\''"); if (value.indexOf(' ') != -1) { // phrase - buffer.append('"').append(value).append('"'); + buffer.append('"').append(escapedValue).append('"'); } else { - buffer.append(value); + buffer.append(escapedValue); } buffer.append("')"); if (prohibited) {