/*
* Copyright (c) 2006-2011 Nuxeo SA (http://nuxeo.com/) and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Florent Guillaume
*/
package org.eclipse.ecr.core.storage.sql.jdbc.dialect;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.DatabaseMetaData;
import junit.framework.TestCase;
import org.eclipse.ecr.core.model.Session;
import org.eclipse.ecr.core.storage.sql.BinaryManager;
import org.eclipse.ecr.core.storage.sql.RepositoryDescriptor;
import org.eclipse.ecr.core.storage.sql.jdbc.QueryMaker.QueryMakerException;
import org.eclipse.ecr.core.storage.sql.jdbc.dialect.Dialect.FulltextQuery;
import org.eclipse.ecr.core.storage.sql.jdbc.dialect.Dialect.FulltextQuery.Op;
public class TestDialectQuerySyntax extends TestCase {
protected static class DatabaseMetaDataInvocationHandler implements
InvocationHandler {
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
String name = method.getName();
if (name.equals("storesUpperCaseIdentifiers")) {
return Boolean.FALSE;
} else if (name.equals("getDatabaseMajorVersion")) {
return Integer.valueOf(0);
} else if (name.equals("getDatabaseMinorVersion")) {
return Integer.valueOf(0);
}
return null;
}
}
public static DatabaseMetaData getDatabaseMetaData() {
return (DatabaseMetaData) Proxy.newProxyInstance(
Session.class.getClassLoader(),
new Class<?>[] { DatabaseMetaData.class },
new DatabaseMetaDataInvocationHandler());
}
public DatabaseMetaData metadata;
public BinaryManager binaryManager;
public RepositoryDescriptor repositoryDescriptor;
public Dialect dialect;
@Override
public void setUp() {
metadata = getDatabaseMetaData();
binaryManager = null;
repositoryDescriptor = new RepositoryDescriptor();
}
protected static void assertFulltextException(String query) {
try {
Dialect.analyzeFulltextQuery(query);
fail("Query should fail: " + query);
} catch (QueryMakerException e) {
// ok
}
}
protected static void dumpFulltextQuery(FulltextQuery ft, StringBuilder buf) {
if (ft.op == Op.AND || ft.op == Op.OR) {
assertNull(ft.word);
buf.append('[');
for (int i = 0; i < ft.terms.size(); i++) {
if (i != 0) {
buf.append(' ');
buf.append(ft.op.name());
buf.append(' ');
}
dumpFulltextQuery(ft.terms.get(i), buf);
}
buf.append(']');
return;
} else {
assertNull(ft.terms);
if (ft.op == Op.NOTWORD) {
buf.append('~');
}
boolean isPhrase = ft.word.contains(" ");
if (isPhrase) {
buf.append('{');
}
buf.append(ft.word);
if (isPhrase) {
buf.append('}');
}
}
}
protected static void assertFulltextQuery(String expected, String query) {
StringBuilder buf = new StringBuilder();
FulltextQuery ftQuery = Dialect.analyzeFulltextQuery(query);
if (ftQuery == null) {
assertNull(expected);
return;
} else {
dumpFulltextQuery(ftQuery, buf);
assertEquals(expected, buf.toString());
}
}
public void testAnalyzeFulltextQuery() throws Exception {
dialect = new DialectH2(metadata, binaryManager, repositoryDescriptor);
// invalid queries
assertFulltextException("OR foo");
assertFulltextException("OR foo bar");
assertFulltextException("foo OR");
assertFulltextException("foo bar OR");
assertFulltextException("foo OR OR bar");
assertFulltextException("foo bar OR OR baz");
assertFulltextException("foo + bar");
assertFulltextException("foo - bar");
// ok queries
assertFulltextQuery(null, "");
assertFulltextQuery(null, " ");
assertFulltextQuery("foo", "foo");
assertFulltextQuery("foo", " foo ");
assertFulltextQuery("[foo AND bar]", "foo bar");
assertFulltextQuery("[foo AND bar AND baz]", "foo bar baz");
assertFulltextQuery("[foo AND ~bar]", "foo -bar");
assertFulltextQuery("[foo AND baz AND ~bar]", "foo -bar baz");
assertFulltextQuery("[foo AND ~bar AND ~baz]", "foo -bar -baz");
assertFulltextQuery("[bar AND ~foo]", "-foo bar");
assertFulltextQuery("[bar AND baz AND ~foo]", "-foo bar baz");
// queries with OR
assertFulltextQuery("[foo OR bar]", "foo OR bar");
assertFulltextQuery("[foo OR [bar AND baz]]", "foo OR bar baz");
assertFulltextQuery("[[foo AND bar] OR baz]", "foo bar OR baz");
assertFulltextQuery("[foo OR bar OR baz]", "foo OR bar OR baz");
assertFulltextQuery("[foo OR [bar AND baz] OR gee]",
"foo OR bar baz OR gee");
assertFulltextQuery("[[bar AND ~foo] OR baz]", "-foo bar OR baz");
assertFulltextQuery("[foo OR [bar AND ~baz]]", "foo OR bar -baz");
// queries containing suppressed terms
assertFulltextQuery(null, "-foo");
assertFulltextQuery(null, "-foo -bar");
assertFulltextQuery("bar", "-foo OR bar");
assertFulltextQuery("foo", "foo OR -bar");
assertFulltextQuery(null, "-foo OR -bar");
assertFulltextQuery("foo", "foo OR -bar -baz");
assertFulltextQuery("baz", "-foo -bar OR baz");
// query with phrases
assertFulltextException("\"foo");
assertFulltextException("\"foo bar");
assertFulltextException("\"fo\"o\"");
assertFulltextQuery(null, "\"\"");
assertFulltextQuery(null, " \" \" ");
assertFulltextQuery("foo", "\"foo\"");
assertFulltextQuery("foo", "+\"foo\"");
assertFulltextQuery(null, "-\"foo\"");
assertFulltextQuery("foo", "\" foo\"");
assertFulltextQuery("foo", "\"foo \"");
assertFulltextQuery("foo", "\" foo \"");
assertFulltextQuery("OR", "\"OR\"");
assertFulltextQuery("{foo bar}", "\"foo bar\"");
assertFulltextQuery("{foo bar}", "\" foo bar\"");
assertFulltextQuery("{foo bar}", "\"foo bar \"");
assertFulltextQuery("{foo bar}", "\" foo bar \"");
assertFulltextQuery("{foo bar}", "+\"foo bar\"");
assertFulltextQuery("{foo or bar}", "\"foo or bar\"");
assertFulltextQuery(null, "-\"foo bar\"");
assertFulltextQuery("[foo AND {bar baz}]", "foo \"bar baz\"");
assertFulltextQuery("[foo AND {bar baz}]", "foo +\"bar baz\"");
assertFulltextQuery("[foo AND ~{bar baz}]", "foo -\"bar baz\"");
assertFulltextQuery("[{foo bar} AND baz]", "\"foo bar\" baz");
assertFulltextQuery("[{foo bar} AND baz]", "+\"foo bar\" baz");
assertFulltextQuery("[baz AND ~{foo bar}]", "-\"foo bar\" baz");
assertFulltextQuery("[{foo bar} AND ~{baz gee}]",
"\"foo bar\" -\"baz gee\"");
}
protected void assertDialectFT(String expected, String query) {
assertEquals(expected, dialect.getDialectFulltextQuery(query));
}
public void testH2() throws Exception {
dialect = new DialectH2(metadata, binaryManager, repositoryDescriptor);
assertDialectFT("DONTMATCHANYTHINGFOREMPTYQUERY", "");
assertDialectFT("foo", "foo");
assertDialectFT("(foo AND bar)", "foo bar");
assertDialectFT("(foo NOT bar)", "foo -bar");
assertDialectFT("(bar NOT foo)", "-foo bar");
assertDialectFT("(foo OR bar)", "foo OR bar");
assertDialectFT("foo", "foo OR -bar");
assertDialectFT("((foo AND bar) OR baz)", "foo bar OR baz");
assertDialectFT("((bar NOT foo) OR baz)", "-foo bar OR baz");
assertDialectFT("((foo NOT bar) OR baz)", "foo -bar OR baz");
assertDialectFT("\"foo bar\"", "\"foo bar\"");
assertDialectFT("(\"foo bar\" AND baz)", "\"foo bar\" baz");
assertDialectFT("(\"foo bar\" OR baz)", "\"foo bar\" OR baz");
assertDialectFT("((\"foo bar\" AND baz) OR \"gee man\")",
"\"foo bar\" baz OR \"gee man\"");
}
public void testPostgreSQL() throws Exception {
dialect = new DialectPostgreSQL(metadata, binaryManager,
repositoryDescriptor);
assertDialectFT("", "-foo");
assertDialectFT("foo", "foo");
assertDialectFT("(foo & bar)", "foo bar ");
assertDialectFT("(foo & bar)", "foo & bar"); // compat
assertDialectFT("(foo & ! bar)", "foo -bar");
assertDialectFT("(bar & ! foo)", "-foo bar");
assertDialectFT("(foo | bar)", "foo OR bar");
assertDialectFT("foo", "foo OR -bar");
assertDialectFT("((foo & bar) | baz)", "foo bar OR baz");
assertDialectFT("((bar & ! foo) | baz)", "-foo bar OR baz");
assertDialectFT("((foo & ! bar) | baz)", "foo -bar OR baz");
}
public void testMySQL() throws Exception {
dialect = new DialectMySQL(metadata, binaryManager,
repositoryDescriptor);
assertDialectFT("DONTMATCHANYTHINGFOREMPTYQUERY", "-foo");
assertDialectFT("foo", "foo");
assertDialectFT("(+foo +bar)", "foo bar");
assertDialectFT("(+foo -bar)", "foo -bar");
assertDialectFT("(+bar -foo)", "-foo bar");
assertDialectFT("(foo bar)", "foo OR bar");
assertDialectFT("foo", "foo OR -bar");
assertDialectFT("((+foo +bar) baz)", "foo bar OR baz");
assertDialectFT("((+bar -foo) baz)", "-foo bar OR baz");
assertDialectFT("((+foo -bar) baz)", "foo -bar OR baz");
assertDialectFT("\"foo bar\"", "\"foo bar\"");
assertDialectFT("(+\"foo bar\" +baz)", "\"foo bar\" baz");
assertDialectFT("(\"foo bar\" baz)", "\"foo bar\" OR baz");
assertDialectFT("((+\"foo bar\" +baz) \"gee man\")",
"\"foo bar\" baz OR \"gee man\"");
}
public void testOracle() throws Exception {
dialect = new DialectOracle(metadata, binaryManager,
repositoryDescriptor);
assertDialectFT("DONTMATCHANYTHINGFOREMPTYQUERY", "-foo");
assertDialectFT("foo", "foo");
assertDialectFT("foo%", "foo*"); // special
assertDialectFT("(foo AND bar)", "foo bar");
assertDialectFT("(foo NOT bar)", "foo -bar");
assertDialectFT("(bar NOT foo)", "-foo bar");
assertDialectFT("(foo OR bar)", "foo OR bar");
assertDialectFT("foo", "foo OR -bar");
assertDialectFT("((foo AND bar) OR baz)", "foo bar OR baz");
assertDialectFT("((bar NOT foo) OR baz)", "-foo bar OR baz");
assertDialectFT("((foo NOT bar) OR baz)", "foo -bar OR baz");
assertDialectFT("foo bar", "\"foo bar\"");
assertDialectFT("(foo bar AND baz)", "\"foo bar\" baz");
assertDialectFT("(foo bar OR baz)", "\"foo bar\" OR baz");
assertDialectFT("((foo bar AND baz) OR gee man)",
"\"foo bar\" baz OR \"gee man\"");
}
public void testSQLServer() throws Exception {
dialect = new DialectSQLServer(metadata, binaryManager,
repositoryDescriptor);
assertDialectFT("DONTMATCHANYTHINGFOREMPTYQUERY", "-foo");
assertDialectFT("foo", "foo");
assertDialectFT("(foo AND bar)", "foo bar");
assertDialectFT("(foo AND NOT bar)", "foo -bar");
assertDialectFT("(bar AND NOT foo)", "-foo bar");
assertDialectFT("(foo OR bar)", "foo OR bar");
assertDialectFT("foo", "foo OR -bar");
assertDialectFT("((foo AND bar) OR baz)", "foo bar OR baz");
assertDialectFT("((bar AND NOT foo) OR baz)", "-foo bar OR baz");
assertDialectFT("((foo AND NOT bar) OR baz)", "foo -bar OR baz");
assertDialectFT("\"foo bar\"", "\"foo bar\"");
assertDialectFT("(\"foo bar\" AND baz)", "\"foo bar\" baz");
assertDialectFT("(\"foo bar\" OR baz)", "\"foo bar\" OR baz");
assertDialectFT("((\"foo bar\" AND baz) OR \"gee man\")",
"\"foo bar\" baz OR \"gee man\"");
}
}