Author: shawkins
Date: 2010-06-06 11:12:19 -0400 (Sun, 06 Jun 2010)
New Revision: 2185
Added:
trunk/engine/src/test/java/org/teiid/query/xquery/saxon/
trunk/engine/src/test/java/org/teiid/query/xquery/saxon/TestSaxonXQueryExpression.java
Modified:
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/PlanToProcessConverter.java
trunk/engine/src/main/java/org/teiid/query/processor/relational/RelationalNode.java
trunk/engine/src/main/java/org/teiid/query/processor/relational/SubqueryAwareRelationalNode.java
trunk/engine/src/main/java/org/teiid/query/processor/relational/TextTableNode.java
trunk/engine/src/main/java/org/teiid/query/processor/relational/XMLTableNode.java
trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java
trunk/engine/src/main/java/org/teiid/query/sql/lang/XMLTable.java
trunk/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java
trunk/engine/src/main/java/org/teiid/query/xquery/saxon/SaxonXQueryExpression.java
trunk/engine/src/main/resources/org/teiid/query/i18n.properties
trunk/engine/src/test/java/org/teiid/query/processor/TestSQLXMLProcessing.java
Log:
TEIID-1087 TEIID-171 refining xquery analysis based upon saxon path maps. memory usage
will be nearly as good as xom/nux, but there are far fewer restrictions on the row path
expression.
Modified:
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/PlanToProcessConverter.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/PlanToProcessConverter.java 2010-06-05
01:49:35 UTC (rev 2184)
+++
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/PlanToProcessConverter.java 2010-06-06
15:12:19 UTC (rev 2185)
@@ -22,9 +22,11 @@
package org.teiid.query.optimizer.relational;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
import org.teiid.api.exception.query.QueryMetadataException;
import org.teiid.api.exception.query.QueryPlannerException;
@@ -69,6 +71,7 @@
import org.teiid.query.processor.relational.SortNode;
import org.teiid.query.processor.relational.TextTableNode;
import org.teiid.query.processor.relational.UnionAllNode;
+import org.teiid.query.processor.relational.XMLTableNode;
import org.teiid.query.processor.relational.JoinNode.JoinStrategyType;
import org.teiid.query.processor.relational.MergeJoinStrategy.SortOption;
import org.teiid.query.processor.relational.SortUtility.Mode;
@@ -83,6 +86,7 @@
import org.teiid.query.sql.lang.TextTable;
import org.teiid.query.sql.lang.XMLTable;
import org.teiid.query.sql.lang.SetQuery.Operation;
+import org.teiid.query.sql.lang.XMLTable.XMLColumn;
import org.teiid.query.sql.symbol.ElementSymbol;
import org.teiid.query.sql.symbol.Expression;
import org.teiid.query.sql.symbol.GroupSymbol;
@@ -369,15 +373,30 @@
}
Object source = node.getProperty(NodeConstants.Info.TABLE_FUNCTION);
if (source instanceof XMLTable) {
- return null;
+ XMLTable xt = (XMLTable)source;
+ XMLTableNode xtn = new XMLTableNode(getID());
+ //we handle the projection filtering once here rather than repeating the
+ //path analysis on a per plan basis
+ Map elementMap = RelationalNode.createLookupMap(xt.getProjectedSymbols());
+ List cols = (List) node.getProperty(NodeConstants.Info.OUTPUT_COLS);
+ int[] projectionIndexes = RelationalNode.getProjectionIndexes(elementMap, cols);
+ ArrayList<XMLColumn> filteredColumns = new
ArrayList<XMLColumn>(projectionIndexes.length);
+ for (int col : projectionIndexes) {
+ filteredColumns.add(xt.getColumns().get(col));
+ }
+ xt.getXQueryExpression().useDocumentProjection(filteredColumns, analysisRecord);
+ xtn.setProjectedColumns(filteredColumns);
+ xtn.setTable(xt);
+ processNode = xtn;
+ break;
}
- if (!(source instanceof TextTable)) {
- return null;
+ if (source instanceof TextTable) {
+ TextTableNode ttn = new TextTableNode(getID());
+ ttn.setTable((TextTable)source);
+ processNode = ttn;
+ break;
}
- TextTableNode ttn = new TextTableNode(getID());
- ttn.setTable((TextTable)source);
- processNode = ttn;
- break;
+ return null;
case NodeConstants.Types.SET_OP:
Operation setOp = (Operation)
node.getProperty(NodeConstants.Info.SET_OPERATION);
boolean useAll = ((Boolean)
node.getProperty(NodeConstants.Info.USE_ALL)).booleanValue();
Modified:
trunk/engine/src/main/java/org/teiid/query/processor/relational/RelationalNode.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/processor/relational/RelationalNode.java 2010-06-05
01:49:35 UTC (rev 2184)
+++
trunk/engine/src/main/java/org/teiid/query/processor/relational/RelationalNode.java 2010-06-06
15:12:19 UTC (rev 2185)
@@ -338,7 +338,7 @@
/**
* Helper method for all the node that will filter the elements needed for the next
node.
*/
- protected int[] getProjectionIndexes(Map<SingleElementSymbol, Integer>
tupleElements, List<SingleElementSymbol> projectElements) {
+ public static int[] getProjectionIndexes(Map<SingleElementSymbol, Integer>
tupleElements, List<SingleElementSymbol> projectElements) {
int[] result = new int[projectElements.size()];
int i = 0;
Modified:
trunk/engine/src/main/java/org/teiid/query/processor/relational/SubqueryAwareRelationalNode.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/processor/relational/SubqueryAwareRelationalNode.java 2010-06-05
01:49:35 UTC (rev 2184)
+++
trunk/engine/src/main/java/org/teiid/query/processor/relational/SubqueryAwareRelationalNode.java 2010-06-06
15:12:19 UTC (rev 2185)
@@ -22,9 +22,16 @@
package org.teiid.query.processor.relational;
+import java.util.Collections;
import java.util.Map;
+import org.teiid.api.exception.query.ExpressionEvaluationException;
+import org.teiid.common.buffer.BlockedException;
+import org.teiid.core.TeiidComponentException;
import org.teiid.query.eval.Evaluator;
+import org.teiid.query.sql.lang.TableFunctionReference;
+import org.teiid.query.sql.symbol.ElementSymbol;
+import org.teiid.query.sql.symbol.Expression;
public abstract class SubqueryAwareRelationalNode extends RelationalNode {
@@ -57,5 +64,14 @@
evaluator.close();
}
}
+
+ protected void setReferenceValues(TableFunctionReference ref) throws
ExpressionEvaluationException, BlockedException, TeiidComponentException {
+ if (ref.getCorrelatedReferences() == null) {
+ return;
+ }
+ for (Map.Entry<ElementSymbol, Expression> entry :
ref.getCorrelatedReferences().asMap().entrySet()) {
+ getContext().getVariableContext().setValue(entry.getKey(),
getEvaluator(Collections.emptyMap()).evaluate(entry.getValue(), null));
+ }
+ }
}
Modified:
trunk/engine/src/main/java/org/teiid/query/processor/relational/TextTableNode.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/processor/relational/TextTableNode.java 2010-06-05
01:49:35 UTC (rev 2184)
+++
trunk/engine/src/main/java/org/teiid/query/processor/relational/TextTableNode.java 2010-06-06
15:12:19 UTC (rev 2185)
@@ -43,6 +43,7 @@
import org.teiid.core.types.TransformationException;
import org.teiid.query.execution.QueryExecPlugin;
import org.teiid.query.processor.ProcessorDataManager;
+import org.teiid.query.sql.lang.TableFunctionReference;
import org.teiid.query.sql.lang.TextTable;
import org.teiid.query.sql.lang.TextTable.TextColumn;
import org.teiid.query.sql.symbol.ElementSymbol;
@@ -69,7 +70,6 @@
private char quote;
private char delimiter;
private int lineWidth;
- private Map elementMap;
private int[] projectionIndexes;
//per file state
@@ -85,7 +85,7 @@
public void initialize(CommandContext context, BufferManager bufferManager,
ProcessorDataManager dataMgr) {
super.initialize(context, bufferManager, dataMgr);
- if (elementMap != null) {
+ if (projectionIndexes != null) {
return;
}
if (table.getSkip() != null) {
@@ -112,7 +112,7 @@
quote = table.getQuote();
}
}
- this.elementMap = createLookupMap(table.getProjectedSymbols());
+ Map elementMap = createLookupMap(table.getProjectedSymbols());
this.projectionIndexes = getProjectionIndexes(elementMap, getElements());
}
@@ -215,11 +215,7 @@
private void initReader() throws ExpressionEvaluationException,
BlockedException, TeiidComponentException, TeiidProcessingException {
- if (table.getCorrelatedReferences() != null) {
- for (Map.Entry<ElementSymbol, Expression> entry :
table.getCorrelatedReferences().asMap().entrySet()) {
- getContext().getVariableContext().setValue(entry.getKey(),
getEvaluator(Collections.emptyMap()).evaluate(entry.getValue(), null));
- }
- }
+ setReferenceValues(this.table);
ClobType file =
(ClobType)getEvaluator(Collections.emptyMap()).evaluate(table.getFile(), null);
if (file == null) {
Modified:
trunk/engine/src/main/java/org/teiid/query/processor/relational/XMLTableNode.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/processor/relational/XMLTableNode.java 2010-06-05
01:49:35 UTC (rev 2184)
+++
trunk/engine/src/main/java/org/teiid/query/processor/relational/XMLTableNode.java 2010-06-06
15:12:19 UTC (rev 2185)
@@ -22,82 +22,198 @@
package org.teiid.query.processor.relational;
-import java.util.Map;
+import java.io.IOException;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Properties;
-import net.sf.saxon.query.XQueryExpression;
-import nu.xom.Element;
-import nu.xom.Node;
-import nu.xom.NodeFactory;
-import nu.xom.Nodes;
-import nux.xom.pool.XQueryPool;
-import nux.xom.xquery.StreamingPathFilter;
-import nux.xom.xquery.StreamingTransform;
-import nux.xom.xquery.XQueryUtil;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.TransformerException;
+import net.sf.saxon.Configuration;
+import net.sf.saxon.om.Item;
+import net.sf.saxon.om.NodeInfo;
+import net.sf.saxon.om.SequenceIterator;
+import net.sf.saxon.query.QueryResult;
+import net.sf.saxon.sxpath.XPathDynamicContext;
+import net.sf.saxon.sxpath.XPathExpression;
+import net.sf.saxon.trans.XPathException;
+import net.sf.saxon.value.Value;
+
+import org.teiid.api.exception.query.ExpressionEvaluationException;
import org.teiid.common.buffer.BlockedException;
-import org.teiid.common.buffer.BufferManager;
import org.teiid.common.buffer.TupleBatch;
import org.teiid.core.TeiidComponentException;
import org.teiid.core.TeiidProcessingException;
-import org.teiid.query.processor.ProcessorDataManager;
+import org.teiid.core.types.DataTypeManager;
+import org.teiid.core.types.SQLXMLImpl;
+import org.teiid.core.types.Streamable;
+import org.teiid.core.types.TransformationException;
+import org.teiid.core.types.XMLTranslator;
+import org.teiid.core.types.XMLType;
+import org.teiid.core.types.XMLType.Type;
+import org.teiid.query.processor.xml.XMLUtil;
import org.teiid.query.sql.lang.XMLTable;
-import org.teiid.query.util.CommandContext;
+import org.teiid.query.sql.lang.XMLTable.XMLColumn;
+import org.teiid.query.sql.symbol.DerivedColumn;
/**
- * Handles xml processing.
+ * Handles xml table processing.
*/
public class XMLTableNode extends SubqueryAwareRelationalNode {
+ private static final class QueryResultTranslator extends XMLTranslator {
+ private final SequenceIterator pathIter;
+ private final Configuration config;
+
+ private QueryResultTranslator(SequenceIterator pathIter, Configuration config) {
+ this.pathIter = pathIter;
+ this.config = config;
+ }
+
+ @Override
+ public void translate(Writer writer) throws TransformerException,
+ IOException {
+ Properties props = new Properties();
+ props.setProperty(OutputKeys.METHOD, "xml"); //$NON-NLS-1$
+ //props.setProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
+ props.setProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); //$NON-NLS-1$
+ QueryResult.serializeSequence(pathIter, config, writer, props);
+ }
+ }
+
private XMLTable table;
+ private List<XMLColumn> projectedColumns;
- //initialized state
- private Map elementMap;
- private int[] projectionIndexes;
+ private SequenceIterator result;
+ private int rowCount = 0;
- //per file state
-
public XMLTableNode(int nodeID) {
super(nodeID);
}
@Override
- public void initialize(CommandContext context, BufferManager bufferManager,
- ProcessorDataManager dataMgr) {
- super.initialize(context, bufferManager, dataMgr);
- if (elementMap != null) {
- return;
- }
- this.elementMap = createLookupMap(table.getProjectedSymbols());
- this.projectionIndexes = getProjectionIndexes(elementMap, getElements());
- }
-
- @Override
public void closeDirect() {
super.closeDirect();
reset();
}
+ @Override
+ public void reset() {
+ super.reset();
+ if (this.result != null) {
+ result.close();
+ result = null;
+ }
+ rowCount = 0;
+ }
+
public void setTable(XMLTable table) {
this.table = table;
}
-
+
+ public void setProjectedColumns(List<XMLColumn> projectedColumns) {
+ this.projectedColumns = projectedColumns;
+ }
+
@Override
public XMLTableNode clone() {
XMLTableNode clone = new XMLTableNode(getID());
this.copy(this, clone);
clone.setTable(table);
+ clone.setProjectedColumns(projectedColumns);
return clone;
}
@Override
protected TupleBatch nextBatchDirect() throws BlockedException,
TeiidComponentException, TeiidProcessingException {
- return null;
+
+ if (result == null) {
+ setReferenceValues(this.table);
+ HashMap<String, Object> parameters = new HashMap<String, Object>();
+ Object contextItem = null;
+ for (DerivedColumn passing : this.table.getPassing()) {
+ Object value = getEvaluator(Collections.emptyMap()).evaluate(passing.getExpression(),
null);
+ if (passing.getAlias() == null) {
+ contextItem = value;
+ } else {
+ parameters.put(passing.getAlias(), value);
+ }
+ }
+ result = this.table.getXQueryExpression().evaluateXQuery(contextItem, parameters);
+ }
+
+ while (!isBatchFull() && !isLastBatch()) {
+ try {
+ processRow();
+ } catch (XPathException e) {
+ e.printStackTrace();
+ }
+ }
+ return pullBatch();
}
-
- public static void main(String[] args) {
-
+ private void processRow() throws XPathException,
+ ExpressionEvaluationException, BlockedException,
+ TeiidComponentException, TeiidProcessingException,
+ TransformationException {
+ Item item = result.next();
+ rowCount++;
+ if (item == null) {
+ terminateBatches();
+ return;
+ }
+ List<Object> tuple = new ArrayList<Object>(projectedColumns.size());
+ for (XMLColumn proColumn : projectedColumns) {
+ if (proColumn.isOrdinal()) {
+ tuple.add(rowCount);
+ } else {
+ XPathExpression path = proColumn.getPathExpression();
+ XPathDynamicContext dynamicContext = path.createDynamicContext(item);
+ SequenceIterator pathIter = path.iterate(dynamicContext);
+ Item colItem = pathIter.next();
+ if (colItem == null) {
+ if (proColumn.getDefaultExpression() != null) {
+ tuple.add(getEvaluator(Collections.emptyMap()).evaluate(proColumn.getDefaultExpression(),
null));
+ } else {
+ tuple.add(null);
+ }
+ continue;
+ }
+ if (proColumn.getSymbol().getType() == DataTypeManager.DefaultDataClasses.XML) {
+ Item next = pathIter.next();
+ XMLType.Type type = Type.FRAGMENT;
+ if (next != null) {
+ if (next instanceof NodeInfo || colItem instanceof NodeInfo) {
+ type = Type.SIBLINGS;
+ } else {
+ type = Type.TEXT;
+ }
+ }
+ pathIter = pathIter.getAnother();
+ SQLXMLImpl xml = XMLUtil.saveToBufferManager(getBufferManager(), new
QueryResultTranslator(pathIter, this.table.getXQueryExpression().getConfig()),
Streamable.STREAMING_BATCH_SIZE_IN_BYTES);
+ XMLType value = new XMLType(xml);
+ value.setType(type);
+ tuple.add(value);
+ continue;
+ }
+ if (pathIter.next() != null) {
+ throw new TeiidProcessingException("Unexpected multi-valued result was returned
for XML Column " + proColumn.getName() + ". All path expressions should return
at most a single result.");
+ }
+ Object value = Value.convertToJava(colItem);
+ if (value instanceof Item) {
+ value = ((Item)value).getStringValue();
+ }
+ value = DataTypeManager.convertToRuntimeType(value);
+ value = DataTypeManager.transformValue(value, proColumn.getSymbol().getType());
+ tuple.add(value);
+ }
+ }
+ addBatchRow(tuple);
}
-
+
}
\ No newline at end of file
Modified: trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java 2010-06-05
01:49:35 UTC (rev 2184)
+++ trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java 2010-06-06
15:12:19 UTC (rev 2185)
@@ -47,8 +47,8 @@
import org.teiid.api.exception.query.QueryResolverException;
import org.teiid.api.exception.query.QueryValidatorException;
import org.teiid.core.TeiidComponentException;
+import org.teiid.core.TeiidException;
import org.teiid.core.TeiidProcessingException;
-import org.teiid.core.TeiidException;
import org.teiid.core.TeiidRuntimeException;
import org.teiid.core.types.DataTypeManager;
import org.teiid.core.util.Assertion;
@@ -926,6 +926,8 @@
TextTable tt = (TextTable)clause;
tt.setFile(rewriteExpressionDirect(tt.getFile()));
} else if (clause instanceof XMLTable) {
+ XMLTable xt = (XMLTable)clause;
+ xt.rewriteDefaultColumn();
rewriteExpressions(clause);
}
return clause;
Modified: trunk/engine/src/main/java/org/teiid/query/sql/lang/XMLTable.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/lang/XMLTable.java 2010-06-05 01:49:35
UTC (rev 2184)
+++ trunk/engine/src/main/java/org/teiid/query/sql/lang/XMLTable.java 2010-06-06 15:12:19
UTC (rev 2185)
@@ -105,7 +105,7 @@
private XMLNamespaces namespaces;
private String xquery;
private List<DerivedColumn> passing = new ArrayList<DerivedColumn>();
- private ElementSymbol defaultColumn;
+ private XMLColumn defaultColumn;
private SaxonXQueryExpression xqueryExpression;
@@ -114,10 +114,14 @@
}
public void compileXqueryExpression() throws TeiidProcessingException {
- this.xqueryExpression = new SaxonXQueryExpression(xquery, namespaces, passing,
columns);
+ List<XMLColumn> cols = this.columns;
+ if (cols.isEmpty()) {
+ cols = Arrays.asList(defaultColumn);
+ }
+ this.xqueryExpression = new SaxonXQueryExpression(xquery, namespaces, passing,
cols);
}
- public SaxonXQueryExpression getXqueryExpression() {
+ public SaxonXQueryExpression getXQueryExpression() {
return xqueryExpression;
}
@@ -155,10 +159,9 @@
return super.getProjectedSymbols();
}
if (defaultColumn == null) {
- defaultColumn = new ElementSymbol("COLUMN_VALUE"); //$NON-NLS-1$
- defaultColumn.setType(DataTypeManager.DefaultDataClasses.XML);
+ defaultColumn = new XMLColumn("OBJECT_VALUE",
DataTypeManager.DefaultDataTypes.XML, ".", null); //$NON-NLS-1$ //$NON-NLS-2$
}
- return Arrays.asList(defaultColumn);
+ return Arrays.asList(defaultColumn.getSymbol());
}
@Override
@@ -194,5 +197,12 @@
XMLTable other = (XMLTable)obj;
return this.columns.equals(other.columns);
}
+
+ public void rewriteDefaultColumn() {
+ if (this.columns.isEmpty() && defaultColumn != null) {
+ this.columns.add(defaultColumn);
+ defaultColumn = null;
+ }
+ }
}
Modified: trunk/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java 2010-06-05
01:49:35 UTC (rev 2184)
+++ trunk/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java 2010-06-06
15:12:19 UTC (rev 2185)
@@ -1162,8 +1162,7 @@
for (DerivedColumn dc : obj.getPassing()) {
if (dc.getAlias() == null) {
Class<?> type = dc.getExpression().getType();
- if (type != DataTypeManager.DefaultDataClasses.STRING &&
- type != DataTypeManager.DefaultDataClasses.XML &&
+ if (type != DataTypeManager.DefaultDataClasses.XML &&
type != DataTypeManager.DefaultDataClasses.CLOB) {
handleValidationError(QueryPlugin.Util.getString("ValidationVisitor.context_item_type"),
obj); //$NON-NLS-1$
}
@@ -1176,6 +1175,9 @@
handleValidationError(QueryPlugin.Util.getString("ValidationVisitor.duplicate_passing",
dc.getAlias()), obj); //$NON-NLS-1$
}
}
+ if (obj.getXQueryExpression().usesContextItem() && !context) {
+ handleValidationError(QueryPlugin.Util.getString("ValidationVisitor.context_required"),
obj); //$NON-NLS-1$
+ }
boolean hasOrdinal = false;
for (XMLColumn xc : obj.getColumns()) {
if (!xc.isOrdinal()) {
Modified:
trunk/engine/src/main/java/org/teiid/query/xquery/saxon/SaxonXQueryExpression.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/xquery/saxon/SaxonXQueryExpression.java 2010-06-05
01:49:35 UTC (rev 2184)
+++
trunk/engine/src/main/java/org/teiid/query/xquery/saxon/SaxonXQueryExpression.java 2010-06-06
15:12:19 UTC (rev 2185)
@@ -22,15 +22,14 @@
package org.teiid.query.xquery.saxon;
-import java.io.StringReader;
import java.sql.Clob;
import java.sql.SQLException;
import java.sql.SQLXML;
import java.util.Arrays;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
-import java.util.Properties;
import javax.xml.transform.ErrorListener;
import javax.xml.transform.Source;
@@ -41,8 +40,10 @@
import net.sf.saxon.Configuration;
import net.sf.saxon.event.ProxyReceiver;
import net.sf.saxon.expr.AxisExpression;
+import net.sf.saxon.expr.ContextItemExpression;
import net.sf.saxon.expr.Expression;
import net.sf.saxon.expr.PathMap;
+import net.sf.saxon.expr.RootExpression;
import net.sf.saxon.expr.PathMap.PathMapArc;
import net.sf.saxon.expr.PathMap.PathMapNode;
import net.sf.saxon.expr.PathMap.PathMapNodeSet;
@@ -54,9 +55,7 @@
import net.sf.saxon.pattern.AnyNodeTest;
import net.sf.saxon.pattern.NodeKindTest;
import net.sf.saxon.query.DynamicQueryContext;
-import net.sf.saxon.query.QueryResult;
import net.sf.saxon.query.StaticQueryContext;
-import net.sf.saxon.query.XQueryExpression;
import net.sf.saxon.sxpath.IndependentContext;
import net.sf.saxon.sxpath.XPathEvaluator;
import net.sf.saxon.sxpath.XPathExpression;
@@ -72,16 +71,15 @@
import org.teiid.core.types.ClobType;
import org.teiid.core.types.DataTypeManager;
import org.teiid.core.types.XMLType;
-import org.teiid.logging.LogConstants;
-import org.teiid.logging.LogManager;
-import org.teiid.logging.MessageLevel;
import org.teiid.query.QueryPlugin;
+import org.teiid.query.analysis.AnalysisRecord;
import org.teiid.query.sql.lang.XMLTable;
import org.teiid.query.sql.lang.XMLTable.XMLColumn;
import org.teiid.query.sql.symbol.DerivedColumn;
import org.teiid.query.sql.symbol.XMLNamespaces;
import org.teiid.query.sql.symbol.XMLNamespaces.NamespaceItem;
+@SuppressWarnings("serial")
public class SaxonXQueryExpression {
private static final Expression DUMMY_EXPRESSION = new Expression() {
@@ -148,10 +146,8 @@
}
}
}
- boolean hasContext = false;
for (DerivedColumn derivedColumn : passing) {
if (derivedColumn.getAlias() == null) {
- hasContext = true; //skip the context item
continue;
}
try {
@@ -159,92 +155,156 @@
} catch (XPathException e) {
throw new TeiidRuntimeException(e, "Could not define global variable");
//$NON-NLS-1$
}
- ic.declareVariable("", derivedColumn.getAlias()); //$NON-NLS-1$
}
- XPathEvaluator eval = new XPathEvaluator(config);
- eval.setStaticContext(ic);
-
- processColumns(columns, eval);
+ processColumns(columns, ic);
try {
this.xQuery = context.compileQuery(xQueryString);
} catch (XPathException e) {
throw new QueryResolverException(e,
QueryPlugin.Util.getString("SaxonXQueryExpression.compile_failed"));
//$NON-NLS-1$
}
- if (hasContext) {
- useDocumentProjection(columns);
- } else {
- LogManager.logDetail(LogConstants.CTX_QUERY_PLANNER, "Document projection will
not be used, since no context item exists or there are unknown dependencies");
//$NON-NLS-1$
- }
}
-
- private void useDocumentProjection(List<XMLTable.XMLColumn> columns) {
- XQueryExpression toAnalyze = this.xQuery;
-
- PathMap map = new PathMap(DUMMY_EXPRESSION);
- PathMapNodeSet set = toAnalyze.getExpression().addToPathMap(map, null);
-
- boolean complexEndState = false;
- if (set != null) {
+
+ public boolean usesContextItem() {
+ return this.xQuery.usesContextItem();
+ }
+
+ public void useDocumentProjection(List<XMLTable.XMLColumn> columns, AnalysisRecord
record) {
+ PathMap map = this.xQuery.getPathMap();
+ PathMapRoot parentRoot;
+ try {
+ parentRoot = map.getContextRoot();
+ } catch (IllegalStateException e) {
+ if (record.recordDebug()) {
+ record.println("Document projection will not be used, since multiple context
item exist."); //$NON-NLS-1$
+ }
+ return;
+ }
+ if (parentRoot == null) {
+ //TODO: this seems like we could omit the context item altogether
+ //this.xQuery.usesContextItem() should also be false
+ if (record.recordDebug()) {
+ record.println("Document projection will not be used, since no context item
reference was found in the XQuery"); //$NON-NLS-1$
+ }
+ return;
+ }
+ HashSet<PathMapNode> finalNodes = new HashSet<PathMapNode>();
+ getReturnableNodes(parentRoot, finalNodes);
+
+ if (!finalNodes.isEmpty()) {
if (columns != null && !columns.isEmpty()) {
- if (set.size() != 1) {
- complexEndState = true;
- } else {
- for (XMLColumn xmlColumn : columns) {
- if (xmlColumn.isOrdinal()) {
- continue;
- }
- Expression internalExpression =
xmlColumn.getPathExpression().getInternalExpression();
- PathMap subMap = new PathMap(internalExpression);
- PathMapRoot root = subMap.getContextRoot();
- if (root == null) {
- continue;
- }
- PathMapNodeSet finalNodes = internalExpression.addToPathMap(map, set);
- if (finalNodes != null) {
- for (Iterator iter = finalNodes.iterator(); iter.hasNext(); ) {
- PathMapNode subNode = (PathMapNode)iter.next();
- if (xmlColumn.getSymbol().getType() == DataTypeManager.DefaultDataClasses.XML)
{
- subNode.createArc(new AxisExpression(Axis.DESCENDANT_OR_SELF,
AnyNodeTest.getInstance()));
- subNode.setReturnable(true);
- } else {
- //this may not always be needed, but it doesn't harm anything
- subNode.createArc(new AxisExpression(Axis.CHILD, NodeKindTest.TEXT));
- subNode.setAtomized();
- }
- }
- }
+ if (finalNodes.size() != 1) {
+ if (record.recordDebug()) {
+ record.println("Document projection will not be used, since multiple return
items exist"); //$NON-NLS-1$
}
+ return;
+ }
+ parentRoot = projectColumns(parentRoot, columns, finalNodes.iterator().next(),
record);
+ if (parentRoot == null) {
+ return;
}
} else {
- for (Iterator iter = set.iterator(); iter.hasNext(); ) {
+ for (Iterator iter = finalNodes.iterator(); iter.hasNext(); ) {
PathMapNode subNode = (PathMapNode)iter.next();
subNode.createArc(new AxisExpression(Axis.DESCENDANT_OR_SELF,
AnyNodeTest.getInstance()));
- subNode.setReturnable(true);
}
}
}
- //PathMap map = toAnalyze.getPathMap();
- contextRoot = map.getContextRoot();
- if (contextRoot == null || complexEndState || contextRoot.hasUnknownDependencies()) {
- LogManager.logDetail(LogConstants.CTX_QUERY_PLANNER, "Document projection will
not be used, since no context item exists or there are unknown dependencies");
//$NON-NLS-1$
- contextRoot = null;
- } else if (LogManager.isMessageToBeRecorded(LogConstants.CTX_QUERY_PLANNER,
MessageLevel.DETAIL)) {
- StringBuilder sb = new StringBuilder();
+ if (parentRoot.hasUnknownDependencies()) {
+ if (record.recordDebug()) {
+ record.println("Document projection will not be used since there are unknown
dependencies (most likely a user defined function)."); //$NON-NLS-1$
+ }
+ return;
+ }
+ contextRoot = parentRoot;
+ if (record.recordDebug()) {
+ StringBuilder sb = new StringBuilder();
showArcs(sb, contextRoot, 0);
- LogManager.logDetail(LogConstants.CTX_QUERY_PLANNER, "Using path filtering for
XQuery context item: \n" + sb.toString()); //$NON-NLS-1$
+ record.println("Using path filtering for XQuery context item: \n" +
sb.toString()); //$NON-NLS-1$
}
-/* StringBuilder sb = new StringBuilder();
- showArcs(sb, contextRoot, 0);
- System.out.println(sb);
-*/ }
+ }
- private void processColumns(List<XMLTable.XMLColumn> columns, XPathEvaluator
eval)
+ private PathMapRoot projectColumns(PathMapRoot parentRoot,
List<XMLTable.XMLColumn> columns, PathMapNode finalNode, AnalysisRecord record) {
+ for (XMLColumn xmlColumn : columns) {
+ if (xmlColumn.isOrdinal()) {
+ continue;
+ }
+ Expression internalExpression =
xmlColumn.getPathExpression().getInternalExpression();
+ PathMap subMap = new PathMap(internalExpression);
+ PathMapRoot subContextRoot = null;
+ for (PathMapRoot root : subMap.getPathMapRoots()) {
+ if (root.getRootExpression() instanceof ContextItemExpression ||
root.getRootExpression() instanceof RootExpression) {
+ if (subContextRoot != null) {
+ if (record.recordDebug()) {
+ record.println("Document projection will not be used, since multiple context
item exist in column path " + xmlColumn.getPath()); //$NON-NLS-1$
+ }
+ return null;
+ }
+ subContextRoot = root;
+ }
+ }
+ if (subContextRoot == null) {
+ //special case for handling '.', which the pathmap logic doesn't
consider as a root
+ if (internalExpression instanceof ContextItemExpression) {
+ addReturnedArcs(xmlColumn, finalNode);
+ }
+ continue;
+ }
+ for (PathMapArc arc : subContextRoot.getArcs()) {
+ finalNode.createArc(arc.getStep(), arc.getTarget());
+ }
+ HashSet<PathMapNode> subFinalNodes = new HashSet<PathMapNode>();
+ getReturnableNodes(subContextRoot, subFinalNodes);
+ for (Iterator iter = subFinalNodes.iterator(); iter.hasNext(); ) {
+ PathMapNode subNode = (PathMapNode)iter.next();
+ addReturnedArcs(xmlColumn, subNode);
+ }
+ }
+ //Workaround to rerun the reduction algorithm - by making a copy of the old version
+ PathMap newMap = new PathMap(DUMMY_EXPRESSION);
+ PathMapRoot newRoot = newMap.makeNewRoot(parentRoot.getRootExpression());
+ if (parentRoot.isAtomized()) {
+ newRoot.setAtomized();
+ }
+ if (parentRoot.isReturnable()) {
+ newRoot.setReturnable(true);
+ }
+ if (parentRoot.hasUnknownDependencies()) {
+ newRoot.setHasUnknownDependencies();
+ }
+ for (PathMapArc arc : parentRoot.getArcs()) {
+ newRoot.createArc(arc.getStep(), arc.getTarget());
+ }
+ return newMap.reduceToDownwardsAxes(newRoot);
+ }
+
+ private void addReturnedArcs(XMLColumn xmlColumn, PathMapNode subNode) {
+ if (xmlColumn.getSymbol().getType() == DataTypeManager.DefaultDataClasses.XML) {
+ subNode.createArc(new AxisExpression(Axis.DESCENDANT_OR_SELF,
AnyNodeTest.getInstance()));
+ } else {
+ //this may not always be needed, but it doesn't harm anything
+ subNode.createArc(new AxisExpression(Axis.CHILD, NodeKindTest.TEXT));
+ subNode.setAtomized();
+ }
+ }
+
+ private void getReturnableNodes(PathMapNode node, HashSet<PathMapNode> finalNodes)
{
+ if (node.isReturnable()) {
+ finalNodes.add(node);
+ }
+ for (PathMapArc arc : node.getArcs()) {
+ getReturnableNodes(arc.getTarget(), finalNodes);
+ }
+ }
+
+ private void processColumns(List<XMLTable.XMLColumn> columns, IndependentContext
ic)
throws TeiidProcessingException {
if (columns == null) {
return;
}
+ XPathEvaluator eval = new XPathEvaluator(config);
+ eval.setStaticContext(ic);
for (XMLColumn xmlColumn : columns) {
if (xmlColumn.isOrdinal()) {
continue;
@@ -254,7 +314,7 @@
path = xmlColumn.getName();
}
path = path.trim();
- if (path.startsWith("/") && !path.startsWith("//"))
{
+ if (path.startsWith("/") && !path.startsWith("//"))
{ //$NON-NLS-1$ //$NON-NLS-2$
path = path.substring(1);
}
XPathExpression exp;
@@ -275,9 +335,6 @@
if (value instanceof XMLType) {
return ((SQLXML)value).getSource(null);
}
- if (value instanceof String) {
- return new StreamSource(new StringReader((String)value));
- }
if (value instanceof ClobType) {
return new StreamSource(((Clob)value).getCharacterStream());
}
@@ -292,12 +349,8 @@
for (Map.Entry<String, Object> entry : parameterValues.entrySet()) {
Object value = entry.getValue();
- if(value instanceof SQLXML) {
- try {
- value = ((SQLXML)value).getSource(null);
- } catch (SQLException e) {
- throw new TeiidProcessingException(e);
- }
+ if(value instanceof SQLXML || value instanceof Clob) {
+ value = convertToSource(value);
}
dynamicContext.setParameter(entry.getKey(), value);
}
@@ -320,9 +373,7 @@
dynamicContext.setContextItem(doc);
}
try {
- //return this.xQuery.iterator(dynamicContext);
- QueryResult.serializeSequence(xQuery.iterator(dynamicContext), config,
System.out, new Properties());
- return null;
+ return xQuery.iterator(dynamicContext);
} catch (TransformerException e) {
throw new TeiidProcessingException(e,
QueryPlugin.Util.getString("SaxonXQueryExpression.bad_xquery")); //$NON-NLS-1$
}
Modified: trunk/engine/src/main/resources/org/teiid/query/i18n.properties
===================================================================
--- trunk/engine/src/main/resources/org/teiid/query/i18n.properties 2010-06-05 01:49:35
UTC (rev 2184)
+++ trunk/engine/src/main/resources/org/teiid/query/i18n.properties 2010-06-06 15:12:19
UTC (rev 2185)
@@ -892,7 +892,7 @@
ValidationVisitor.text_table_newline=Text table DELIMITER, QUOTE, and ESCAPE characters
cannot be the new line character.
ValidationVisitor.xml_namespaces=At most only one NO DEFAULT or DEFAULT namespace may be
specified.
ValidationVisitor.xml_namespaces_reserved=At most only one NO DEFAULT or DEFAULT
namespace may be specified.
-ValidationVisitor.context_item_type=XMLTABLE or XMLQUERY PASSING context item must be a
character type (XML, STRING, CLOB).
+ValidationVisitor.context_item_type=XMLTABLE or XMLQUERY PASSING context item must be an
XML or CLOB value.
ValidationVisitor.passing_requires_name=XMLTABLE or XMLQUERY PASSING clause can only
contain at most 1 unnamed item.
ValidationVisitor.duplicate_passing=XMLTABLE or XMLQUERY PASSING clause duplicate item
name "{0}".
ValidationVisitor.one_ordinal=Only one FOR ORDINALITY column is allowed for an XMLTABLE.
Modified: trunk/engine/src/test/java/org/teiid/query/processor/TestSQLXMLProcessing.java
===================================================================
---
trunk/engine/src/test/java/org/teiid/query/processor/TestSQLXMLProcessing.java 2010-06-05
01:49:35 UTC (rev 2184)
+++
trunk/engine/src/test/java/org/teiid/query/processor/TestSQLXMLProcessing.java 2010-06-06
15:12:19 UTC (rev 2185)
@@ -29,16 +29,15 @@
import org.junit.Ignore;
import org.junit.Test;
-import org.teiid.query.processor.ProcessorPlan;
import org.teiid.query.unittest.FakeMetadataFactory;
-@SuppressWarnings("nls")
+@SuppressWarnings({"nls", "unchecked"})
public class TestSQLXMLProcessing {
@Test public void testXmlElementTextContent() throws Exception {
String sql = "SELECT xmlelement(foo, '<bar>',
convert('<bar1/>', xml))"; //$NON-NLS-1$
- List[] expected = new List[] {
+ List<?>[] expected = new List<?>[] {
Arrays.asList("<foo><bar><bar1/></foo>"),
};
@@ -57,7 +56,7 @@
@Test public void testXmlElementTextContent1() throws Exception {
String sql = "SELECT xmlelement(foo, '<bar>', convert('<?xml
version=\"1.0\" encoding=\"UTF-8\"?><bar1/>',
xml))"; //$NON-NLS-1$
- List[] expected = new List[] {
+ List<?>[] expected = new List<?>[] {
Arrays.asList("<foo><bar><bar1></bar1></foo>"),
};
@@ -72,7 +71,7 @@
@Test public void testXmlElement() {
String sql = "SELECT xmlelement(e1, e2) from pm1.g1 order by e1, e2";
//$NON-NLS-1$
- List[] expected = new List[] {
+ List<?>[] expected = new List<?>[] {
Arrays.asList("<e1>1</e1>"),
Arrays.asList("<e1>0</e1>"),
Arrays.asList("<e1>0</e1>"),
@@ -92,7 +91,7 @@
@Test public void testXmlElementWithConcat() {
String sql = "SELECT xmlelement(e1, e2, xmlconcat(xmlelement(x),
xmlelement(y, e3))) from pm1.g1 order by e1, e2"; //$NON-NLS-1$
- List[] expected = new List[] {
+ List<?>[] expected = new List<?>[] {
Arrays.asList("<e1>1<x></x><y>false</y></e1>"),
Arrays.asList("<e1>0<x></x><y>false</y></e1>"),
Arrays.asList("<e1>0<x></x><y>false</y></e1>"),
@@ -112,7 +111,7 @@
@Test public void testXmlElementWithForest() {
String sql = "SELECT xmlelement(x, xmlforest(e1, e2, '1' as val))
from pm1.g1 order by e1, e2 limit 2"; //$NON-NLS-1$
- List[] expected = new List[] {
+ List<?>[] expected = new List<?>[] {
Arrays.asList("<x><e2>1</e2><val>1</val></x>"),
//note e1 is not present, because it's null
Arrays.asList("<x><e1>a</e1><e2>0</e2><val>1</val></x>"),
};
@@ -128,7 +127,7 @@
@Test public void testXmlElementWithAttributes() {
String sql = "SELECT xmlelement(x, xmlattributes(e1, e2, '1' as
val)) from pm1.g1 order by e1, e2 limit 2"; //$NON-NLS-1$
- List[] expected = new List[] {
+ List<?>[] expected = new List<?>[] {
Arrays.asList("<x e2=\"1\"
val=\"1\"></x>"), //note e1 is not present, because it's null
Arrays.asList("<x e1=\"a\" e2=\"0\"
val=\"1\"></x>"),
};
@@ -144,7 +143,7 @@
@Test public void testXmlElementWithPi() {
String sql = "SELECT xmlelement(x, xmlpi(name e1, ' 1'))";
//$NON-NLS-1$
- List[] expected = new List[] {
+ List<?>[] expected = new List<?>[] {
Arrays.asList("<x><?e1 1?></x>"),
};
@@ -159,7 +158,7 @@
@Test public void testXmlElementWithNamespaces() {
String sql = "SELECT xmlelement(x, xmlnamespaces(no default,
'http://foo' as x, 'http://foo1' as y), xmlattributes(e1), e2) from pm1.g1
order by e1, e2 limit 2"; //$NON-NLS-1$
- List[] expected = new List[] {
+ List<?>[] expected = new List<?>[] {
Arrays.asList("<x xmlns=\"\" xmlns:x=\"http://foo\"
xmlns:y=\"http://foo1\">1</x>"), //note e1 is not present, because
it's null
Arrays.asList("<x xmlns=\"\" xmlns:x=\"http://foo\"
xmlns:y=\"http://foo1\" e1=\"a\">0</x>"),
};
@@ -175,7 +174,7 @@
@Test public void testXmlAgg() {
String sql = "SELECT xmlelement(parent, xmlAgg(xmlelement(x,
xmlattributes(e1, e2)))) from pm1.g1"; //$NON-NLS-1$
- List[] expected = new List[] {
+ List<?>[] expected = new List<?>[] {
Arrays.asList("<parent><x e1=\"a\"
e2=\"0\"></x><x e2=\"1\"></x><x
e1=\"a\" e2=\"3\"></x><x e1=\"c\"
e2=\"1\"></x><x e1=\"b\"
e2=\"2\"></x><x e1=\"a\"
e2=\"0\"></x></parent>"),
};
@@ -190,7 +189,7 @@
@Test public void testXmlAggOrderBy() {
String sql = "SELECT xmlelement(parent, xmlAgg(xmlelement(x,
xmlattributes(e1, e2)) order by e2)) from pm1.g1"; //$NON-NLS-1$
- List[] expected = new List[] {
+ List<?>[] expected = new List<?>[] {
Arrays.asList("<parent><x e1=\"a\"
e2=\"0\"></x><x e1=\"a\"
e2=\"0\"></x><x e2=\"1\"></x><x
e1=\"c\" e2=\"1\"></x><x e1=\"b\"
e2=\"2\"></x><x e1=\"a\"
e2=\"3\"></x></parent>"),
};
@@ -205,7 +204,7 @@
@Test public void testXmlSerialize() {
String sql = "SELECT xmlserialize(document xmlelement(parent) as string)";
//$NON-NLS-1$
- List[] expected = new List[] {
+ List<?>[] expected = new List<?>[] {
Arrays.asList("<parent></parent>"),
};
@@ -217,12 +216,12 @@
helpProcess(plan, dataManager, expected);
}
- @Ignore
@Test public void testXmlTable() {
- String sql = "select * from xmltable('/a/b' passing
'<a><b>first</b><b x='attr'>second</b>'
columns x string, val string path '/b')"; //$NON-NLS-1$
+ String sql = "select * from xmltable('/a/b' passing
convert('<a><b>first</b><b
x=\"attr\">second</b></a>', xml) columns x string path
'@x', val string path '/.') as x"; //$NON-NLS-1$
- List[] expected = new List[] {
- Arrays.asList("<parent><x e1=\"a\"
e2=\"0\"></x><x e1=\"a\"
e2=\"0\"></x><x e2=\"1\"></x><x
e1=\"c\" e2=\"1\"></x><x e1=\"b\"
e2=\"2\"></x><x e1=\"a\"
e2=\"3\"></x></parent>"),
+ List<?>[] expected = new List<?>[] {
+ Arrays.asList(null, "first"),
+ Arrays.asList("attr", "second"),
};
FakeDataManager dataManager = new FakeDataManager();
@@ -232,5 +231,83 @@
helpProcess(plan, dataManager, expected);
}
+
+ @Test public void testXmlTableDefaultAndParent() {
+ String sql = "select * from xmltable('/a/b' passing
convert('<a y=\"rev\"><b>first</b><b
x=\"1\">second</b></a>', xml) columns x integer path
'@x' default -1, val string path '../@y') as x"; //$NON-NLS-1$
+
+ List<?>[] expected = new List<?>[] {
+ Arrays.asList(-1, "rev"),
+ Arrays.asList(1, "rev"),
+ };
+
+ FakeDataManager dataManager = new FakeDataManager();
+ sampleData1(dataManager);
+
+ ProcessorPlan plan = helpGetPlan(helpParse(sql),
FakeMetadataFactory.example1Cached());
+
+ helpProcess(plan, dataManager, expected);
+ }
+
+ @Test public void testXmlTableReturnXml() {
+ String sql = "select * from xmltable('/a/b' passing
convert('<a><b>first</b><b
x=\"1\">second</b></a>', xml) columns val xml path
'.') as x"; //$NON-NLS-1$
+
+ List<?>[] expected = new List<?>[] {
+ Arrays.asList("<b>first</b>"),
+ Arrays.asList("<b x=\"1\">second</b>"),
+ };
+
+ FakeDataManager dataManager = new FakeDataManager();
+ sampleData1(dataManager);
+
+ ProcessorPlan plan = helpGetPlan(helpParse(sql),
FakeMetadataFactory.example1Cached());
+
+ helpProcess(plan, dataManager, expected);
+ }
+
+ @Test public void testXmlTableNoColumns() {
+ String sql = "select * from xmltable('/a' passing
convert('<a><b>first</b><b
x=\"1\">second</b></a>', xml)) as x"; //$NON-NLS-1$
+
+ List<?>[] expected = new List<?>[] {
+ Arrays.asList("<a><b>first</b><b
x=\"1\">second</b></a>"),
+ };
+
+ FakeDataManager dataManager = new FakeDataManager();
+ sampleData1(dataManager);
+
+ ProcessorPlan plan = helpGetPlan(helpParse(sql),
FakeMetadataFactory.example1Cached());
+
+ helpProcess(plan, dataManager, expected);
+ }
+
+ @Test public void testXmlTablePassing() {
+ String sql = "select * from xmltable('<root>{for $x in $a/a/b
return <c>{$x}</c>}</root>' passing
convert('<a><b>first</b><b
x=\"1\">second</b></a>', xml) as a columns x xml path
'c[1]/b') as x"; //$NON-NLS-1$
+
+ List<?>[] expected = new List<?>[] {
+ Arrays.asList("<b>first</b>"),
+ };
+
+ FakeDataManager dataManager = new FakeDataManager();
+ sampleData1(dataManager);
+
+ ProcessorPlan plan = helpGetPlan(helpParse(sql),
FakeMetadataFactory.example1Cached());
+
+ helpProcess(plan, dataManager, expected);
+ }
+
+ @Ignore
+ @Test public void testXmlTableForOrdinality() {
+ String sql = "select * from xmltable('/a/b' passing
convert('<a><b><c>1</c></b><b>1</b><b><c>1</c></b><b>1</b></a>',
xml) as a columns x for ordinality, c integer path '.') as x"; //$NON-NLS-1$
+
+ List<?>[] expected = new List<?>[] {
+ Arrays.asList("<b>first</b>"),
+ };
+
+ FakeDataManager dataManager = new FakeDataManager();
+ sampleData1(dataManager);
+
+ ProcessorPlan plan = helpGetPlan(helpParse(sql),
FakeMetadataFactory.example1Cached());
+
+ helpProcess(plan, dataManager, expected);
+ }
}
Added:
trunk/engine/src/test/java/org/teiid/query/xquery/saxon/TestSaxonXQueryExpression.java
===================================================================
---
trunk/engine/src/test/java/org/teiid/query/xquery/saxon/TestSaxonXQueryExpression.java
(rev 0)
+++
trunk/engine/src/test/java/org/teiid/query/xquery/saxon/TestSaxonXQueryExpression.java 2010-06-06
15:12:19 UTC (rev 2185)
@@ -0,0 +1,66 @@
+package org.teiid.query.xquery.saxon;
+
+import java.util.Arrays;
+import java.util.HashMap;
+
+import net.sf.saxon.om.SequenceIterator;
+
+import org.junit.Ignore;
+import org.teiid.core.types.SQLXMLImpl;
+import org.teiid.core.types.XMLType;
+import org.teiid.query.sql.lang.XMLTable;
+import org.teiid.query.sql.symbol.DerivedColumn;
+import org.teiid.query.sql.symbol.ElementSymbol;
+import org.teiid.query.sql.symbol.XMLNamespaces;
+
+@Ignore
+public class TestSaxonXQueryExpression {
+
+ public static void main(String[] args) throws Exception {
+ String xquery =
+ "/Catalogs/Catalog/Items"; //$NON-NLS-1$
+
+ String inputdoc =
+ "<?xml version=\"1.0\"
encoding=\"UTF-8\"?>\n" + //$NON-NLS-1$
+ "<Catalogs xmlns=\"foo\"
xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n&q... +
//$NON-NLS-1$
+ " <Catalog>\n" + //$NON-NLS-1$
+ " <Items>\n" + //$NON-NLS-1$
+ " <Item ItemID=\"001\"
x=\"1\">\n" + //$NON-NLS-1$
+ " <Name>Lamp</Name>\n" + //$NON-NLS-1$
+ " <Quantity>5</Quantity>\n" +
//$NON-NLS-1$
+ " </Item>\n" + //$NON-NLS-1$
+ " <Item ItemID=\"002\">\n" +
//$NON-NLS-1$
+ " <Name>Screwdriver</Name>\n" +
//$NON-NLS-1$
+ " <Quantity>100</Quantity>\n" +
//$NON-NLS-1$
+ " </Item>\n" + //$NON-NLS-1$
+ " <Item ItemID=\"003\">\n" +
//$NON-NLS-1$
+ " <Name>Goat</Name>\n" + //$NON-NLS-1$
+ " <Quantity>4</Quantity>\n" +
//$NON-NLS-1$
+ " </Item>\n" + //$NON-NLS-1$
+ " </Items>\n" + //$NON-NLS-1$
+ " </Catalog>\n" + //$NON-NLS-1$
+ "</Catalogs>"; //$NON-NLS-1$
+
+/* Configuration config = new Configuration();
+ XPathExpression exp = new
XPathEvaluator(config).createExpression("text()");
+ Expression expr = exp.getInternalExpression();
+ PathMap map = new PathMap(expr);
+ map.diagnosticDump(System.out);
+ PathMapRoot root = map.getContextRoot();
+ StringBuilder sb = new StringBuilder();
+ SaxonXQueryExpression.showArcs(sb, root.getArcs(), 0);
+ System.out.println(sb);
+ Source s = config.buildDocument(new StreamSource(new StringReader("<a
Name='foo'><b><c
Name='bar'>hello<d>world</d></c></b></a>")));
+ Object o = new
XPathEvaluator(config).createExpression("//c").evaluateSingle(s);
+ XPathDynamicContext dc = exp.createDynamicContext((Item)o);
+ System.out.println(exp.evaluateSingle(dc).getStringValue());
+*/
+ XMLNamespaces namespaces = new XMLNamespaces(Arrays.asList(new
XMLNamespaces.NamespaceItem("foo", null)));
+ SaxonXQueryExpression se = new SaxonXQueryExpression(xquery, namespaces,
Arrays.asList(new DerivedColumn(null, new ElementSymbol("x"))),
Arrays.asList(new XMLTable.XMLColumn("y", "string", "/elem",
null), new XMLTable.XMLColumn("x", "string", "../@attr",
null)));
+ HashMap<String, Object> values = new HashMap<String, Object>();
+ values.put("y", new SQLXMLImpl(inputdoc));
+ SequenceIterator iter = se.evaluateXQuery(new XMLType(new SQLXMLImpl(inputdoc)),
values);
+ }
+
+
+}
Property changes on:
trunk/engine/src/test/java/org/teiid/query/xquery/saxon/TestSaxonXQueryExpression.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain