1*f7cf3d52SAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 3*f7cf3d52SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 4*f7cf3d52SAndrew Rist * or more contributor license agreements. See the NOTICE file 5*f7cf3d52SAndrew Rist * distributed with this work for additional information 6*f7cf3d52SAndrew Rist * regarding copyright ownership. The ASF licenses this file 7*f7cf3d52SAndrew Rist * to you under the Apache License, Version 2.0 (the 8*f7cf3d52SAndrew Rist * "License"); you may not use this file except in compliance 9*f7cf3d52SAndrew Rist * with the License. You may obtain a copy of the License at 10cdf0e10cSrcweir * 11*f7cf3d52SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12cdf0e10cSrcweir * 13*f7cf3d52SAndrew Rist * Unless required by applicable law or agreed to in writing, 14*f7cf3d52SAndrew Rist * software distributed under the License is distributed on an 15*f7cf3d52SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*f7cf3d52SAndrew Rist * KIND, either express or implied. See the License for the 17*f7cf3d52SAndrew Rist * specific language governing permissions and limitations 18*f7cf3d52SAndrew Rist * under the License. 19cdf0e10cSrcweir * 20*f7cf3d52SAndrew Rist *************************************************************/ 21*f7cf3d52SAndrew Rist 22*f7cf3d52SAndrew Rist 23cdf0e10cSrcweir package complex.dbaccess; 24cdf0e10cSrcweir 25cdf0e10cSrcweir import com.sun.star.beans.PropertyState; 26cdf0e10cSrcweir import com.sun.star.sdb.SQLFilterOperator; 27cdf0e10cSrcweir import com.sun.star.beans.PropertyAttribute; 28cdf0e10cSrcweir import com.sun.star.beans.XPropertySet; 29cdf0e10cSrcweir import com.sun.star.beans.XPropertyContainer; 30cdf0e10cSrcweir import com.sun.star.beans.NamedValue; 31cdf0e10cSrcweir import com.sun.star.container.XNameAccess; 32cdf0e10cSrcweir import com.sun.star.sdbcx.XTablesSupplier; 33cdf0e10cSrcweir import com.sun.star.sdb.XParametersSupplier; 34cdf0e10cSrcweir import com.sun.star.beans.PropertyValue; 35cdf0e10cSrcweir import com.sun.star.sdbcx.XColumnsSupplier; 36cdf0e10cSrcweir import com.sun.star.container.XIndexAccess; 37cdf0e10cSrcweir import com.sun.star.sdb.CommandType; 38cdf0e10cSrcweir import com.sun.star.sdb.XSingleSelectQueryComposer; 39cdf0e10cSrcweir import com.sun.star.uno.UnoRuntime; 40cdf0e10cSrcweir 41cdf0e10cSrcweir import com.sun.star.sdbc.DataType; 42cdf0e10cSrcweir import java.lang.reflect.InvocationTargetException; 43cdf0e10cSrcweir import java.lang.reflect.Method; 44cdf0e10cSrcweir 45cdf0e10cSrcweir // ---------- junit imports ----------------- 46cdf0e10cSrcweir import org.junit.Test; 47cdf0e10cSrcweir import static org.junit.Assert.*; 48cdf0e10cSrcweir // ------------------------------------------ 49cdf0e10cSrcweir 50cdf0e10cSrcweir public class SingleSelectQueryComposer extends CRMBasedTestCase 51cdf0e10cSrcweir { 52cdf0e10cSrcweir 53cdf0e10cSrcweir private XSingleSelectQueryComposer m_composer = null; 54cdf0e10cSrcweir private final static String COMPLEXFILTER = "( \"ID\" = 1 AND \"Postal\" = '4' )" 55cdf0e10cSrcweir + " OR ( \"ID\" = 2 AND \"Postal\" = '5' )" 56cdf0e10cSrcweir + " OR ( \"ID\" = 3 AND \"Postal\" = '6' AND \"Address\" = '7' )" 57cdf0e10cSrcweir + " OR ( \"Address\" = '8' )" 58cdf0e10cSrcweir + " OR ( \"Postal\" = '9' )" 59cdf0e10cSrcweir + " OR ( NOW( ) = {D '2010-01-01' } )"; 60cdf0e10cSrcweir private final static String INNERPRODUCTSQUERY = "products (inner)"; 61cdf0e10cSrcweir 62cdf0e10cSrcweir // -------------------------------------------------------------------------------------------------------- createQueries()63cdf0e10cSrcweir private void createQueries() throws Exception 64cdf0e10cSrcweir { 65cdf0e10cSrcweir m_database.getDatabase().getDataSource().createQuery(INNERPRODUCTSQUERY, "SELECT * FROM \"products\""); 66cdf0e10cSrcweir } 67cdf0e10cSrcweir 68cdf0e10cSrcweir // -------------------------------------------------------------------------------------------------------- 69cdf0e10cSrcweir @Override createTestCase()70cdf0e10cSrcweir protected void createTestCase() 71cdf0e10cSrcweir { 72cdf0e10cSrcweir try 73cdf0e10cSrcweir { 74cdf0e10cSrcweir super.createTestCase(); 75cdf0e10cSrcweir 76cdf0e10cSrcweir createQueries(); 77cdf0e10cSrcweir 78cdf0e10cSrcweir m_composer = createQueryComposer(); 79cdf0e10cSrcweir 80cdf0e10cSrcweir } 81cdf0e10cSrcweir catch (Exception e) 82cdf0e10cSrcweir { 83cdf0e10cSrcweir fail("caught an exception (" + e.getMessage() + ") while creating the test case"); 84cdf0e10cSrcweir } 85cdf0e10cSrcweir } 86cdf0e10cSrcweir 87cdf0e10cSrcweir // -------------------------------------------------------------------------------------------------------- checkAttributeAccess(String _attributeName, String _attributeValue)88cdf0e10cSrcweir private void checkAttributeAccess(String _attributeName, String _attributeValue) 89cdf0e10cSrcweir { 90cdf0e10cSrcweir System.out.println("setting " + _attributeName + " to " + _attributeValue); 91cdf0e10cSrcweir String realValue = null; 92cdf0e10cSrcweir try 93cdf0e10cSrcweir { 94cdf0e10cSrcweir final Class composerClass = m_composer.getClass(); 95cdf0e10cSrcweir final Method attributeGetter = composerClass.getMethod("get" + _attributeName, new Class[] 96cdf0e10cSrcweir { 97cdf0e10cSrcweir }); 98cdf0e10cSrcweir final Method attributeSetter = composerClass.getMethod("set" + _attributeName, new Class[] 99cdf0e10cSrcweir { 100cdf0e10cSrcweir String.class 101cdf0e10cSrcweir }); 102cdf0e10cSrcweir 103cdf0e10cSrcweir attributeSetter.invoke(m_composer, new Object[] 104cdf0e10cSrcweir { 105cdf0e10cSrcweir _attributeValue 106cdf0e10cSrcweir }); 107cdf0e10cSrcweir realValue = (String) attributeGetter.invoke(m_composer, new Object[] 108cdf0e10cSrcweir { 109cdf0e10cSrcweir }); 110cdf0e10cSrcweir } 111cdf0e10cSrcweir catch (NoSuchMethodException e) 112cdf0e10cSrcweir { 113cdf0e10cSrcweir } 114cdf0e10cSrcweir catch (IllegalAccessException e) 115cdf0e10cSrcweir { 116cdf0e10cSrcweir } 117cdf0e10cSrcweir catch (InvocationTargetException e) 118cdf0e10cSrcweir { 119cdf0e10cSrcweir } 120cdf0e10cSrcweir assertTrue("set/get" + _attributeName + " not working as expected (set: " + _attributeValue + ", get: " + (realValue != null ? realValue : "null") + ")", 121cdf0e10cSrcweir realValue.equals(_attributeValue)); 122cdf0e10cSrcweir System.out.println(" (results in " + m_composer.getQuery() + ")"); 123cdf0e10cSrcweir } 124cdf0e10cSrcweir 125cdf0e10cSrcweir /** tests setCommand of the composer 126cdf0e10cSrcweir */ 127cdf0e10cSrcweir @Test testSetCommand()128cdf0e10cSrcweir public void testSetCommand() 129cdf0e10cSrcweir { 130cdf0e10cSrcweir System.out.println("testing SingleSelectQueryComposer's setCommand"); 131cdf0e10cSrcweir 132cdf0e10cSrcweir try 133cdf0e10cSrcweir { 134cdf0e10cSrcweir final String table = "SELECT * FROM \"customers\""; 135cdf0e10cSrcweir m_composer.setCommand("customers", CommandType.TABLE); 136cdf0e10cSrcweir assertTrue("setCommand/getQuery TABLE inconsistent", m_composer.getQuery().equals(table)); 137cdf0e10cSrcweir 138cdf0e10cSrcweir m_database.getDatabase().getDataSource().createQuery("set command test", "SELECT * FROM \"orders for customer\" \"a\", \"customers\" \"b\" WHERE \"a\".\"Product Name\" = \"b\".\"Name\""); 139cdf0e10cSrcweir m_composer.setCommand("set command test", CommandType.QUERY); 140cdf0e10cSrcweir assertTrue("setCommand/getQuery QUERY inconsistent", m_composer.getQuery().equals(m_database.getDatabase().getDataSource().getQueryDefinition("set command test").getCommand())); 141cdf0e10cSrcweir 142cdf0e10cSrcweir final String sql = "SELECT * FROM \"orders for customer\" WHERE \"Product Name\" = 'test'"; 143cdf0e10cSrcweir m_composer.setCommand(sql, CommandType.COMMAND); 144cdf0e10cSrcweir assertTrue("setCommand/getQuery COMMAND inconsistent", m_composer.getQuery().equals(sql)); 145cdf0e10cSrcweir } 146cdf0e10cSrcweir catch (Exception e) 147cdf0e10cSrcweir { 148cdf0e10cSrcweir fail("Exception caught: " + e); 149cdf0e10cSrcweir } 150cdf0e10cSrcweir } 151cdf0e10cSrcweir 152cdf0e10cSrcweir /** tests accessing attributes of the composer (order, filter, group by, having) 153cdf0e10cSrcweir */ 154cdf0e10cSrcweir @Test testAttributes()155cdf0e10cSrcweir public void testAttributes() 156cdf0e10cSrcweir { 157cdf0e10cSrcweir System.out.println("testing SingleSelectQueryComposer's attributes (order, filter, group by, having)"); 158cdf0e10cSrcweir 159cdf0e10cSrcweir try 160cdf0e10cSrcweir { 161cdf0e10cSrcweir System.out.println("check setElementaryQuery"); 162cdf0e10cSrcweir 163cdf0e10cSrcweir final String simpleQuery2 = "SELECT * FROM \"customers\" WHERE \"Name\" = 'oranges'"; 164cdf0e10cSrcweir m_composer.setElementaryQuery(simpleQuery2); 165cdf0e10cSrcweir assertTrue("setElementaryQuery/getQuery inconsistent", m_composer.getQuery().equals(simpleQuery2)); 166cdf0e10cSrcweir 167cdf0e10cSrcweir System.out.println("check setQuery"); 168cdf0e10cSrcweir final String simpleQuery = "SELECT * FROM \"customers\""; 169cdf0e10cSrcweir m_composer.setQuery(simpleQuery); 170cdf0e10cSrcweir assertTrue("set/getQuery inconsistent", m_composer.getQuery().equals(simpleQuery)); 171cdf0e10cSrcweir 172cdf0e10cSrcweir checkAttributeAccess("Filter", "\"Name\" = 'oranges'"); 173cdf0e10cSrcweir checkAttributeAccess("Group", "\"City\""); 174cdf0e10cSrcweir checkAttributeAccess("Order", "\"Address\""); 175cdf0e10cSrcweir checkAttributeAccess("HavingClause", "\"ID\" <> 4"); 176cdf0e10cSrcweir 177cdf0e10cSrcweir final XIndexAccess orderColumns = m_composer.getOrderColumns(); 178cdf0e10cSrcweir assertTrue("Order columns doesn't exist: \"Address\"", 179cdf0e10cSrcweir orderColumns != null && orderColumns.getCount() == 1 && orderColumns.getByIndex(0) != null); 180cdf0e10cSrcweir 181cdf0e10cSrcweir final XIndexAccess groupColumns = m_composer.getGroupColumns(); 182cdf0e10cSrcweir assertTrue("Group columns doesn't exist: \"City\"", 183cdf0e10cSrcweir groupColumns != null && groupColumns.getCount() == 1 && groupColumns.getByIndex(0) != null); 184cdf0e10cSrcweir 185cdf0e10cSrcweir // XColumnsSupplier 186cdf0e10cSrcweir final XColumnsSupplier xSelectColumns = UnoRuntime.queryInterface(XColumnsSupplier.class, m_composer); 187cdf0e10cSrcweir assertTrue("no select columns, or wrong number of select columns", 188cdf0e10cSrcweir xSelectColumns != null && xSelectColumns.getColumns() != null && xSelectColumns.getColumns().getElementNames().length == 6); 189cdf0e10cSrcweir 190cdf0e10cSrcweir // structured filter 191cdf0e10cSrcweir m_composer.setQuery("SELECT \"ID\", \"Postal\", \"Address\" FROM \"customers\""); 192cdf0e10cSrcweir m_composer.setFilter(COMPLEXFILTER); 193cdf0e10cSrcweir final PropertyValue[][] aStructuredFilter = m_composer.getStructuredFilter(); 194cdf0e10cSrcweir m_composer.setFilter(""); 195cdf0e10cSrcweir m_composer.setStructuredFilter(aStructuredFilter); 196cdf0e10cSrcweir if (!m_composer.getFilter().equals(COMPLEXFILTER)) 197cdf0e10cSrcweir { 198cdf0e10cSrcweir System.out.println(COMPLEXFILTER); 199cdf0e10cSrcweir System.out.println(m_composer.getFilter()); 200cdf0e10cSrcweir } 201cdf0e10cSrcweir assertTrue("Structured Filter not identical", m_composer.getFilter().equals(COMPLEXFILTER)); 202cdf0e10cSrcweir 203cdf0e10cSrcweir // structured having clause 204cdf0e10cSrcweir m_composer.setHavingClause(COMPLEXFILTER); 205cdf0e10cSrcweir final PropertyValue[][] aStructuredHaving = m_composer.getStructuredHavingClause(); 206cdf0e10cSrcweir m_composer.setHavingClause(""); 207cdf0e10cSrcweir m_composer.setStructuredHavingClause(aStructuredHaving); 208cdf0e10cSrcweir assertTrue("Structured Having Clause not identical", m_composer.getHavingClause().equals(COMPLEXFILTER)); 209cdf0e10cSrcweir } 210cdf0e10cSrcweir catch (Exception e) 211cdf0e10cSrcweir { 212cdf0e10cSrcweir fail("Exception caught: " + e); 213cdf0e10cSrcweir } 214cdf0e10cSrcweir } 215cdf0e10cSrcweir 216cdf0e10cSrcweir /** test various sub query related features ("queries in queries") 217cdf0e10cSrcweir */ 218cdf0e10cSrcweir @Test testSubQueries()219cdf0e10cSrcweir public void testSubQueries() throws Exception 220cdf0e10cSrcweir { 221cdf0e10cSrcweir m_composer.setQuery("SELECT * from \"" + INNERPRODUCTSQUERY + "\""); 222cdf0e10cSrcweir final XTablesSupplier suppTables = UnoRuntime.queryInterface(XTablesSupplier.class, m_composer); 223cdf0e10cSrcweir final XNameAccess tables = suppTables.getTables(); 224cdf0e10cSrcweir assertTrue("a simple SELECT * FROM <query> could not be parsed", 225cdf0e10cSrcweir tables != null && tables.hasByName(INNERPRODUCTSQUERY)); 226cdf0e10cSrcweir 227cdf0e10cSrcweir final String sInnerCommand = m_database.getDatabase().getDataSource().getQueryDefinition(INNERPRODUCTSQUERY).getCommand(); 228cdf0e10cSrcweir final String sExecutableQuery = m_composer.getQueryWithSubstitution(); 229cdf0e10cSrcweir assertTrue("simple query containing a sub query improperly parsed to SDBC level statement: \n1. " + sExecutableQuery + "\n2. " + "SELECT * FROM ( " + sInnerCommand + " ) AS \"" + INNERPRODUCTSQUERY + "\"", 230cdf0e10cSrcweir sExecutableQuery.equals("SELECT * FROM ( " + sInnerCommand + " ) AS \"" + INNERPRODUCTSQUERY + "\"")); 231cdf0e10cSrcweir } 232cdf0e10cSrcweir 233cdf0e10cSrcweir /** tests the XParametersSupplier functionality 234cdf0e10cSrcweir */ 235cdf0e10cSrcweir @Test testParameters()236cdf0e10cSrcweir public void testParameters() 237cdf0e10cSrcweir { 238cdf0e10cSrcweir try 239cdf0e10cSrcweir { 240cdf0e10cSrcweir // "orders for customers" is a query with a named parameter (based on another query) 241cdf0e10cSrcweir m_database.getDatabase().getDataSource().createQuery("orders for customer", "SELECT * FROM \"all orders\" WHERE \"Customer Name\" LIKE :cname"); 242cdf0e10cSrcweir // "orders for customer and product" is query based on "orders for customers", adding an additional, 243cdf0e10cSrcweir // anonymous parameter 244cdf0e10cSrcweir m_database.getDatabase().getDataSource().createQuery("orders for customer and product", "SELECT * FROM \"orders for customer\" WHERE \"Product Name\" LIKE ?"); 245cdf0e10cSrcweir 246cdf0e10cSrcweir m_composer.setQuery(m_database.getDatabase().getDataSource().getQueryDefinition("orders for customer and product").getCommand()); 247cdf0e10cSrcweir final XParametersSupplier suppParams = UnoRuntime.queryInterface(XParametersSupplier.class, m_composer); 248cdf0e10cSrcweir final XIndexAccess parameters = suppParams.getParameters(); 249cdf0e10cSrcweir 250cdf0e10cSrcweir final String expectedParamNames[] = 251cdf0e10cSrcweir 252cdf0e10cSrcweir { 253cdf0e10cSrcweir "cname", 254cdf0e10cSrcweir "Product Name" 255cdf0e10cSrcweir }; 256cdf0e10cSrcweir 257cdf0e10cSrcweir final int paramCount = parameters.getCount(); 258cdf0e10cSrcweir assertTrue("composer did find wrong number of parameters in the nested queries.", 259cdf0e10cSrcweir paramCount == expectedParamNames.length); 260cdf0e10cSrcweir 261cdf0e10cSrcweir for (int i = 0; i < paramCount; ++i) 262cdf0e10cSrcweir { 263cdf0e10cSrcweir final XPropertySet parameter = UnoRuntime.queryInterface(XPropertySet.class, parameters.getByIndex(i)); 264cdf0e10cSrcweir final String paramName = (String) parameter.getPropertyValue("Name"); 265cdf0e10cSrcweir assertTrue("wrong parameter name at position " + (i + 1) + " (expected: " + expectedParamNames[i] + ", found: " + paramName + ")", 266cdf0e10cSrcweir paramName.equals(expectedParamNames[i])); 267cdf0e10cSrcweir 268cdf0e10cSrcweir } 269cdf0e10cSrcweir } 270cdf0e10cSrcweir catch (Exception e) 271cdf0e10cSrcweir { 272cdf0e10cSrcweir fail("caught an exception: " + e); 273cdf0e10cSrcweir } 274cdf0e10cSrcweir } 275cdf0e10cSrcweir 276cdf0e10cSrcweir @Test testConditionByColumn()277cdf0e10cSrcweir public void testConditionByColumn() 278cdf0e10cSrcweir { 279cdf0e10cSrcweir try 280cdf0e10cSrcweir { 281cdf0e10cSrcweir m_composer.setQuery("SELECT * FROM \"customers\""); 282cdf0e10cSrcweir 283cdf0e10cSrcweir final Object initArgs[] = 284cdf0e10cSrcweir 285cdf0e10cSrcweir { 286cdf0e10cSrcweir new NamedValue("AutomaticAddition", Boolean.valueOf(true)) 287cdf0e10cSrcweir }; 288cdf0e10cSrcweir final String serviceName = "com.sun.star.beans.PropertyBag"; 289cdf0e10cSrcweir final XPropertyContainer filter = UnoRuntime.queryInterface(XPropertyContainer.class, getMSF().createInstanceWithArguments(serviceName, initArgs)); 290cdf0e10cSrcweir filter.addProperty("Name", PropertyAttribute.MAYBEVOID, "Comment"); 291cdf0e10cSrcweir filter.addProperty("RealName", PropertyAttribute.MAYBEVOID, "Comment"); 292cdf0e10cSrcweir filter.addProperty("TableName", PropertyAttribute.MAYBEVOID, "customers"); 293cdf0e10cSrcweir filter.addProperty("Value", PropertyAttribute.MAYBEVOID, "Good one."); 294cdf0e10cSrcweir filter.addProperty("Type", PropertyAttribute.MAYBEVOID, Integer.valueOf(DataType.LONGVARCHAR)); 295cdf0e10cSrcweir final XPropertySet column = UnoRuntime.queryInterface(XPropertySet.class, filter); 296cdf0e10cSrcweir 297cdf0e10cSrcweir m_composer.appendFilterByColumn(column, true, SQLFilterOperator.LIKE); 298cdf0e10cSrcweir assertTrue("At least one row should exist", m_database.getConnection().createStatement().executeQuery(m_composer.getQuery()).next()); 299cdf0e10cSrcweir 300cdf0e10cSrcweir } 301cdf0e10cSrcweir catch (Exception e) 302cdf0e10cSrcweir { 303cdf0e10cSrcweir // this is an error: the query is expected to be parseable 304cdf0e10cSrcweir fail("caught an exception: " + e); 305cdf0e10cSrcweir } 306cdf0e10cSrcweir } 307cdf0e10cSrcweir impl_testDisjunctiveNormalForm(String _query, PropertyValue[][] _expectedDNF)308cdf0e10cSrcweir private void impl_testDisjunctiveNormalForm(String _query, PropertyValue[][] _expectedDNF) 309cdf0e10cSrcweir { 310cdf0e10cSrcweir try 311cdf0e10cSrcweir { 312cdf0e10cSrcweir m_composer.setQuery(_query); 313cdf0e10cSrcweir } 314cdf0e10cSrcweir catch (Exception e) 315cdf0e10cSrcweir { 316cdf0e10cSrcweir // this is an error: the query is expected to be parseable 317cdf0e10cSrcweir fail("caught an exception: " + e); 318cdf0e10cSrcweir } 319cdf0e10cSrcweir 320cdf0e10cSrcweir final PropertyValue[][] disjunctiveNormalForm = m_composer.getStructuredFilter(); 321cdf0e10cSrcweir 322cdf0e10cSrcweir assertEquals("DNF: wrong number of rows", _expectedDNF.length, disjunctiveNormalForm.length); 323cdf0e10cSrcweir for (int i = 0; i < _expectedDNF.length; ++i) 324cdf0e10cSrcweir { 325cdf0e10cSrcweir assertEquals("DNF: wrong number of columns in row " + i, _expectedDNF[i].length, disjunctiveNormalForm[i].length); 326cdf0e10cSrcweir for (int j = 0; j < _expectedDNF[i].length; ++j) 327cdf0e10cSrcweir { 328cdf0e10cSrcweir assertEquals("DNF: wrong content in column " + j + ", row " + i, 329cdf0e10cSrcweir _expectedDNF[i][j].Name, disjunctiveNormalForm[i][j].Name); 330cdf0e10cSrcweir } 331cdf0e10cSrcweir } 332cdf0e10cSrcweir } 333cdf0e10cSrcweir 334cdf0e10cSrcweir /** tests the disjunctive normal form functionality, aka the structured filter, 335cdf0e10cSrcweir * of the composer 336cdf0e10cSrcweir */ 337cdf0e10cSrcweir @Test testDisjunctiveNormalForm()338cdf0e10cSrcweir public void testDisjunctiveNormalForm() 339cdf0e10cSrcweir { 340cdf0e10cSrcweir // a simple case: WHERE clause simply is a combination of predicates knitted with AND 341cdf0e10cSrcweir String query = 342cdf0e10cSrcweir "SELECT \"customers\".\"Name\", " 343cdf0e10cSrcweir + "\"customers\".\"Address\", " 344cdf0e10cSrcweir + "\"customers\".\"City\", " 345cdf0e10cSrcweir + "\"customers\".\"Postal\", " 346cdf0e10cSrcweir + "\"products\".\"Name\" " 347cdf0e10cSrcweir + "FROM \"orders\", \"customers\", \"orders_details\", \"products\" " 348cdf0e10cSrcweir + "WHERE ( \"orders\".\"CustomerID\" = \"customers\".\"ID\" " 349cdf0e10cSrcweir + "AND \"orders_details\".\"OrderID\" = \"orders\".\"ID\" " 350cdf0e10cSrcweir + "AND \"orders_details\".\"ProductID\" = \"products\".\"ID\" " 351cdf0e10cSrcweir + ") "; 352cdf0e10cSrcweir 353cdf0e10cSrcweir impl_testDisjunctiveNormalForm(query, new PropertyValue[][] 354cdf0e10cSrcweir { 355cdf0e10cSrcweir new PropertyValue[] 356cdf0e10cSrcweir { 357cdf0e10cSrcweir new PropertyValue("CustomerID", SQLFilterOperator.EQUAL, "\"customers\".\"ID\"", PropertyState.DIRECT_VALUE), 358cdf0e10cSrcweir new PropertyValue("OrderID", SQLFilterOperator.EQUAL, "\"orders\".\"ID\"", PropertyState.DIRECT_VALUE), 359cdf0e10cSrcweir new PropertyValue("ProductID", SQLFilterOperator.EQUAL, "\"products\".\"ID\"", PropertyState.DIRECT_VALUE) 360cdf0e10cSrcweir } 361cdf0e10cSrcweir }); 362cdf0e10cSrcweir 363cdf0e10cSrcweir // somewhat more challenging: One of the conjunction terms is a disjunction itself 364cdf0e10cSrcweir query = 365cdf0e10cSrcweir "SELECT \"customers\".\"Name\", " 366cdf0e10cSrcweir + "\"customers\".\"Address\", " 367cdf0e10cSrcweir + "\"customers\".\"City\", " 368cdf0e10cSrcweir + "\"customers\".\"Postal\", " 369cdf0e10cSrcweir + "\"products\".\"Name\" " 370cdf0e10cSrcweir + "FROM \"orders\", \"customers\", \"orders_details\", \"products\" " 371cdf0e10cSrcweir + "WHERE ( \"orders\".\"CustomerID\" = \"customers\".\"ID\" " 372cdf0e10cSrcweir + "AND \"orders_details\".\"OrderID\" = \"orders\".\"ID\" " 373cdf0e10cSrcweir + "AND \"orders_details\".\"ProductID\" = \"products\".\"ID\" " 374cdf0e10cSrcweir + ") " 375cdf0e10cSrcweir + "AND " 376cdf0e10cSrcweir + "( \"products\".\"Name\" = 'Apples' " 377cdf0e10cSrcweir + "OR \"products\".\"ID\" = 2 " 378cdf0e10cSrcweir + ")"; 379cdf0e10cSrcweir 380cdf0e10cSrcweir impl_testDisjunctiveNormalForm(query, new PropertyValue[][] 381cdf0e10cSrcweir { 382cdf0e10cSrcweir new PropertyValue[] 383cdf0e10cSrcweir { 384cdf0e10cSrcweir new PropertyValue("CustomerID", SQLFilterOperator.EQUAL, "\"customers\".\"ID\"", PropertyState.DIRECT_VALUE), 385cdf0e10cSrcweir new PropertyValue("OrderID", SQLFilterOperator.EQUAL, "\"orders\".\"ID\"", PropertyState.DIRECT_VALUE), 386cdf0e10cSrcweir new PropertyValue("ProductID", SQLFilterOperator.EQUAL, "\"products\".\"ID\"", PropertyState.DIRECT_VALUE), 387cdf0e10cSrcweir new PropertyValue("Name", SQLFilterOperator.EQUAL, "Apples", PropertyState.DIRECT_VALUE) 388cdf0e10cSrcweir }, 389cdf0e10cSrcweir new PropertyValue[] 390cdf0e10cSrcweir { 391cdf0e10cSrcweir new PropertyValue("CustomerID", SQLFilterOperator.EQUAL, "\"customers\".\"ID\"", PropertyState.DIRECT_VALUE), 392cdf0e10cSrcweir new PropertyValue("OrderID", SQLFilterOperator.EQUAL, "\"orders\".\"ID\"", PropertyState.DIRECT_VALUE), 393cdf0e10cSrcweir new PropertyValue("ProductID", SQLFilterOperator.EQUAL, "\"products\".\"ID\"", PropertyState.DIRECT_VALUE), 394cdf0e10cSrcweir new PropertyValue("ID", SQLFilterOperator.EQUAL, Integer.valueOf(2), PropertyState.DIRECT_VALUE) 395cdf0e10cSrcweir } 396cdf0e10cSrcweir }); 397cdf0e10cSrcweir 398cdf0e10cSrcweir } 399cdf0e10cSrcweir } 400