Author: mattmann
Date: Mon Nov 28 04:41:43 2011
New Revision: 1206971

URL: http://svn.apache.org/viewvc?rev=1206971&view=rev
Log:
- fix for OODT-336 xmlps should omit joining of tables that are unnecessary to 
fulfill query (contributed by Ricky Nguyen)

Added:
    oodt/trunk/xmlps/src/test/resources/test-required-tables-ps.xml
Modified:
    oodt/trunk/CHANGES.txt
    
oodt/trunk/xmlps/src/main/java/org/apache/oodt/xmlps/product/XMLPSProductHandler.java
    
oodt/trunk/xmlps/src/test/java/org/apache/oodt/xmlps/product/TestXMLPSProductHandler.java

Modified: oodt/trunk/CHANGES.txt
URL: 
http://svn.apache.org/viewvc/oodt/trunk/CHANGES.txt?rev=1206971&r1=1206970&r2=1206971&view=diff
==============================================================================
--- oodt/trunk/CHANGES.txt (original)
+++ oodt/trunk/CHANGES.txt Mon Nov 28 04:41:43 2011
@@ -4,6 +4,9 @@ Apache OODT Change Log
 Release 0.4: Current Development
 --------------------------------------------
 
+* OODT-336 xmlps should omit joining of tables that are unnecessary to 
+  fulfill query (Ricky Nguyen via mattmann)
+
 * OODT-339 MappingReader should add default join table to DatabaseTable 
   if none defined (Ricky Nguyen via mattmann)
 

Modified: 
oodt/trunk/xmlps/src/main/java/org/apache/oodt/xmlps/product/XMLPSProductHandler.java
URL: 
http://svn.apache.org/viewvc/oodt/trunk/xmlps/src/main/java/org/apache/oodt/xmlps/product/XMLPSProductHandler.java?rev=1206971&r1=1206970&r2=1206971&view=diff
==============================================================================
--- 
oodt/trunk/xmlps/src/main/java/org/apache/oodt/xmlps/product/XMLPSProductHandler.java
 (original)
+++ 
oodt/trunk/xmlps/src/main/java/org/apache/oodt/xmlps/product/XMLPSProductHandler.java
 Mon Nov 28 04:41:43 2011
@@ -41,8 +41,10 @@ import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.sql.SQLException;
 import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Set;
 import java.util.Stack;
 import java.util.Vector;
 import java.util.logging.Level;
@@ -189,10 +191,10 @@ public class XMLPSProductHandler impleme
                 .createQueryStack(query.getWhereElementSet());
         Expression parsedQuery = HandlerQueryParser.parse(queryStack,
                 this.mapping);
-        List<QueryElement> names = getElemNamesFromQueryElemSet(query
+        List<QueryElement> selectNames = getElemNamesFromQueryElemSet(query
                 .getSelectElementSet());
 
-        String querySelectNames = toSQLSelectColumns(names);
+        String querySelectNames = toSQLSelectColumns(selectNames);
 
         StringBuffer sqlBuf = new StringBuffer("SELECT ");
         sqlBuf.append(querySelectNames);
@@ -201,10 +203,9 @@ public class XMLPSProductHandler impleme
         sqlBuf.append(" ");
 
         if (mapping.getNumTables() > 0) {
-            for (Iterator<String> i = mapping.getTableNames().iterator(); i
-                    .hasNext();) {
-                String tableName = i.next();
-                DatabaseTable tbl = mapping.getTableByName(tableName);
+            List<QueryElement> whereNames = 
getElemNamesFromQueryElemSet(query.getWhereElementSet());
+            Set<DatabaseTable> requiredTables = getRequiredTables(whereNames, 
selectNames);
+            for (DatabaseTable tbl : requiredTables) {
                 sqlBuf.append("INNER JOIN ");
                 sqlBuf.append(tbl.getName());
                 sqlBuf.append(" ON ");
@@ -229,7 +230,7 @@ public class XMLPSProductHandler impleme
         if (executor != null) {
             try {
                 CDEResult res = executor.executeLocalQuery(this.mapping,
-                        sqlBuf.toString(), toSQLResultSetColumns(names));
+                        sqlBuf.toString(), toSQLResultSetColumns(selectNames));
 
                 res = addConstFields(res,
                         getConstElemNamesFromQueryElemSet(query
@@ -382,5 +383,49 @@ public class XMLPSProductHandler impleme
         }
 
     }
+  
+    protected Set<DatabaseTable> getRequiredTables(
+            List<QueryElement> whereElemNames, List<QueryElement> 
selectElemNames) {
+        Set<DatabaseTable> tables = new HashSet<DatabaseTable>();
+        // add tables from where element set
+        if (whereElemNames != null) {
+            for (QueryElement qe : whereElemNames) {
+                MappingField fld = mapping.getFieldByLocalName(qe.getValue());
+                if (fld != null) {
+                    DatabaseTable t = 
mapping.getTableByName(fld.getTableName());
+                    if (t != null && !tables.contains(t)) {
+                        tables.add(t);
+                    }
+                }
+            }
+        }
+        // add tables from select element set
+        if (selectElemNames != null) {
+            for (QueryElement qe : selectElemNames) {
+                MappingField fld = mapping.getFieldByLocalName(qe.getValue());
+                if (fld != null) {
+                    DatabaseTable t = 
mapping.getTableByName(fld.getTableName());
+                    if (t != null && !tables.contains(t)) {
+                        tables.add(t);
+                    }
+                }
+            }
+        }
+        // the tables found may be joined on columns from tables we haven't 
found
+        // yet
+        // add additional required join tables
+        Set<DatabaseTable> moreTables = new HashSet<DatabaseTable>(tables);
+        for (DatabaseTable t : tables) {
+            DatabaseTable join = 
mapping.getTableByName(t.getDefaultTableJoin());
+            // recursively add all join tables until we get to either
+            // (a) the mapping default table (join == null)
+            // (b) or a table already found (moreTables.contains(join))
+            while (join != null && !moreTables.contains(join)) {
+                moreTables.add(join);
+                join = mapping.getTableByName(join.getDefaultTableJoin());
+            }
+        }
+        return moreTables;
+    }
 
 }

Modified: 
oodt/trunk/xmlps/src/test/java/org/apache/oodt/xmlps/product/TestXMLPSProductHandler.java
URL: 
http://svn.apache.org/viewvc/oodt/trunk/xmlps/src/test/java/org/apache/oodt/xmlps/product/TestXMLPSProductHandler.java?rev=1206971&r1=1206970&r2=1206971&view=diff
==============================================================================
--- 
oodt/trunk/xmlps/src/test/java/org/apache/oodt/xmlps/product/TestXMLPSProductHandler.java
 (original)
+++ 
oodt/trunk/xmlps/src/test/java/org/apache/oodt/xmlps/product/TestXMLPSProductHandler.java
 Mon Nov 28 04:41:43 2011
@@ -20,8 +20,10 @@ package org.apache.oodt.xmlps.product;
 //JDK imports
 import java.util.Iterator;
 import java.util.List;
+import java.util.Set;
 
 //APACHE imports
+import org.apache.oodt.xmlps.mapping.DatabaseTable;
 import org.apache.oodt.xmlps.util.XMLQueryHelper;
 import org.apache.oodt.xmlquery.QueryElement;
 import org.apache.oodt.xmlquery.XMLQuery;
@@ -140,4 +142,43 @@ public class TestXMLPSProductHandler ext
                 expectedSpecimenFldName);
 
     }
+    
+    public void testGetRequiredTables() {
+        System.setProperty("org.apache.oodt.xmlps.xml.mapFilePath",
+            "./src/test/resources/test-required-tables-ps.xml");
+        
+        try {
+            handler = new XMLPSProductHandler();
+        } catch (InstantiationException e) {
+            fail(e.getMessage());
+        }
+        
+        String queryStr = "RETURN = id AND RETURN = id_1 AND RETURN = id_2 AND 
RETURN = id_3 AND RETURN = id_4";
+        XMLQuery query = 
XMLQueryHelper.getDefaultQueryFromQueryString(queryStr);
+        
+        List<QueryElement> where = query.getWhereElementSet();
+        List<QueryElement> select = query.getSelectElementSet();
+        
+        try {
+            handler.translateToDomain(where, false);
+            handler.translateToDomain(select, true);
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+        
+        List<QueryElement> whereNames = 
handler.getElemNamesFromQueryElemSet(where);
+        List<QueryElement> selectNames = 
handler.getElemNamesFromQueryElemSet(select);
+        
+        Set<DatabaseTable> tables = handler.getRequiredTables(whereNames, 
selectNames);
+        
+        assertEquals(7, tables.size());
+        
assertTrue(tables.contains(handler.mapping.getTableByName("joinToDefault")));
+        
assertTrue(tables.contains(handler.mapping.getTableByName("joinToExtraDefault")));
+        
assertTrue(tables.contains(handler.mapping.getTableByName("joinToExtraJoin")));
+        
assertTrue(tables.contains(handler.mapping.getTableByName("joinToExtraOther")));
+        
assertTrue(tables.contains(handler.mapping.getTableByName("extraDefault")));
+        
assertTrue(tables.contains(handler.mapping.getTableByName("extraOther")));
+        assertTrue(tables.contains(handler.mapping.getTableByName("other")));
+        
assertTrue(!tables.contains(handler.mapping.getTableByName("another")));
+    }
 }

Added: oodt/trunk/xmlps/src/test/resources/test-required-tables-ps.xml
URL: 
http://svn.apache.org/viewvc/oodt/trunk/xmlps/src/test/resources/test-required-tables-ps.xml?rev=1206971&view=auto
==============================================================================
--- oodt/trunk/xmlps/src/test/resources/test-required-tables-ps.xml (added)
+++ oodt/trunk/xmlps/src/test/resources/test-required-tables-ps.xml Mon Nov 28 
04:41:43 2011
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<!-- Example XML mapping configuration file -->
+<oodt:xmlps xmlns:oodt="http://incubator.apache.org/oodt/0.1-incubating";
+  name="Example Query Handler" id="project:subproject:exampleps">
+  <tables default="defaultTable">
+    <table name="joinToDefault" join="id" tofld="id" />
+    <table name="joinToExtraDefault" join="id" to="extraDefault" tofld="id" />
+    <table name="joinToExtraJoin" join="id" to="joinToExtraDefault" 
tofld="id"/>
+    <table name="joinToExtraOther" join="id" to="extraOther" tofld="id"/>
+    <table name="extraDefault" join="id" tofld="id"/>
+    <table name="extraOther" join="id" to="other" tofld="id"/>
+    <table name="other" join="id" tofld="id" />
+    <table name="another" join="id" tofld="id" />
+  </tables>
+  <!-- 
+    field:
+    
+    type (required):   dynamic or constant. If you choose dynamic, then the 
field
+    value is read from the row in the ResultSet returned
+    from the database. If constant, then each returned row
+    from the ResultSet is annotated with the value specified
+    in the 'value' attribute.
+    
+    name (required):   the name of the attribute that you want returned
+    in the product server.
+    
+    string (optional): whether or not the internal db representation at the 
local
+    site for this field is a STRING, or something else (e.g., a number, etc.). 
Possible 
+    values for this attribute are "true", to indicate that the field is a 
string, or
+    "false", to indicate that it is something else. If this attribute is 
omitted, a value
+    of "false" is assumed, and the attribute will not be quoted in the where 
clause of
+    the underlying SQL statement generated.
+    
+    dbname (optional): the name of the field within the underlying db. If not
+    specified, then assumed to be name
+    
+    table (optional):  if provided, then the attribute a is selected as
+    'table'.'a',and then returned. If omitted, the attribute
+    is assumed to come from the default table returned from the
+    PS query.
+    
+    value (optional):  is necessary to provide if type='constant' is selected.
+    
+    scope (optional):  limits the scope of a field's existence: acceptable 
values
+    are &quot;query&quot;, which signifies that the field is only applicable 
when
+    translating queries: and &quot;return&quot;, which signifies the field is 
only
+    applicable as a return field when converting database results into 
CDEResults.
+    
+  -->
+  <field type="dynamic" name="id" dbname="id" table="defaultTable"/>
+  <field type="dynamic" name="id_1" dbname="id" table="joinToDefault"/>
+  <field type="dynamic" name="id_2" dbname="id" table="joinToExtraDefault"/>
+  <field type="dynamic" name="id_3" dbname="id" table="joinToExtraJoin"/>
+  <field type="dynamic" name="id_4" dbname="id" table="joinToExtraOther"/>
+</oodt:xmlps>


Reply via email to