[teiid-commits] teiid SVN: r2097 - in trunk: documentation/reference/src/main/docbook/en-US/content and 6 other directories.

teiid-commits at lists.jboss.org teiid-commits at lists.jboss.org
Tue May 4 15:00:29 EDT 2010


Author: shawkins
Date: 2010-05-04 15:00:28 -0400 (Tue, 04 May 2010)
New Revision: 2097

Modified:
   trunk/connector-api/src/main/java/org/teiid/connector/api/SourceSystemFunctions.java
   trunk/documentation/reference/src/main/docbook/en-US/content/scalar_functions.xml
   trunk/engine/src/main/java/com/metamatrix/query/function/source/SystemSource.java
   trunk/engine/src/main/java/com/metamatrix/query/function/source/XMLSystemFunctions.java
   trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleAssignOutputElements.java
   trunk/engine/src/main/javacc/com/metamatrix/query/parser/SQLParser.jj
   trunk/engine/src/main/resources/com/metamatrix/query/i18n.properties
   trunk/engine/src/test/java/com/metamatrix/query/function/TestFunctionLibrary.java
   trunk/engine/src/test/java/com/metamatrix/query/processor/TestProcessor.java
Log:
TEIID-171 adding support for the xmlelement function

Modified: trunk/connector-api/src/main/java/org/teiid/connector/api/SourceSystemFunctions.java
===================================================================
--- trunk/connector-api/src/main/java/org/teiid/connector/api/SourceSystemFunctions.java	2010-05-04 14:06:31 UTC (rev 2096)
+++ trunk/connector-api/src/main/java/org/teiid/connector/api/SourceSystemFunctions.java	2010-05-04 19:00:28 UTC (rev 2097)
@@ -137,5 +137,6 @@
 	//xml
 	public static final String XPATHVALUE = "xpathvalue"; //$NON-NLS-1$
 	public static final String XSLTRANSFORM = "xsltransform"; //$NON-NLS-1$
+	public static final String XMLELEMENT = "xmlelement"; //$NON-NLS-1$
 
 }

Modified: trunk/documentation/reference/src/main/docbook/en-US/content/scalar_functions.xml
===================================================================
--- trunk/documentation/reference/src/main/docbook/en-US/content/scalar_functions.xml	2010-05-04 14:06:31 UTC (rev 2096)
+++ trunk/documentation/reference/src/main/docbook/en-US/content/scalar_functions.xml	2010-05-04 19:00:28 UTC (rev 2097)
@@ -1957,6 +1957,23 @@
               </para>
             </entry>
           </row>
+          <row>
+            <entry>
+              <para><code>XMLELEMENT(name [, content]*)</code></para>
+            </entry>
+            <entry>
+              <para>Returns an XML element with the given name and conent.  If the content value is of a type other than xml, 
+              it will be escaped when added to the parent element.  Null content values are ignored.  
+              Whitespace in XML or the string values of the content is preserved, but no whitespace is added between content values.</para>
+              <para>Example: with an xml_value of &lt;doc/&gt;, <code>xmlelement('myelement', 1, '&lt;2/&gt;', xml_value)</code>
+              		Returns: <code>&lt;myelement&gt;1&amp;lt;2/&amp;gt;&lt;doc/&gt;&gt;</code>
+              </para>
+            </entry>
+            <entry>
+              <para>Name in {string}.  Content can be any type. Return value is xml.
+              </para>
+            </entry>
+          </row>
         </tbody>
       </tgroup>
     </informaltable>

Modified: trunk/engine/src/main/java/com/metamatrix/query/function/source/SystemSource.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/function/source/SystemSource.java	2010-05-04 14:06:31 UTC (rev 2096)
+++ trunk/engine/src/main/java/com/metamatrix/query/function/source/SystemSource.java	2010-05-04 19:00:28 UTC (rev 2097)
@@ -168,6 +168,7 @@
         // xml functions
         addXpathFunction();
         addXslTransformFunction();
+        addXmlElement();
         
         addSecurityFunctions();
         
@@ -904,6 +905,14 @@
                             new FunctionParameter("result", DataTypeManager.DefaultDataTypes.CLOB, QueryPlugin.Util.getString("SystemSource.xsltransform_result")) ) );       //$NON-NLS-1$ //$NON-NLS-2$
     }
     
+    private void addXmlElement() {
+        functions.add(new FunctionMethod(SourceSystemFunctions.XMLELEMENT, QueryPlugin.Util.getString("SystemSource.xsltransform_description"), XML, XML_FUNCTION_CLASS, "xmlElement", //$NON-NLS-1$ //$NON-NLS-2$  
+                            new FunctionParameter[] { 
+                                new FunctionParameter("name", DataTypeManager.DefaultDataTypes.STRING, QueryPlugin.Util.getString("SystemSource.xmlelement_param1")), //$NON-NLS-1$ //$NON-NLS-2$
+                                new FunctionParameter("value", DataTypeManager.DefaultDataTypes.OBJECT, QueryPlugin.Util.getString("SystemSource.xmlelement_param2"), true)}, //$NON-NLS-1$ //$NON-NLS-2$ 
+                            new FunctionParameter("result", DataTypeManager.DefaultDataTypes.XML, QueryPlugin.Util.getString("SystemSource.xmlement_result")) ) );       //$NON-NLS-1$ //$NON-NLS-2$
+    }
+    
     private void addTimeZoneFunctions() {
         functions.add(new FunctionMethod(SourceSystemFunctions.MODIFYTIMEZONE, QueryPlugin.Util.getString("SystemSource.modifyTimeZone_description"), DATETIME, FUNCTION_CLASS, "modifyTimeZone", //$NON-NLS-1$ //$NON-NLS-2$ 
                             new FunctionParameter[] { 

Modified: trunk/engine/src/main/java/com/metamatrix/query/function/source/XMLSystemFunctions.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/function/source/XMLSystemFunctions.java	2010-05-04 14:06:31 UTC (rev 2096)
+++ trunk/engine/src/main/java/com/metamatrix/query/function/source/XMLSystemFunctions.java	2010-05-04 19:00:28 UTC (rev 2097)
@@ -29,6 +29,14 @@
 import java.sql.SQLException;
 import java.sql.SQLXML;
 
+import javax.xml.stream.EventFilter;
+import javax.xml.stream.XMLEventFactory;
+import javax.xml.stream.XMLEventReader;
+import javax.xml.stream.XMLEventWriter;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.events.XMLEvent;
 import javax.xml.transform.Source;
 import javax.xml.transform.Transformer;
 import javax.xml.transform.TransformerException;
@@ -38,10 +46,12 @@
 
 import net.sf.saxon.trans.XPathException;
 
+import com.metamatrix.api.exception.MetaMatrixComponentException;
 import com.metamatrix.api.exception.query.FunctionExecutionException;
 import com.metamatrix.common.types.ClobType;
 import com.metamatrix.common.types.DataTypeManager;
 import com.metamatrix.common.types.Streamable;
+import com.metamatrix.common.types.TransformationException;
 import com.metamatrix.common.types.XMLTranslator;
 import com.metamatrix.common.types.XMLType;
 import com.metamatrix.internal.core.xml.XPathHelper;
@@ -49,9 +59,6 @@
 import com.metamatrix.query.processor.xml.XMLUtil;
 import com.metamatrix.query.util.CommandContext;
 
-
-
-
 /** 
  * This class contains scalar system functions supporting for XML manipulation.
  * 
@@ -60,10 +67,6 @@
 public class XMLSystemFunctions {
 
     public static Object xpathValue(Object document, Object xpathStr) throws FunctionExecutionException {
-        if(document == null || xpathStr == null) {
-            return null;
-        }
-        
         Reader stream = null;
         
         if (document instanceof SQLXML) {
@@ -93,6 +96,7 @@
 		Reader reader = xmlResults.getCharacterStream();
 		final Source xmlSource = new StreamSource(reader);
 		try {
+			//this creates a non-validated sqlxml - it may not be valid xml/root-less xml
 			SQLXML result = XMLUtil.saveToBufferManager(context.getBufferManager(), new XMLTranslator() {
 				
 				@Override
@@ -115,5 +119,67 @@
 			}
 		}
     }
-    
+	
+	/**
+	 * Basic support for xmlelement.  Attributes are not yet supported.
+	 * @param context
+	 * @param name
+	 * @param contents
+	 * @return
+	 * @throws MetaMatrixComponentException
+	 */
+	public static XMLType xmlElement(CommandContext context, final String name, final Object... contents) throws MetaMatrixComponentException {
+		return new XMLType(XMLUtil.saveToBufferManager(context.getBufferManager(), new XMLTranslator() {
+			
+			@Override
+			public void translate(Writer writer) throws TransformerException,
+					IOException {
+				try {
+					XMLOutputFactory factory = XMLOutputFactory.newInstance();
+					XMLEventWriter eventWriter = factory.createXMLEventWriter(writer);
+					XMLEventFactory eventFactory = XMLEventFactory.newInstance();
+					eventWriter.add(eventFactory.createStartElement("", null, name)); //$NON-NLS-1$
+					for (Object object : contents) {
+						if (object == null) {
+							continue;
+						}
+						if (object instanceof XMLType) {
+							Reader r = null;
+							try {
+								r = ((XMLType)object).getCharacterStream();
+								XMLInputFactory inputFactory = XMLInputFactory.newInstance();
+								XMLEventReader xmlEventReader = inputFactory.createFilteredReader(inputFactory.createXMLEventReader(r), new EventFilter() {
+									
+									@Override
+									public boolean accept(XMLEvent event) {
+										return !event.isStartDocument() && !event.isEndDocument();
+									}
+								});
+								eventWriter.add(xmlEventReader);
+							} catch (SQLException e) {
+								throw new IOException(e);
+							} finally {
+								if (r != null) {
+									r.close();
+								}
+							}
+						} else {
+							try {
+								String result = DataTypeManager.transformValue(object, DataTypeManager.DefaultDataClasses.STRING);
+								eventWriter.add(eventFactory.createCharacters(result));
+							} catch (TransformationException e) {
+								throw new TransformerException(e);
+							}
+						}
+					}
+					eventWriter.add(eventFactory.createEndElement("", null, name)); //$NON-NLS-1$
+				} catch (XMLStreamException e) {
+					throw new TransformerException(e);
+				} finally {
+					
+				}
+			}
+		}, context.getStreamingBatchSize()));
+	}
+	
 }

Modified: trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleAssignOutputElements.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleAssignOutputElements.java	2010-05-04 14:06:31 UTC (rev 2096)
+++ trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleAssignOutputElements.java	2010-05-04 19:00:28 UTC (rev 2097)
@@ -194,12 +194,15 @@
 	            break;
 		    }
 		    default: {
-	            GroupSymbol intoGroup = (GroupSymbol)root.getProperty(NodeConstants.Info.INTO_GROUP);
-	            if (intoGroup != null) { //if this is a project into, treat the nodes under the source as a new plan root
-	                PlanNode intoRoot = NodeEditor.findNodePreOrder(root, NodeConstants.Types.SOURCE);
-	                execute(intoRoot.getFirstChild(), metadata, capFinder, rules, analysisRecord, context);
-	                return;
-	            }
+		    	if (root.getType() == NodeConstants.Types.PROJECT) {
+		    		GroupSymbol intoGroup = (GroupSymbol)root.getProperty(NodeConstants.Info.INTO_GROUP);
+		            if (intoGroup != null) { //if this is a project into, treat the nodes under the source as a new plan root
+		                PlanNode intoRoot = NodeEditor.findNodePreOrder(root, NodeConstants.Types.SOURCE);
+		                execute(intoRoot.getFirstChild(), metadata, capFinder, rules, analysisRecord, context);
+		                return;
+		            }
+	            	root.setProperty(NodeConstants.Info.PROJECT_COLS, outputElements);
+		    	}
 	            
 	            List<SingleElementSymbol> requiredInput = collectRequiredInputSymbols(root);
 	            

Modified: trunk/engine/src/main/javacc/com/metamatrix/query/parser/SQLParser.jj
===================================================================
--- trunk/engine/src/main/javacc/com/metamatrix/query/parser/SQLParser.jj	2010-05-04 14:06:31 UTC (rev 2096)
+++ trunk/engine/src/main/javacc/com/metamatrix/query/parser/SQLParser.jj	2010-05-04 19:00:28 UTC (rev 2097)
@@ -2904,7 +2904,7 @@
 	(
 		(funcToken = <LEFT> | funcToken = <RIGHT> | funcToken = <CHAR> | funcToken = <USER> 
 		                    | funcToken = <YEAR> | funcToken = <MONTH> | funcToken = <HOUR>
-		                    | funcToken = <MINUTE> | funcToken = <SECOND>)
+		                    | funcToken = <MINUTE> | funcToken = <SECOND> | funcToken = <XMLELEMENT>)
 		<LPAREN>
 		[
 			expression = expression(info)

Modified: trunk/engine/src/main/resources/com/metamatrix/query/i18n.properties
===================================================================
--- trunk/engine/src/main/resources/com/metamatrix/query/i18n.properties	2010-05-04 14:06:31 UTC (rev 2096)
+++ trunk/engine/src/main/resources/com/metamatrix/query/i18n.properties	2010-05-04 19:00:28 UTC (rev 2097)
@@ -771,6 +771,10 @@
 SystemSource.xsltransform_param1=Source document
 SystemSource.xsltransform_param2=XSL stylesheet
 SystemSource.xsltransform_result=Clob result
+SystemSource.xmlelement_description=Create an XML element. 
+SystemSource.xmlelement_param1=Element name
+SystemSource.xmlelement_param2=Element contents
+SystemSource.xmlelement_result=XML result
 SystemSource.modifyTimeZone_description=Modify the time zone of this timestamp by adding or subtracting time
 SystemSource.modifyTimeZone_param1=Timestamp
 SystemSource.modifyTimeZone_param2=Starting time zone

Modified: trunk/engine/src/test/java/com/metamatrix/query/function/TestFunctionLibrary.java
===================================================================
--- trunk/engine/src/test/java/com/metamatrix/query/function/TestFunctionLibrary.java	2010-05-04 14:06:31 UTC (rev 2096)
+++ trunk/engine/src/test/java/com/metamatrix/query/function/TestFunctionLibrary.java	2010-05-04 19:00:28 UTC (rev 2097)
@@ -1339,5 +1339,15 @@
         String xml = ObjectConverterUtil.convertToString(result.getCharacterStream());
         assertEquals("<?xml version=\"1.0\" encoding=\"UTF-8\"?><Catalogs xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"><Catalog><Items><Item ItemID=\"001\"><Name>Lamp</Name></Item></Items></Catalog></Catalogs>", xml);
     }
-    
+	
+	@Test public void testInvokeXmlElement() throws Exception {
+        CommandContext c = new CommandContext();
+        c.setBufferManager(BufferManagerFactory.getStandaloneBufferManager());
+        XMLType result = (XMLType)helpInvokeMethod("xmlelement", new Class[] {DataTypeManager.DefaultDataClasses.STRING, DataTypeManager.DefaultDataClasses.OBJECT, DataTypeManager.DefaultDataClasses.OBJECT}, 
+        		new Object[] {"foo", "<bar>", new XMLType(new SQLXMLImpl("<?xml version=\"1.0\" encoding=\"UTF-8\"?><Catalogs xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"><Catalog><Items><Item ItemID=\"001\"><Name>Lamp</Name><Quantity>5</Quantity></Item></Items></Catalog></Catalogs>"))}, c);
+        
+        String xml = ObjectConverterUtil.convertToString(result.getCharacterStream());
+        assertEquals("<foo>&lt;bar&gt;<Catalogs xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"><Catalog><Items><Item ItemID=\"001\"><Name>Lamp</Name><Quantity>5</Quantity></Item></Items></Catalog></Catalogs></foo>", xml);
+    }
+	
 }

Modified: trunk/engine/src/test/java/com/metamatrix/query/processor/TestProcessor.java
===================================================================
--- trunk/engine/src/test/java/com/metamatrix/query/processor/TestProcessor.java	2010-05-04 14:06:31 UTC (rev 2096)
+++ trunk/engine/src/test/java/com/metamatrix/query/processor/TestProcessor.java	2010-05-04 19:00:28 UTC (rev 2097)
@@ -302,6 +302,7 @@
 		CommandContext context = new CommandContext("0", "test", "user", null, "myvdb", 1, props, DEBUG, false); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
         context.setProcessorBatchSize(2000);
         context.setConnectorBatchSize(2000);
+        context.setBufferManager(BufferManagerFactory.getStandaloneBufferManager());
 		return context;
 	}   
     	
@@ -7482,6 +7483,25 @@
         helpProcess(plan, dataManager, expected);
     }
     
-
+    @Test public void testXmlElement() {
+        String sql = "SELECT xmlelement(e1, e2) from pm1.g1 order by e1, e2"; //$NON-NLS-1$
+        
+        List[] expected = new List[] {
+        		Arrays.asList(new String[] {null}),
+        		Arrays.asList("<a>0</a>"),
+        		Arrays.asList("<a>0</a>"),
+        		Arrays.asList("<a>3</a>"),
+        		Arrays.asList("<b>2</b>"),
+                Arrays.asList("<c>1</c>"),
+        };    
+    
+        FakeDataManager dataManager = new FakeDataManager();
+        sampleData1(dataManager);
+        
+        ProcessorPlan plan = helpGetPlan(helpParse(sql), FakeMetadataFactory.example1Cached());
+        
+        helpProcess(plan, dataManager, expected);
+    }
+    
     private static final boolean DEBUG = false;
 }



More information about the teiid-commits mailing list