[teiid-commits] teiid SVN: r4364 - in trunk: api/src/main/java/org/teiid/metadata and 16 other directories.

teiid-commits at lists.jboss.org teiid-commits at lists.jboss.org
Fri Aug 24 15:54:49 EDT 2012


Author: shawkins
Date: 2012-08-24 15:54:48 -0400 (Fri, 24 Aug 2012)
New Revision: 4364

Added:
   trunk/api/src/main/java/org/teiid/util/XMLReader.java
   trunk/api/src/test/java/org/teiid/util/TestXMLReader.java
Modified:
   trunk/api/src/main/java/org/teiid/language/SQLConstants.java
   trunk/api/src/main/java/org/teiid/metadata/AbstractMetadataRecord.java
   trunk/api/src/main/java/org/teiid/util/StAXSQLXML.java
   trunk/api/src/main/java/org/teiid/util/XMLInputStream.java
   trunk/api/src/test/java/org/teiid/util/TestXMLInputStream.java
   trunk/common-core/src/main/java/org/teiid/core/types/InputStreamFactory.java
   trunk/common-core/src/main/java/org/teiid/core/types/XMLType.java
   trunk/common-core/src/test/java/org/teiid/core/types/basic/TestStringToXmlTransform.java
   trunk/engine/src/main/java/org/teiid/query/eval/Evaluator.java
   trunk/engine/src/main/java/org/teiid/query/function/source/XMLSystemFunctions.java
   trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java
   trunk/engine/src/main/java/org/teiid/query/sql/symbol/XMLSerialize.java
   trunk/engine/src/main/java/org/teiid/query/sql/visitor/SQLStringVisitor.java
   trunk/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java
   trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj
   trunk/engine/src/main/resources/org/teiid/query/i18n.properties
   trunk/engine/src/test/java/org/teiid/query/parser/TestParser.java
   trunk/engine/src/test/java/org/teiid/query/processor/TestSQLXMLProcessing.java
   trunk/engine/src/test/java/org/teiid/query/rewriter/TestQueryRewriter.java
   trunk/engine/src/test/java/org/teiid/query/validator/TestValidator.java
Log:
TEIID-2163 adding support for binary xmlserialize

Modified: trunk/api/src/main/java/org/teiid/language/SQLConstants.java
===================================================================
--- trunk/api/src/main/java/org/teiid/language/SQLConstants.java	2012-08-23 18:14:04 UTC (rev 4363)
+++ trunk/api/src/main/java/org/teiid/language/SQLConstants.java	2012-08-24 19:54:48 UTC (rev 4364)
@@ -120,6 +120,10 @@
 		public static final String TRIM = "TRIM"; //$NON-NLS-1$
 		public static final String RESULT = "RESULT"; //$NON-NLS-1$
 		public static final Object OBJECTTABLE = "OBJECTTABLE"; //$NON-NLS-1$
+		public static final Object VERSION = "VERSION"; //$NON-NLS-1$
+		public static final Object INCLUDING = "INCLUDING"; //$NON-NLS-1$
+		public static final Object EXCLUDING = "EXCLUDING"; //$NON-NLS-1$
+		public static final Object XMLDECLARATION = "XMLDECLARATION"; //$NON-NLS-1$
 	}
 	
 	public interface Reserved {

Modified: trunk/api/src/main/java/org/teiid/metadata/AbstractMetadataRecord.java
===================================================================
--- trunk/api/src/main/java/org/teiid/metadata/AbstractMetadataRecord.java	2012-08-23 18:14:04 UTC (rev 4363)
+++ trunk/api/src/main/java/org/teiid/metadata/AbstractMetadataRecord.java	2012-08-24 19:54:48 UTC (rev 4364)
@@ -32,6 +32,7 @@
 
 import org.teiid.core.types.DataTypeManager;
 import org.teiid.core.util.EquivalenceUtil;
+import org.teiid.core.util.StringUtil;
 
 
 /**
@@ -94,7 +95,26 @@
         }
         return name;
 	}
+
+	public void getSQLString(StringBuilder sb) {
+		AbstractMetadataRecord parent = getParent();
+		if (parent != null) {
+        	parent.getSQLString(sb);
+        	sb.append(NAME_DELIM_CHAR);
+        }
+		sb.append('"').append(StringUtil.replace(name, "\"", "\"\"")).append('"'); //$NON-NLS-1$ //$NON-NLS-2$
+	}
 	
+	/**
+	 * Get the full name as a SQL safe string
+	 * @return
+	 */
+	public String getSQLString() {
+		StringBuilder sb = new StringBuilder();
+		getSQLString(sb);
+		return sb.toString();
+	}
+	
 	public AbstractMetadataRecord getParent() {
 		return null;
 	}

Modified: trunk/api/src/main/java/org/teiid/util/StAXSQLXML.java
===================================================================
--- trunk/api/src/main/java/org/teiid/util/StAXSQLXML.java	2012-08-23 18:14:04 UTC (rev 4363)
+++ trunk/api/src/main/java/org/teiid/util/StAXSQLXML.java	2012-08-24 19:54:48 UTC (rev 4364)
@@ -24,7 +24,9 @@
 
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.Reader;
 import java.io.StringWriter;
+import java.nio.charset.Charset;
 import java.sql.SQLException;
 
 import javax.xml.stream.FactoryConfigurationError;
@@ -36,27 +38,52 @@
 
 import org.teiid.core.types.SQLXMLImpl;
 import org.teiid.core.types.StandardXMLTranslator;
+import org.teiid.core.types.Streamable;
 
 /**
  * NOTE that this representation of XML does become unreadable after a read operation.
  */
 public class StAXSQLXML extends SQLXMLImpl {
-	private StAXSource source;
-	
-	public StAXSQLXML(StAXSource source) {
-		this.source = source;
+
+	public interface StAXSourceProvider {
+		StAXSource getStaxSource() throws SQLException;
 	}
-	
-	@SuppressWarnings("unchecked")
-	public <T extends Source> T getSource(Class<T> sourceClass) throws SQLException {
-		if (sourceClass == null || sourceClass == StAXSource.class) {
+
+	private static final class SingleUseStAXSourceProvider implements
+			StAXSourceProvider {
+		private StAXSource source;
+		
+		public SingleUseStAXSourceProvider(StAXSource source) {
+			this.source = source;
+		}
+
+		@Override
+		public StAXSource getStaxSource() throws SQLException {
 			if (source == null) {
 				throw new SQLException("Already Freed"); //$NON-NLS-1$
 			}
 			StAXSource result = source;
 			source = null;
-			return (T) result;
+			return result;
 		}
+	}
+
+	private StAXSourceProvider sourceProvider;
+
+	public StAXSQLXML(StAXSource source) {
+		this(new SingleUseStAXSourceProvider(source), Streamable.CHARSET);
+	}
+	
+	public StAXSQLXML(StAXSourceProvider provider, Charset charSet) {
+		this.sourceProvider = provider;
+		this.setCharset(charSet);
+	}
+	
+	@SuppressWarnings("unchecked")
+	public <T extends Source> T getSource(Class<T> sourceClass) throws SQLException {
+		if (sourceClass == null || sourceClass == StAXSource.class) {
+			return (T) sourceProvider.getStaxSource();
+		}
 		return super.getSource(sourceClass);
 	}
 	
@@ -76,7 +103,7 @@
 	@Override
 	public InputStream getBinaryStream() throws SQLException {
 		try {
-			return new XMLInputStream(getSource(StAXSource.class), XMLOutputFactory.newFactory());
+			return new XMLInputStream(getSource(StAXSource.class), XMLOutputFactory.newFactory(), getCharset().name());
 		} catch (XMLStreamException e) {
 			throw new SQLException(e);
 		} catch (FactoryConfigurationError e) {
@@ -84,4 +111,15 @@
 		}
 	}
 	
+	@Override
+	public Reader getCharacterStream() throws SQLException {
+		try {
+			return new XMLReader(getSource(StAXSource.class), XMLOutputFactory.newFactory());
+		} catch (XMLStreamException e) {
+			throw new SQLException(e);
+		} catch (FactoryConfigurationError e) {
+			throw new SQLException(e);
+		}
+	}
+	
 }
\ No newline at end of file

Modified: trunk/api/src/main/java/org/teiid/util/XMLInputStream.java
===================================================================
--- trunk/api/src/main/java/org/teiid/util/XMLInputStream.java	2012-08-23 18:14:04 UTC (rev 4363)
+++ trunk/api/src/main/java/org/teiid/util/XMLInputStream.java	2012-08-24 19:54:48 UTC (rev 4364)
@@ -32,22 +32,36 @@
 import javax.xml.stream.events.XMLEvent;
 import javax.xml.transform.stax.StAXSource;
 
+import org.teiid.core.types.Streamable;
 import org.teiid.core.types.XMLType;
 import org.teiid.core.util.AccessibleByteArrayOutputStream;
 
+/**
+ * Provides an {@link InputStream} adapter for StAX
+ */
 public class XMLInputStream extends InputStream {
 	private static final int BUFFER_SIZE = 1<<13;
 	private int pos = 0;
 	private AccessibleByteArrayOutputStream baos = new AccessibleByteArrayOutputStream(BUFFER_SIZE);
 	private XMLEventReader reader;
 	private XMLEventWriter writer;
+
+	/**
+	 * Return a UTF-8 {@link InputStream} of the XML
+	 * @param source
+	 * @param outFactory
+	 * @throws XMLStreamException
+	 */
+	public XMLInputStream(StAXSource source, XMLOutputFactory outFactory) throws XMLStreamException {
+		this(source, outFactory, Streamable.ENCODING);
+	}
 	
-	public XMLInputStream(StAXSource source, XMLOutputFactory outFactory) throws XMLStreamException {
+	public XMLInputStream(StAXSource source, XMLOutputFactory outFactory, String encoding) throws XMLStreamException {
 		reader = source.getXMLEventReader();
 		if (reader == null) {
 			this.reader = XMLType.getXmlInputFactory().createXMLEventReader(source.getXMLStreamReader());
 		}
-		this.writer = outFactory.createXMLEventWriter(baos);
+		this.writer = outFactory.createXMLEventWriter(baos, encoding);
 	}
 	
 	@Override
@@ -68,7 +82,7 @@
 				throw new IOException(e);
 			}
 		}
-		return baos.getBuffer()[pos++];
+		return 0xff & baos.getBuffer()[pos++];
 	}
 	
 	@Override

Added: trunk/api/src/main/java/org/teiid/util/XMLReader.java
===================================================================
--- trunk/api/src/main/java/org/teiid/util/XMLReader.java	                        (rev 0)
+++ trunk/api/src/main/java/org/teiid/util/XMLReader.java	2012-08-24 19:54:48 UTC (rev 4364)
@@ -0,0 +1,126 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.  Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA.
+ */
+
+package org.teiid.util;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.io.Writer;
+
+import javax.xml.stream.XMLEventReader;
+import javax.xml.stream.XMLEventWriter;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.events.XMLEvent;
+import javax.xml.transform.stax.StAXSource;
+
+import org.teiid.core.types.XMLType;
+
+/**
+ * Provides a {@link Reader} adapter for StAX
+ */
+public class XMLReader extends Reader {
+	private static final int BUFFER_SIZE = 1<<13;
+	private int pos = 0;
+	private StringBuilder builder = new StringBuilder(BUFFER_SIZE);
+	private XMLEventReader reader;
+	private XMLEventWriter writer;
+	
+	public XMLReader(StAXSource source, XMLOutputFactory outFactory) throws XMLStreamException {
+		reader = source.getXMLEventReader();
+		if (reader == null) {
+			this.reader = XMLType.getXmlInputFactory().createXMLEventReader(source.getXMLStreamReader());
+		}
+		this.writer = outFactory.createXMLEventWriter(new Writer() {
+			
+			@Override
+			public void write(char[] cbuf, int off, int len) throws IOException {
+				builder.append(cbuf, off, len);
+			}
+			
+			@Override
+			public void flush() throws IOException {
+				
+			}
+			
+			@Override
+			public void write(String str, int off, int len) throws IOException {
+				builder.append(str, off, len);
+			}
+			
+			@Override
+			public void close() throws IOException {
+				
+			}
+		});
+	}
+	
+	@Override
+	public int read() throws IOException {
+		while (pos >= builder.length()) {
+			if (!reader.hasNext()) {
+				return -1;
+			}
+			if (builder.length() > BUFFER_SIZE) {
+				builder.setLength(0);
+				pos = 0;
+			}
+			try {
+				XMLEvent event = reader.nextEvent();
+				writer.add(event);
+				writer.flush();
+			} catch (XMLStreamException e) {
+				throw new IOException(e);
+			}
+		}
+		return builder.charAt(pos++);
+	}
+	
+
+	@Override
+	public void close() throws IOException {
+		try {
+			reader.close();
+		} catch (XMLStreamException e) {
+			throw new IOException(e);
+		}
+	}
+	
+	@Override
+	public int read(char[] cbuf, int off, int len) throws IOException {
+		int i = 0;
+		int c = 0;
+		for (i = 0; i < len; i++) {
+			c = read();
+			if (c == -1) {
+				if (i == 0) {
+					return -1;
+				}
+				break;
+			}
+			cbuf[i+off] = (char)c;
+		}
+		return i;
+	}
+	
+
+}
\ No newline at end of file


Property changes on: trunk/api/src/main/java/org/teiid/util/XMLReader.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Modified: trunk/api/src/test/java/org/teiid/util/TestXMLInputStream.java
===================================================================
--- trunk/api/src/test/java/org/teiid/util/TestXMLInputStream.java	2012-08-23 18:14:04 UTC (rev 4363)
+++ trunk/api/src/test/java/org/teiid/util/TestXMLInputStream.java	2012-08-24 19:54:48 UTC (rev 4364)
@@ -51,5 +51,21 @@
 		byte[] bytes = ObjectConverterUtil.convertToByteArray(is);
 		assertEquals(xml, new String(bytes, "UTF-8"));
 	}
+	
+	@Test public void testUTF16Streaming() throws Exception {
+		StringBuilder xmlBuilder = new StringBuilder();
+		xmlBuilder.append("<?xml version=\"1.0\"?><root>");
+		for (int i = 0; i < 1000; i++) {
+			xmlBuilder.append("<a></a>");
+			xmlBuilder.append("<b></b>");
+		}
+		xmlBuilder.append("</root>");
+		String xml = xmlBuilder.toString();
+		
+		StAXSource source = new StAXSource(XMLType.getXmlInputFactory().createXMLEventReader(new StringReader(xml)));
+		XMLInputStream is = new XMLInputStream(source, XMLOutputFactory.newFactory(), "UTF-16");
+		byte[] bytes = ObjectConverterUtil.convertToByteArray(is);
+		assertEquals(xml, new String(bytes, "UTF-16"));
+	}
 
 }

Added: trunk/api/src/test/java/org/teiid/util/TestXMLReader.java
===================================================================
--- trunk/api/src/test/java/org/teiid/util/TestXMLReader.java	                        (rev 0)
+++ trunk/api/src/test/java/org/teiid/util/TestXMLReader.java	2012-08-24 19:54:48 UTC (rev 4364)
@@ -0,0 +1,55 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.  Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA.
+ */
+
+package org.teiid.util;
+
+import static org.junit.Assert.*;
+
+import java.io.StringReader;
+
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.transform.stax.StAXSource;
+
+import org.junit.Test;
+import org.teiid.core.types.XMLType;
+import org.teiid.core.util.ObjectConverterUtil;
+
+ at SuppressWarnings("nls")
+public class TestXMLReader {
+	
+	@Test public void testStreaming() throws Exception {
+		StringBuilder xmlBuilder = new StringBuilder();
+		xmlBuilder.append("<?xml version=\"1.0\"?><root>");
+		for (int i = 0; i < 1000; i++) {
+			xmlBuilder.append("<a></a>");
+			xmlBuilder.append("<b></b>");
+		}
+		xmlBuilder.append("</root>");
+		String xml = xmlBuilder.toString();
+		
+		StAXSource source = new StAXSource(XMLType.getXmlInputFactory().createXMLEventReader(new StringReader(xml)));
+		XMLReader is = new XMLReader(source, XMLOutputFactory.newFactory());
+		String str = ObjectConverterUtil.convertToString(is);
+		assertEquals(xml, str);
+	}
+
+}


Property changes on: trunk/api/src/test/java/org/teiid/util/TestXMLReader.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Modified: trunk/common-core/src/main/java/org/teiid/core/types/InputStreamFactory.java
===================================================================
--- trunk/common-core/src/main/java/org/teiid/core/types/InputStreamFactory.java	2012-08-23 18:14:04 UTC (rev 4363)
+++ trunk/common-core/src/main/java/org/teiid/core/types/InputStreamFactory.java	2012-08-24 19:54:48 UTC (rev 4364)
@@ -262,7 +262,7 @@
     
     public static class SQLXMLInputStreamFactory extends InputStreamFactory implements DataSource {
     	
-    	private SQLXML sqlxml;
+    	protected SQLXML sqlxml;
     	
     	public SQLXMLInputStreamFactory(SQLXML sqlxml) {
     		this.sqlxml = sqlxml;

Modified: trunk/common-core/src/main/java/org/teiid/core/types/XMLType.java
===================================================================
--- trunk/common-core/src/main/java/org/teiid/core/types/XMLType.java	2012-08-23 18:14:04 UTC (rev 4363)
+++ trunk/common-core/src/main/java/org/teiid/core/types/XMLType.java	2012-08-24 19:54:48 UTC (rev 4364)
@@ -136,6 +136,9 @@
 	}
 	
 	public String getEncoding() {
+		if (encoding == null) {
+			this.encoding = getEncoding(this);
+		}
 		return encoding;
 	}
 	
@@ -211,7 +214,7 @@
 			if (xml instanceof SQLXMLImpl) {
 				Charset cs = ((SQLXMLImpl)xml).getCharset();
 				if (cs != null) {
-					return cs.displayName();
+					return cs.name();
 				}
 			}
 			return getEncoding(xml.getBinaryStream());

Modified: trunk/common-core/src/test/java/org/teiid/core/types/basic/TestStringToXmlTransform.java
===================================================================
--- trunk/common-core/src/test/java/org/teiid/core/types/basic/TestStringToXmlTransform.java	2012-08-23 18:14:04 UTC (rev 4363)
+++ trunk/common-core/src/test/java/org/teiid/core/types/basic/TestStringToXmlTransform.java	2012-08-24 19:54:48 UTC (rev 4364)
@@ -28,7 +28,7 @@
 
 import org.junit.Test;
 import org.teiid.core.types.TransformationException;
-import org.teiid.core.types.basic.StringToSQLXMLTransform;
+import org.teiid.core.types.XMLType;
 
 
 @SuppressWarnings("nls")
@@ -45,6 +45,19 @@
        SQLXML xmlValue = (SQLXML)transform.transformDirect(xml);
        assertEquals(xml.replaceAll("[\r]", ""), xmlValue.getString().replaceAll("[\r]", ""));
     }
+	
+	@Test public void testGoodElement() throws Exception {
+        String xml = "<customer>\n" + //$NON-NLS-1$
+                        "<name>ABC</name>" + //$NON-NLS-1$
+                        "<age>32</age>" + //$NON-NLS-1$
+                     "</customer>"; //$NON-NLS-1$
+        
+       StringToSQLXMLTransform transform = new StringToSQLXMLTransform();
+       
+       XMLType xmlValue = (XMLType)transform.transformDirect(xml);
+       assertEquals(xml.replaceAll("[\r]", ""), xmlValue.getString().replaceAll("[\r]", ""));
+       assertEquals(XMLType.Type.ELEMENT, xmlValue.getType());
+    }
     
     @Test(expected=TransformationException.class) public void testBadXML() throws Exception {
         String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><customer>\n" + //$NON-NLS-1$

Modified: trunk/engine/src/main/java/org/teiid/query/eval/Evaluator.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/eval/Evaluator.java	2012-08-23 18:14:04 UTC (rev 4363)
+++ trunk/engine/src/main/java/org/teiid/query/eval/Evaluator.java	2012-08-24 19:54:48 UTC (rev 4364)
@@ -54,7 +54,15 @@
 import org.teiid.core.TeiidComponentException;
 import org.teiid.core.TeiidProcessingException;
 import org.teiid.core.TeiidRuntimeException;
-import org.teiid.core.types.*;
+import org.teiid.core.types.BaseLob;
+import org.teiid.core.types.BlobType;
+import org.teiid.core.types.ClobType;
+import org.teiid.core.types.InputStreamFactory;
+import org.teiid.core.types.SQLXMLImpl;
+import org.teiid.core.types.Sequencable;
+import org.teiid.core.types.Streamable;
+import org.teiid.core.types.TransformationException;
+import org.teiid.core.types.XMLType;
 import org.teiid.core.types.XMLType.Type;
 import org.teiid.core.types.basic.StringToSQLXMLTransform;
 import org.teiid.core.util.EquivalenceUtil;
@@ -694,8 +702,20 @@
 		return xml;
 	}
 
-	//TODO: determine when wrapping is not needed
 	public static InputStreamFactory getInputStreamFactory(Streamable<?> s) {
+		if (s.getReference() instanceof Streamable<?>) {
+			return getInputStreamFactory((Streamable<?>) s.getReference());
+		}
+		if (s.getReference() instanceof BaseLob) {
+			BaseLob bl = (BaseLob) s.getReference();
+			try {
+				InputStreamFactory isf = bl.getStreamFactory();
+				if (isf != null) {
+					return isf;
+				}
+			} catch (SQLException e) {
+			}
+		}
 		if (s instanceof ClobType) {
 			return new InputStreamFactory.ClobInputStreamFactory((Clob)s.getReference());
 		} else if (s instanceof BlobType){
@@ -796,14 +816,14 @@
 		}
 		try {
 			if (xs.isDocument() == null || !xs.isDocument()) {
-				return serialize(xs, value);
+				return XMLSystemFunctions.serialize(xs, value);
 			}
 			if (value.getType() == Type.UNKNOWN) {
 				Type type = StringToSQLXMLTransform.isXml(value.getCharacterStream());
 				value.setType(type);
 			}
 			if (value.getType() == Type.DOCUMENT || value.getType() == Type.ELEMENT) {
-				return serialize(xs, value);
+				return XMLSystemFunctions.serialize(xs, value);
 			}
 		} catch (SQLException e) {
 			 throw new FunctionExecutionException(QueryPlugin.Event.TEIID30334, e);
@@ -813,14 +833,6 @@
 		 throw new FunctionExecutionException(QueryPlugin.Event.TEIID30336, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30336));
 	}
 
-	private Object serialize(XMLSerialize xs, XMLType value) throws TransformationException {
-		if (xs.getType() == DataTypeManager.DefaultDataClasses.STRING) {
-			return DataTypeManager.transformValue(value, xs.getType());
-		}
-		InputStreamFactory isf = getInputStreamFactory(value);
-		return new ClobType(new ClobImpl(isf, -1));
-	}
-	
 	private Object evaluateTextLine(List<?> tuple, TextLine function) throws ExpressionEvaluationException, BlockedException, TeiidComponentException, FunctionExecutionException {
 		List<DerivedColumn> args = function.getExpressions();
 		Evaluator.NameValuePair<Object>[] nameValuePairs = getNameValuePairs(tuple, args, true);

Modified: trunk/engine/src/main/java/org/teiid/query/function/source/XMLSystemFunctions.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/function/source/XMLSystemFunctions.java	2012-08-23 18:14:04 UTC (rev 4363)
+++ trunk/engine/src/main/java/org/teiid/query/function/source/XMLSystemFunctions.java	2012-08-24 19:54:48 UTC (rev 4364)
@@ -42,6 +42,7 @@
 import java.util.Collections;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.NoSuchElementException;
 
 import javax.xml.XMLConstants;
 import javax.xml.namespace.QName;
@@ -55,6 +56,7 @@
 import javax.xml.stream.XMLOutputFactory;
 import javax.xml.stream.XMLStreamException;
 import javax.xml.stream.events.XMLEvent;
+import javax.xml.stream.util.EventReaderDelegate;
 import javax.xml.transform.Source;
 import javax.xml.transform.Transformer;
 import javax.xml.transform.TransformerException;
@@ -82,23 +84,22 @@
 import org.teiid.common.buffer.BufferManager;
 import org.teiid.common.buffer.FileStore;
 import org.teiid.common.buffer.FileStoreInputStreamFactory;
+import org.teiid.core.CorePlugin;
 import org.teiid.core.TeiidComponentException;
 import org.teiid.core.TeiidProcessingException;
 import org.teiid.core.TeiidRuntimeException;
-import org.teiid.core.types.ClobImpl;
-import org.teiid.core.types.ClobType;
-import org.teiid.core.types.SQLXMLImpl;
-import org.teiid.core.types.StandardXMLTranslator;
-import org.teiid.core.types.Streamable;
-import org.teiid.core.types.XMLTranslator;
-import org.teiid.core.types.XMLType;
+import org.teiid.core.types.*;
 import org.teiid.core.types.XMLType.Type;
+import org.teiid.core.util.ObjectConverterUtil;
+import org.teiid.core.util.ReaderInputStream;
 import org.teiid.query.QueryPlugin;
 import org.teiid.query.eval.Evaluator;
 import org.teiid.query.function.CharsetUtils;
+import org.teiid.query.sql.symbol.XMLSerialize;
 import org.teiid.query.util.CommandContext;
 import org.teiid.translator.WSConnection.Util;
 import org.teiid.util.StAXSQLXML;
+import org.teiid.util.StAXSQLXML.StAXSourceProvider;
 
 
 /** 
@@ -141,6 +142,63 @@
 		}
 	};
 
+	private static final EventFilter declarationOmittingFilter = new EventFilter() {
+		@Override
+		public boolean accept(XMLEvent event) {
+			return !event.isStartDocument() && !event.isEndDocument();
+		}
+	};
+
+	private static final class DeclarationStaxSourceProvider implements
+			StAXSourceProvider {
+		private final XMLEvent start;
+		private XMLType value;
+
+		private DeclarationStaxSourceProvider(XMLEvent start, XMLType value) {
+			this.start = start;
+			this.value = value;
+		}
+
+		@Override
+		public StAXSource getStaxSource() throws SQLException {
+			StAXSource source = value.getSource(StAXSource.class);
+			try {
+				XMLEventReader reader = getXMLEventReader(source);
+				reader = new EventReaderDelegate(reader) {
+					@Override
+					public XMLEvent nextEvent() throws XMLStreamException {
+						return replaceStart(super.nextEvent());
+					}
+					
+					@Override
+					public XMLEvent peek() throws XMLStreamException {
+						return replaceStart(super.peek());
+					}
+	
+					private XMLEvent replaceStart(XMLEvent event) {
+						if (event != null && event.getEventType() == XMLEvent.START_DOCUMENT) {
+							return start;
+						}
+						return event;
+					}
+					
+					@Override
+					public Object next() {
+						try {
+							return nextEvent();
+						} catch (XMLStreamException e) {
+							throw new NoSuchElementException();
+						}
+					}
+				};
+				return new StAXSource(reader);
+			} catch (XMLStreamException e) {
+				throw new SQLException(e);
+			}
+		}
+
+	}
+
 	private static final class JsonToXmlContentHandler implements
 			ContentHandler, XMLEventReader {
 		private Reader reader;
@@ -352,6 +410,15 @@
 	}
 	static XMLOutputFactory xmlOutputFactory = newXmlOutputFactory();
 	
+	private static XMLEventReader getXMLEventReader(StAXSource source) throws XMLStreamException {
+		XMLEventReader reader = source.getXMLEventReader();
+		if (reader == null) {
+			XMLInputFactory inputFactory = XMLType.getXmlInputFactory();
+			reader = inputFactory.createXMLEventReader(source.getXMLStreamReader());
+		}
+		return reader;
+	}
+	
 	public static XMLOutputFactory getOutputFactory() throws FactoryConfigurationError {
 		if (XMLType.isThreadSafeXmlFactories()) {
 			return xmlOutputFactory;
@@ -630,13 +697,12 @@
 		try {
 			if (object instanceof XMLType) {
 				XMLType xml = (XMLType)object;
-				r = xml.getCharacterStream();
 				Type type = xml.getType();
-				convertReader(writer, eventWriter, r, type);
+				convertReader(writer, eventWriter, null, type, xml);
 			} else if (object instanceof Clob) {
 				Clob clob = (Clob)object;
 				r = clob.getCharacterStream();
-				convertReader(writer, eventWriter, r, Type.TEXT);
+				convertReader(writer, eventWriter, r, Type.TEXT, null);
 			} else {
 				String val = convertToAtomicValue(object).getStringValue();
 				eventWriter.add(eventFactory.createCharacters(val));
@@ -652,8 +718,8 @@
 	}
 
 	private static void convertReader(Writer writer,
-			XMLEventWriter eventWriter, Reader r, Type type)
-			throws XMLStreamException, IOException, FactoryConfigurationError {
+			XMLEventWriter eventWriter, Reader r, Type type, XMLType xml)
+			throws XMLStreamException, IOException, FactoryConfigurationError, SQLException {
 		switch(type) {
 		case CONTENT:
 		case ELEMENT: 
@@ -662,6 +728,9 @@
 			eventWriter.flush();
 			char[] buf = new char[1 << 13];
 			int read = -1;
+			if (r == null) {
+				r = xml.getCharacterStream();
+			}
 			while ((read = r.read(buf)) != -1) {
 				writer.write(buf, 0, read);
 			}
@@ -669,20 +738,27 @@
 		}
 		case UNKNOWN:  //assume a document
 		case DOCUMENT: //filter the doc declaration
+			XMLEventReader eventReader = null;
 			XMLInputFactory inputFactory = XMLType.getXmlInputFactory();
-			if (!(r instanceof BufferedReader)) {
-				r = new BufferedReader(r);
+			if (r != null) {
+				if (!(r instanceof BufferedReader)) {
+					r = new BufferedReader(r);
+				}
+				eventReader = inputFactory.createXMLEventReader(r);
+			} else {
+				StAXSource staxSource = xml.getSource(StAXSource.class);
+				eventReader = staxSource.getXMLEventReader();
+				if (eventReader == null) {
+					eventReader = inputFactory.createXMLEventReader(staxSource.getXMLStreamReader());
+				}
 			}
-			XMLEventReader eventReader = inputFactory.createXMLEventReader(r);
-			eventReader = inputFactory.createFilteredReader(eventReader, new EventFilter() {
-				@Override
-				public boolean accept(XMLEvent event) {
-					return !event.isStartDocument() && !event.isEndDocument();
-				}
-			});
+			eventReader = inputFactory.createFilteredReader(eventReader, declarationOmittingFilter);
 			eventWriter.add(eventReader);
 			break;
 		case TEXT:
+			if (r == null) {
+				r = xml.getCharacterStream();
+			}
 			XMLEventFactory eventFactory = threadLocalEventtFactory.get();
 			char[] buf = new char[1 << 13];
 			int read = -1;
@@ -919,5 +995,89 @@
 	    	}
 	    }
 	}
+	
+	public static Object serialize(XMLSerialize xs, XMLType value) throws TransformationException {
+		Type type = value.getType();
+		final Charset encoding;
+		if (xs.getEncoding() != null) {
+			encoding = Charset.forName(xs.getEncoding());					
+		} else {
+			encoding = UTF_8;
+		}
+		if (Boolean.TRUE.equals(xs.getDeclaration())) {
+			//need to replace existing/default declaration
+			if (type == Type.ELEMENT || type == Type.DOCUMENT) {
+				XMLEventFactory xmlEventFactory = threadLocalEventtFactory.get();
+				xmlEventFactory.setLocation(dummyLocation);
+				XMLEvent start = null;
+				if (xs.getVersion() != null) {
+					start = xmlEventFactory.createStartDocument(encoding.name(), xs.getVersion());
+				} else if (xs.getEncoding() != null) {
+					start = xmlEventFactory.createStartDocument(encoding.name());
+				} else {
+					start = xmlEventFactory.createStartDocument();
+				}
+				StAXSourceProvider sourceProvider = new DeclarationStaxSourceProvider(start, value);
+				value = new XMLType(new StAXSQLXML(sourceProvider, encoding));
+				value.setType(type);
+			}
+			//else just ignore, since the result is likely invalid
+		} else if (type == Type.DOCUMENT && Boolean.FALSE.equals(xs.getDeclaration())){
+			final XMLType v = value;
+			StAXSourceProvider sourceProvider = new StAXSourceProvider() {
+				@Override
+				public StAXSource getStaxSource() throws SQLException {
+					try {
+						XMLEventReader eventReader = getXMLEventReader(v.getSource(StAXSource.class));
+						eventReader = XMLType.getXmlInputFactory().createFilteredReader(eventReader, declarationOmittingFilter);
+						return new StAXSource(eventReader);
+					} catch (XMLStreamException e) {
+						throw new SQLException(e);
+					}
+				}
+			};
+			value = new XMLType(new StAXSQLXML(sourceProvider, encoding));
+			value.setType(Type.DOCUMENT);
+		}
+		if (xs.getType() == DataTypeManager.DefaultDataClasses.STRING) {
+			return DataTypeManager.transformValue(value, xs.getType());
+		}
+		if (xs.getType() == DataTypeManager.DefaultDataClasses.CLOB) {
+			InputStreamFactory isf = Evaluator.getInputStreamFactory(value);
+			return new ClobType(new ClobImpl(isf, -1));
+		}
+		if (xs.getType() == DataTypeManager.DefaultDataClasses.VARBINARY) {
+			try {
+				InputStream is = null;
+				if (!Charset.forName(value.getEncoding()).equals(encoding)) {
+					is = new ReaderInputStream(value.getCharacterStream(), encoding);
+				} else {
+					is = value.getBinaryStream();					
+				}
+				byte[] bytes = ObjectConverterUtil.convertToByteArray(is, DataTypeManager.MAX_LOB_MEMORY_BYTES);
+				return new BinaryType(bytes);
+			} catch (SQLException e) {
+				throw new TransformationException(CorePlugin.Event.TEIID10080, e, CorePlugin.Util.gs(CorePlugin.Event.TEIID10080, "XML", "VARBINARY")); //$NON-NLS-1$ //$NON-NLS-2$ 
+		    } catch (IOException e) {
+		    	throw new TransformationException(CorePlugin.Event.TEIID10080, e, CorePlugin.Util.gs(CorePlugin.Event.TEIID10080, "XML", "VARBINARY")); //$NON-NLS-1$ //$NON-NLS-2$
+		    }
+		}
+		InputStreamFactory isf = null;
+		if (!Charset.forName(value.getEncoding()).equals(encoding)) {
+			//create a wrapper for the input stream
+			isf = new InputStreamFactory.SQLXMLInputStreamFactory(value) {
+				public InputStream getInputStream() throws IOException {
+					try {
+						return new ReaderInputStream(sqlxml.getCharacterStream(), encoding);
+					} catch (SQLException e) {
+						throw new IOException(e);
+					}
+				}
+			};
+		} else {
+			isf = Evaluator.getInputStreamFactory(value);
+		}
+		return new BlobType(new BlobImpl(isf));
+	}
     
 }

Modified: trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java	2012-08-23 18:14:04 UTC (rev 4363)
+++ trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java	2012-08-24 19:54:48 UTC (rev 4364)
@@ -24,6 +24,7 @@
 
 import java.math.BigDecimal;
 import java.math.BigInteger;
+import java.nio.charset.Charset;
 import java.sql.Date;
 import java.sql.Time;
 import java.sql.Timestamp;
@@ -1949,6 +1950,22 @@
         	expression = rewriteExpressionDirect(((ExpressionSymbol)expression).getExpression());
         } else if (expression instanceof Criteria) {
         	expression = rewriteCriteria((Criteria)expression);
+        } else if (expression instanceof XMLSerialize) {
+        	rewriteExpressions(expression);
+        	XMLSerialize serialize = (XMLSerialize)expression;
+        	if (isNull(serialize.getExpression())) {
+        		return new Constant(null, serialize.getType());
+        	}
+        	if (serialize.getDeclaration() == null && serialize.isDocument()) {
+        		if ((serialize.getVersion() != null && !serialize.getVersion().equals("1.0"))) { //$NON-NLS-1$
+        			serialize.setDeclaration(true);
+        		} else if (serialize.getEncoding() != null) {
+        			Charset encoding = Charset.forName(serialize.getEncoding());
+        			if (!encoding.equals(Charset.forName("UTF-8")) && !encoding.equals(Charset.forName("UTF-16"))) { //$NON-NLS-1$ //$NON-NLS-2$
+            			serialize.setDeclaration(true);
+        			}
+        		}
+        	}
         } else {
         	rewriteExpressions(expression);
         } 

Modified: trunk/engine/src/main/java/org/teiid/query/sql/symbol/XMLSerialize.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/symbol/XMLSerialize.java	2012-08-23 18:14:04 UTC (rev 4363)
+++ trunk/engine/src/main/java/org/teiid/query/sql/symbol/XMLSerialize.java	2012-08-24 19:54:48 UTC (rev 4364)
@@ -23,6 +23,8 @@
 package org.teiid.query.sql.symbol;
 
 import org.teiid.core.types.DataTypeManager;
+import org.teiid.core.util.EquivalenceUtil;
+import org.teiid.core.util.HashCodeUtil;
 import org.teiid.query.sql.LanguageVisitor;
 import org.teiid.query.sql.visitor.SQLStringVisitor;
 
@@ -31,9 +33,12 @@
 	private static final long serialVersionUID = -6574662238317329252L;
 	
 	private Boolean document;
+	private Boolean declaration;
 	private Expression expression;
 	private String typeString;
 	private Class<?> type;
+	private String version;
+	private String encoding;
 	
 	@Override
 	public Class<?> getType() {
@@ -47,6 +52,30 @@
 		return type;
 	}
 	
+	public String getEncoding() {
+		return encoding;
+	}
+	
+	public void setEncoding(String encoding) {
+		this.encoding = encoding;
+	}
+	
+	public String getVersion() {
+		return version;
+	}
+	
+	public void setVersion(String version) {
+		this.version = version;
+	}
+	
+	public Boolean getDeclaration() {
+		return declaration;
+	}
+	
+	public void setDeclaration(Boolean declaration) {
+		this.declaration = declaration;
+	}
+	
 	public Expression getExpression() {
 		return expression;
 	}
@@ -83,12 +112,15 @@
 		clone.expression = (Expression)this.expression.clone();
 		clone.typeString = this.typeString;
 		clone.type = this.type;
+		clone.declaration = this.declaration;
+		clone.version = this.version;
+		clone.encoding = this.encoding;
 		return clone;
 	}
 	
 	@Override
 	public int hashCode() {
-		return expression.hashCode();
+		return HashCodeUtil.hashCode(expression.hashCode(), getType());
 	}
 	
 	public boolean equals(Object obj) {
@@ -99,9 +131,12 @@
 			return false;
 		}
 		XMLSerialize other = (XMLSerialize)obj;
-		return document == other.document 
+		return EquivalenceUtil.areEqual(this.document, other.document)
 			&& this.expression.equals(other.expression)
-			&& this.getType() == other.getType();
+			&& this.getType() == other.getType()
+			&& EquivalenceUtil.areEqual(this.declaration, other.declaration)
+			&& EquivalenceUtil.areEqual(this.version, other.version)
+			&& EquivalenceUtil.areEqual(this.encoding, other.encoding);
 	}
 	
 	@Override

Modified: trunk/engine/src/main/java/org/teiid/query/sql/visitor/SQLStringVisitor.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/visitor/SQLStringVisitor.java	2012-08-23 18:14:04 UTC (rev 4363)
+++ trunk/engine/src/main/java/org/teiid/query/sql/visitor/SQLStringVisitor.java	2012-08-24 19:54:48 UTC (rev 4364)
@@ -1922,6 +1922,28 @@
             append(SPACE);
             append(obj.getTypeString());
         }
+        if (obj.getEncoding() != null) {
+        	append(SPACE);
+        	append(NonReserved.ENCODING);
+        	append(SPACE);
+        	append(escapeSinglePart(obj.getEncoding()));
+        }
+        if (obj.getVersion() != null) {
+        	append(SPACE);
+        	append(NonReserved.VERSION);
+        	append(SPACE);
+        	append(new Constant(obj.getVersion()));
+        }
+        if (obj.getDeclaration() != null) {
+        	append(SPACE);
+        	if (obj.getDeclaration()) {
+        		append(NonReserved.INCLUDING);
+        	} else {
+        		append(NonReserved.EXCLUDING);
+        	}
+        	append(SPACE);
+        	append(NonReserved.XMLDECLARATION);
+        }
         append(Tokens.RPAREN);
     }
 

Modified: trunk/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java	2012-08-23 18:14:04 UTC (rev 4363)
+++ trunk/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java	2012-08-24 19:54:48 UTC (rev 4364)
@@ -248,6 +248,20 @@
 			handleValidationError(QueryPlugin.Util.getString("ERR.015.012.0011"),obj); //$NON-NLS-1$
 		}
 	}
+	
+	@Override
+	public void visit(XMLSerialize obj) {
+		if (obj.getEncoding() != null ) {
+        	try {
+				Charset.forName(obj.getEncoding());
+        	} catch (IllegalArgumentException e) {
+        		handleValidationError(QueryPlugin.Util.getString("ValidationVisitor.invalid_encoding", obj.getEncoding()), obj); //$NON-NLS-1$
+        	}
+			if ((obj.getType() != DataTypeManager.DefaultDataClasses.BLOB && obj.getType() != DataTypeManager.DefaultDataClasses.VARBINARY)) {
+				handleValidationError(QueryPlugin.Util.getString("ValidationVisitor.encoding_for_binary"), obj); //$NON-NLS-1$
+			}
+		}
+	}
 
     public void visit(DependentSetCriteria obj) {
         this.validateRowLimitFunctionNotInInvalidCriteria(obj);

Modified: trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj
===================================================================
--- trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj	2012-08-23 18:14:04 UTC (rev 4363)
+++ trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj	2012-08-24 19:54:48 UTC (rev 4364)
@@ -450,6 +450,10 @@
 |   <HEADER: "header">
 |   <NULLS: "nulls">
 |   <OBJECTTABLE: "objecttable">
+|   <VERSION: "version">
+|   <INCLUDING: "including">
+|   <EXCLUDING: "excluding">
+|   <XMLDECLARATION: "xmldeclaration">
 
 }
 /*
@@ -552,7 +556,12 @@
 {
 }
 {
-    (<INSTEAD>|<VIEW>|<ENABLED>|<DISABLED>|<KEY>|<SERIAL>|<TEXTAGG>|<COUNT>|<ROW_NUMBER>|<RANK>|<DENSE_RANK>|<SUM>|<AVG>|<MIN>|<MAX>|<EVERY>|<STDDEV_POP>|<STDDEV_SAMP>|<VAR_SAMP>|<VAR_POP>|<DOCUMENT>|<CONTENT>|<TRIM>|<EMPTY>|<ORDINALITY>|<PATH>|<FIRST>|<LAST>|<NEXT>|<SUBSTRING>|<EXTRACT>|<TO_CHARS>|<TO_BYTES>|<TIMESTAMPADD>|<TIMESTAMPDIFF>|<QUERYSTRING>|<NAMESPACE>|<RESULT>|<INDEX>|<ACCESSPATTERN>|<AUTO_INCREMENT>|<WELLFORMED>|<SQL_TSI_FRAC_SECOND>|<SQL_TSI_SECOND>|<SQL_TSI_MINUTE>|<SQL_TSI_HOUR>|<SQL_TSI_DAY>|<SQL_TSI_WEEK>|<SQL_TSI_MONTH>|<SQL_TSI_QUARTER>|<SQL_TSI_YEAR>|<TEXTTABLE>|<ARRAYTABLE>|<SELECTOR>|<SKIP_KEYWORD>|<WIDTH>|<PASSING>|<NAME>|<ENCODING>|<COLUMNS>|<DELIMITER>|<QUOTE>|<HEADER>|<NULLS>|<OBJECTTABLE>)
+    (<INSTEAD>|<VIEW>|<ENABLED>|<DISABLED>|<KEY>|<SERIAL>|<TEXTAGG>|<COUNT>|<ROW_NUMBER>|<RANK>|<DENSE_RANK>|<SUM>|<AVG>|<MIN>|<MAX>|<EVERY>|<STDDEV_POP>
+     |<STDDEV_SAMP>|<VAR_SAMP>|<VAR_POP>|<DOCUMENT>|<CONTENT>|<TRIM>|<EMPTY>|<ORDINALITY>|<PATH>|<FIRST>|<LAST>|<NEXT>|<SUBSTRING>|<EXTRACT>|<TO_CHARS>
+     |<TO_BYTES>|<TIMESTAMPADD>|<TIMESTAMPDIFF>|<QUERYSTRING>|<NAMESPACE>|<RESULT>|<INDEX>|<ACCESSPATTERN>|<AUTO_INCREMENT>|<WELLFORMED>|<SQL_TSI_FRAC_SECOND>
+     |<SQL_TSI_SECOND>|<SQL_TSI_MINUTE>|<SQL_TSI_HOUR>|<SQL_TSI_DAY>|<SQL_TSI_WEEK>|<SQL_TSI_MONTH>|<SQL_TSI_QUARTER>|<SQL_TSI_YEAR>|<TEXTTABLE>|<ARRAYTABLE>
+     |<SELECTOR>|<SKIP_KEYWORD>|<WIDTH>|<PASSING>|<NAME>|<ENCODING>|<COLUMNS>|<DELIMITER>|<QUOTE>|<HEADER>|<NULLS>|<OBJECTTABLE>
+     |<VERSION>|<INCLUDING>|<EXCLUDING>|<XMLDECLARATION>)
     {
     	return getToken(0);
     }	
@@ -2326,17 +2335,26 @@
 	Expression expr = null;
 	Boolean doc = null;
 	Token t = null;
+	String enc = null;
+	Boolean declr = null;
+	String ver = null;
 }
 {
 	<XMLSERIALIZE> <LPAREN>
 	[LOOKAHEAD(1) (<DOCUMENT> {doc = true;}| <CONTENT> {doc = false;})]
 	expr = expression(info)
 	[
-		<AS> (t = <STRING> | t = <VARCHAR> | t = <CLOB>)
+		<AS> (<STRING> | <VARCHAR> | <CLOB> | <VARBINARY> | <BLOB>) { t = getToken(0);}
 	]
+	[ <ENCODING> enc = id() ]
+	[ <VERSION> ver = stringVal() ]
+	[ ( <INCLUDING> {declr = true;}| <EXCLUDING> {declr = false;}) <XMLDECLARATION> ]
 	<RPAREN>
 	{
 		XMLSerialize result = new XMLSerialize();
+		result.setEncoding(enc);
+		result.setVersion(ver);
+		result.setDeclaration(declr);
 		result.setExpression(expr);
 		if (doc != null) {
 			result.setDocument(doc);

Modified: trunk/engine/src/main/resources/org/teiid/query/i18n.properties
===================================================================
--- trunk/engine/src/main/resources/org/teiid/query/i18n.properties	2012-08-23 18:14:04 UTC (rev 4363)
+++ trunk/engine/src/main/resources/org/teiid/query/i18n.properties	2012-08-24 19:54:48 UTC (rev 4364)
@@ -185,6 +185,7 @@
 ValidationVisitor.no_loop = CONTINUE/BREAK can only be used in a LOOP/WHILE statement.
 ValidationVisitor.invalid_label = CONTINUE/BREAK labels can only target LOOP/WHILE statements. {0} targets a block.
 ValidationVisitor.unknown_block_label = No label found in containing scope with name {0}.
+ValidationVisitor.encoding_for_binary=The XMLSERIALIZE ENCODING option is only for binary serialization types.
 ERR.015.012.0029 = INSERT, UPDATE, and DELETE not allowed on XML documents
 ERR.015.012.0030 = Commands used in stored procedure language not allowed on XML documents
 TEIID30130=Queries against XML documents can not have a GROUP By clause

Modified: trunk/engine/src/test/java/org/teiid/query/parser/TestParser.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/parser/TestParser.java	2012-08-23 18:14:04 UTC (rev 4363)
+++ trunk/engine/src/test/java/org/teiid/query/parser/TestParser.java	2012-08-24 19:54:48 UTC (rev 4364)
@@ -5073,6 +5073,18 @@
 		assertEquals("SELECT * FROM OBJECTTABLE(LANGUAGE 'foo' 'x' COLUMNS y date 'row.date' DEFAULT {d'2000-01-01'}) AS x", actualCommand.toString());
     }
     
+    @Test public void testObjectTable1() throws Exception {
+    	Query query = new Query();
+    	query.setSelect(new Select(Arrays.asList(new MultipleElementSymbol())));
+    	ObjectTable objectTable = new ObjectTable();
+    	objectTable.setRowScript("y");
+    	objectTable.setPassing(Arrays.asList(new DerivedColumn("y", new ElementSymbol("e1"))));
+    	objectTable.setColumns(Arrays.asList(new ObjectTable.ObjectColumn("z", "time", "now()", null)));
+    	objectTable.setName("x");
+		query.setFrom(new From(Arrays.asList(objectTable)));
+    	helpTest("select * from objecttable('y' passing e1 as y columns z time 'now()') as x", "SELECT * FROM OBJECTTABLE('y' PASSING e1 AS y COLUMNS z time 'now()') AS x", query);
+    }
+    
     @Test public void testXmlSerialize() throws Exception {
     	XMLSerialize f = new XMLSerialize();
     	f.setDocument(true);
@@ -5104,6 +5116,16 @@
     	helpTestExpression("xmlserialize(x as CLOB)", "XMLSERIALIZE(x AS CLOB)", f);
     }
     
+    @Test public void testXmlSerialize2() throws Exception {
+    	XMLSerialize f = new XMLSerialize();
+    	f.setExpression(new ElementSymbol("x"));
+    	f.setTypeString("BLOB");
+    	f.setDeclaration(Boolean.TRUE);
+    	f.setVersion("1.0");
+    	f.setEncoding("UTF-8");
+    	helpTestExpression("xmlserialize(x as BLOB encoding \"UTF-8\" version '1.0' INCLUDING xmldeclaration)", "XMLSERIALIZE(x AS BLOB ENCODING \"UTF-8\" VERSION '1.0' INCLUDING XMLDECLARATION)", f);
+    }
+    
     @Test public void testExpressionCriteria() throws Exception {
     	SearchedCaseExpression sce = new SearchedCaseExpression(Arrays.asList(new ExpressionCriteria(new ElementSymbol("x"))), Arrays.asList(new ElementSymbol("y")));
     	helpTestExpression("case when x then y end", "CASE WHEN x THEN y END", sce);

Modified: trunk/engine/src/test/java/org/teiid/query/processor/TestSQLXMLProcessing.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/processor/TestSQLXMLProcessing.java	2012-08-23 18:14:04 UTC (rev 4363)
+++ trunk/engine/src/test/java/org/teiid/query/processor/TestSQLXMLProcessing.java	2012-08-24 19:54:48 UTC (rev 4364)
@@ -187,6 +187,69 @@
         process(sql, expected);
     }
     
+    @Test public void testXmlSerialize1() throws Exception {
+    	String sql = "SELECT xmlserialize(document xmlelement(parent) as string including xmldeclaration)"; //$NON-NLS-1$
+        
+        List<?>[] expected = new List<?>[] {
+        		Arrays.asList("<?xml version=\"1.0\" encoding=\"UTF-8\"?><parent></parent>"), 
+        };    
+    
+        process(sql, expected);
+    }
+    
+    @Test public void testXmlSerialize2() throws Exception {
+    	String sql = "SELECT xmlserialize(document xmlelement(parent) as string version '1.2' including xmldeclaration)"; //$NON-NLS-1$
+        
+        List<?>[] expected = new List<?>[] {
+        		Arrays.asList("<?xml version=\"1.2\" encoding=\"UTF-8\"?><parent></parent>"), 
+        };    
+    
+        process(sql, expected);
+    }
+    
+    @Test public void testXmlSerializeBinary() throws Exception {
+    	String sql = "SELECT xmlserialize(document xmlelement(parent) as varbinary version '1.2' including xmldeclaration)"; //$NON-NLS-1$
+        
+        List<?>[] expected = new List<?>[] {
+        		Arrays.asList(new BinaryType("<?xml version=\"1.2\" encoding=\"UTF-8\"?><parent></parent>".getBytes(Charset.forName("UTF-8")))), 
+        };    
+    
+        process(sql, expected);
+    }
+    
+    @Test public void testXmlSerializeBinary1() throws Exception {
+    	String sql = "SELECT xmlserialize(document xmlelement(parent) as varbinary encoding \"UTF-16\" version '1.2' including xmldeclaration)"; //$NON-NLS-1$
+        
+        List<?>[] expected = new List<?>[] {
+        		Arrays.asList(new BinaryType("<?xml version=\"1.2\" encoding=\"UTF-16\"?><parent></parent>".getBytes(Charset.forName("UTF-16")))), 
+        };    
+    
+        process(sql, expected);
+    }
+    
+    @Test public void testXmlSerializeBinary2() throws Exception {
+    	String sql = "SELECT cast(xmlserialize(document xmlelement(other) as blob encoding \"UTF-16\" version '1.2' including xmldeclaration) as varbinary)"; //$NON-NLS-1$
+        
+        List<?>[] expected = new List<?>[] {
+        		Arrays.asList(new BinaryType("<?xml version=\"1.2\" encoding=\"UTF-16\"?><other></other>".getBytes(Charset.forName("UTF-16")))), 
+        };    
+    
+        process(sql, expected);
+    }
+    
+    /**
+     * if not specifically excluding, then leave the declaration intact (pre-8.2 behavior)
+     */
+    @Test public void testXmlSerialize3() throws Exception {
+    	String sql = "SELECT xmlserialize(document xmlparse(document '<?xml version=\"1.1\" encoding=\"UTF-8\"?><a></a>') as string)"; //$NON-NLS-1$
+        
+        List<?>[] expected = new List<?>[] {
+        		Arrays.asList("<?xml version=\"1.1\" encoding=\"UTF-8\"?><a></a>"), 
+        };    
+    
+        process(sql, expected);
+    }
+    
     @Test public void testXmlTable() throws Exception {
         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$
         

Modified: trunk/engine/src/test/java/org/teiid/query/rewriter/TestQueryRewriter.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/rewriter/TestQueryRewriter.java	2012-08-23 18:14:04 UTC (rev 4363)
+++ trunk/engine/src/test/java/org/teiid/query/rewriter/TestQueryRewriter.java	2012-08-24 19:54:48 UTC (rev 4364)
@@ -1636,5 +1636,9 @@
     @Test public void testRewriteTrim1() throws Exception {
     	helpTestRewriteExpression("trim(leading from pm1.g1.e1)", "ltrim(pm1.g1.e1)", RealMetadataFactory.example1Cached());
     }
+    
+    @Test public void testRewriteXmlSerialize1() throws Exception {
+    	helpTestRewriteExpression("xmlserialize(DOCUMENT cast (pm1.g1.e1 as xml) as clob version '2.0')", "XMLSERIALIZE(DOCUMENT convert(pm1.g1.e1, xml) AS clob VERSION '2.0' INCLUDING XMLDECLARATION)", RealMetadataFactory.example1Cached());
+    }
 
 }

Modified: trunk/engine/src/test/java/org/teiid/query/validator/TestValidator.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/validator/TestValidator.java	2012-08-23 18:14:04 UTC (rev 4363)
+++ trunk/engine/src/test/java/org/teiid/query/validator/TestValidator.java	2012-08-24 19:54:48 UTC (rev 4364)
@@ -595,6 +595,19 @@
 
         helpRunValidator(command, new String[] {}, metadata);
     }
+    
+    @Test public void testXMLSerializeEncoding() {
+    	helpValidate("SELECT xmlserialize(? AS CLOB ENCODING \"UTF-8\")", new String[] {"XMLSERIALIZE(? AS CLOB ENCODING \"UTF-8\")"}, RealMetadataFactory.example1Cached()); //$NON-NLS-1$
+    }
+    
+    @Test public void testXMLSerializeEncoding1() {
+    	helpValidate("SELECT xmlserialize(? AS BLOB ENCODING \"UTF-8\" INCLUDING XMLDECLARATION)", new String[] {}, RealMetadataFactory.example1Cached()); //$NON-NLS-1$
+    }
+    
+    @Test public void testXMLSerializeEncoding2() {
+    	helpValidate("SELECT xmlserialize(? AS BLOB ENCODING \"UTF-75\" INCLUDING XMLDECLARATION)", new String[] {"XMLSERIALIZE(? AS BLOB ENCODING \"UTF-75\" INCLUDING XMLDECLARATION)"}, RealMetadataFactory.example1Cached()); //$NON-NLS-1$
+    }
+
     @Test public void testXMLQuery1() {
     	helpValidate("SELECT * FROM vm1.doc1", new String[] {}, exampleMetadata()); //$NON-NLS-1$
     }



More information about the teiid-commits mailing list