teiid SVN: r3244 - branches/7.4.x/connectors/translator-file/src/main/java/org/teiid/translator/file.
by teiid-commits@lists.jboss.org
Author: shawkins
Date: 2011-06-10 15:34:01 -0400 (Fri, 10 Jun 2011)
New Revision: 3244
Modified:
branches/7.4.x/connectors/translator-file/src/main/java/org/teiid/translator/file/FileExecutionFactory.java
Log:
TEIID-1634 adding debug messages to file operations
Modified: branches/7.4.x/connectors/translator-file/src/main/java/org/teiid/translator/file/FileExecutionFactory.java
===================================================================
--- branches/7.4.x/connectors/translator-file/src/main/java/org/teiid/translator/file/FileExecutionFactory.java 2011-06-10 19:23:01 UTC (rev 3243)
+++ branches/7.4.x/connectors/translator-file/src/main/java/org/teiid/translator/file/FileExecutionFactory.java 2011-06-10 19:34:01 UTC (rev 3244)
@@ -46,6 +46,8 @@
import org.teiid.core.util.ObjectConverterUtil;
import org.teiid.core.util.ReaderInputStream;
import org.teiid.language.Call;
+import org.teiid.logging.LogConstants;
+import org.teiid.logging.LogManager;
import org.teiid.metadata.MetadataFactory;
import org.teiid.metadata.Procedure;
import org.teiid.metadata.ProcedureParameter;
@@ -79,6 +81,7 @@
@Override
public void execute() throws TranslatorException {
files = FileConnection.Util.getFiles((String)command.getArguments().get(0).getArgumentValue().getValue(), fc);
+ LogManager.logDetail(LogConstants.CTX_CONNECTOR, "Getting", files != null ? files.length : 0, "file(s)"); //$NON-NLS-1$ //$NON-NLS-2$
String name = command.getProcedureName();
if (name.equalsIgnoreCase(GETTEXTFILES)) {
isText = true;
@@ -104,6 +107,7 @@
}
ArrayList<Object> result = new ArrayList<Object>(2);
final File file = files[index++];
+ LogManager.logDetail(LogConstants.CTX_CONNECTOR, "Getting", file); //$NON-NLS-1$
FileInputStreamFactory isf = new FileInputStreamFactory(file);
isf.setLength(file.length());
Object value = null;
@@ -156,6 +160,7 @@
if (file == null || filePath == null) {
throw new TranslatorException(UTIL.getString("non_null")); //$NON-NLS-1$
}
+ LogManager.logDetail(LogConstants.CTX_CONNECTOR, "Saving", filePath); //$NON-NLS-1$
InputStream is = null;
try {
if (file instanceof SQLXML) {
13 years, 7 months
teiid SVN: r3243 - in branches/7.1.1.CP2/connectors/sandbox: translator-teradata and 17 other directories.
by teiid-commits@lists.jboss.org
Author: rareddy
Date: 2011-06-10 15:23:01 -0400 (Fri, 10 Jun 2011)
New Revision: 3243
Added:
branches/7.1.1.CP2/connectors/sandbox/translator-teradata/
branches/7.1.1.CP2/connectors/sandbox/translator-teradata/pom.xml
branches/7.1.1.CP2/connectors/sandbox/translator-teradata/src/
branches/7.1.1.CP2/connectors/sandbox/translator-teradata/src/main/
branches/7.1.1.CP2/connectors/sandbox/translator-teradata/src/main/java/
branches/7.1.1.CP2/connectors/sandbox/translator-teradata/src/main/java/org/
branches/7.1.1.CP2/connectors/sandbox/translator-teradata/src/main/java/org/teiid/
branches/7.1.1.CP2/connectors/sandbox/translator-teradata/src/main/java/org/teiid/translator/
branches/7.1.1.CP2/connectors/sandbox/translator-teradata/src/main/java/org/teiid/translator/jdbc/
branches/7.1.1.CP2/connectors/sandbox/translator-teradata/src/main/java/org/teiid/translator/jdbc/teradata/
branches/7.1.1.CP2/connectors/sandbox/translator-teradata/src/main/java/org/teiid/translator/jdbc/teradata/TeradataExecutionFactory.java
branches/7.1.1.CP2/connectors/sandbox/translator-teradata/src/main/java/org/teiid/translator/jdbc/teradata/TeradataSQLConversionVisitor.java
branches/7.1.1.CP2/connectors/sandbox/translator-teradata/src/main/resources/
branches/7.1.1.CP2/connectors/sandbox/translator-teradata/src/main/resources/META-INF/
branches/7.1.1.CP2/connectors/sandbox/translator-teradata/src/main/resources/META-INF/jboss-beans.xml
branches/7.1.1.CP2/connectors/sandbox/translator-teradata/src/test/
branches/7.1.1.CP2/connectors/sandbox/translator-teradata/src/test/java/
branches/7.1.1.CP2/connectors/sandbox/translator-teradata/src/test/java/org/
branches/7.1.1.CP2/connectors/sandbox/translator-teradata/src/test/java/org/teiid/
branches/7.1.1.CP2/connectors/sandbox/translator-teradata/src/test/java/org/teiid/translator/
branches/7.1.1.CP2/connectors/sandbox/translator-teradata/src/test/java/org/teiid/translator/jdbc/
branches/7.1.1.CP2/connectors/sandbox/translator-teradata/src/test/java/org/teiid/translator/jdbc/teradata/
branches/7.1.1.CP2/connectors/sandbox/translator-teradata/src/test/java/org/teiid/translator/jdbc/teradata/TestTeradataTranslator.java
Modified:
branches/7.1.1.CP2/connectors/sandbox/pom.xml
Log:
SOA-3103
Modified: branches/7.1.1.CP2/connectors/sandbox/pom.xml
===================================================================
--- branches/7.1.1.CP2/connectors/sandbox/pom.xml 2011-06-10 17:50:13 UTC (rev 3242)
+++ branches/7.1.1.CP2/connectors/sandbox/pom.xml 2011-06-10 19:23:01 UTC (rev 3243)
@@ -13,5 +13,6 @@
<description>Experimental connectors in progress</description>
<modules>
<module>translator-yahoo</module>
+ <module>translator-teradata</module>
</modules>
</project>
Added: branches/7.1.1.CP2/connectors/sandbox/translator-teradata/pom.xml
===================================================================
--- branches/7.1.1.CP2/connectors/sandbox/translator-teradata/pom.xml (rev 0)
+++ branches/7.1.1.CP2/connectors/sandbox/translator-teradata/pom.xml 2011-06-10 19:23:01 UTC (rev 3243)
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <parent>
+ <artifactId>sandbox</artifactId>
+ <groupId>org.jboss.teiid.connectors</groupId>
+ <version>7.1.1.GA</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>translator-teradata</artifactId>
+ <groupId>org.jboss.teiid.connectors.sandbox</groupId>
+ <name>Teradata Translator</name>
+ <description>Teradata Translator</description>
+ <dependencies>
+ <dependency>
+ <groupId>org.jboss.teiid</groupId>
+ <artifactId>teiid-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.teiid</groupId>
+ <artifactId>teiid-common-core</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.teiid.connectors</groupId>
+ <artifactId>translator-jdbc</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.teiid.connectors</groupId>
+ <artifactId>translator-jdbc</artifactId>
+ <version>${project.version}</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.resource</groupId>
+ <artifactId>connector-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <outputDirectory>target/classes</outputDirectory>
+ <resources>
+ <resource>
+ <directory>src/main/resources</directory>
+ <filtering>true</filtering>
+ <includes>
+ <include>**/*.xml</include>
+ <include>**/*.properties</include>
+ </includes>
+ </resource>
+ <resource>
+ <directory>src/main/resources</directory>
+ <filtering>false</filtering>
+ <excludes>
+ <exclude>**/*.xml</exclude>
+ <exclude>**/*.properties</exclude>
+ </excludes>
+ </resource>
+ </resources>
+ </build>
+</project>
Added: branches/7.1.1.CP2/connectors/sandbox/translator-teradata/src/main/java/org/teiid/translator/jdbc/teradata/TeradataExecutionFactory.java
===================================================================
--- branches/7.1.1.CP2/connectors/sandbox/translator-teradata/src/main/java/org/teiid/translator/jdbc/teradata/TeradataExecutionFactory.java (rev 0)
+++ branches/7.1.1.CP2/connectors/sandbox/translator-teradata/src/main/java/org/teiid/translator/jdbc/teradata/TeradataExecutionFactory.java 2011-06-10 19:23:01 UTC (rev 3243)
@@ -0,0 +1,472 @@
+/*
+ * 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.translator.jdbc.teradata;
+
+import static org.teiid.translator.TypeFacility.RUNTIME_NAMES.*;
+
+import java.sql.Date;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.teiid.language.ColumnReference;
+import org.teiid.language.Expression;
+import org.teiid.language.Function;
+import org.teiid.language.LanguageFactory;
+import org.teiid.language.Literal;
+import org.teiid.translator.SourceSystemFunctions;
+import org.teiid.translator.Translator;
+import org.teiid.translator.TranslatorException;
+import org.teiid.translator.TypeFacility;
+import org.teiid.translator.jdbc.AliasModifier;
+import org.teiid.translator.jdbc.ConvertModifier;
+import org.teiid.translator.jdbc.FunctionModifier;
+import org.teiid.translator.jdbc.JDBCExecutionFactory;
+import org.teiid.translator.jdbc.SQLConversionVisitor;
+
+
+
+/**
+ * Teradata database Release 12
+ */
+@Translator(name="teradata", description="A translator for Teradata Database")
+public class TeradataExecutionFactory extends JDBCExecutionFactory {
+
+ public static String TERADATA = "teradata"; //$NON-NLS-1$
+ protected ConvertModifier convert = new ConvertModifier();
+
+ public TeradataExecutionFactory() {
+ setSupportsOuterJoins(false);
+ }
+
+ @Override
+ public void start() throws TranslatorException {
+ super.start();
+ convert.addTypeMapping("byteint", FunctionModifier.BYTE, FunctionModifier.SHORT, FunctionModifier.BOOLEAN); //$NON-NLS-1$
+ convert.addTypeMapping("double precision", FunctionModifier.DOUBLE); //$NON-NLS-1$
+ convert.addTypeMapping("numeric(18,0)", FunctionModifier.BIGINTEGER); //$NON-NLS-1$
+ convert.addTypeMapping("char(1)", FunctionModifier.CHAR); //$NON-NLS-1$
+
+ convert.addConvert(FunctionModifier.TIMESTAMP, FunctionModifier.TIME, new CastModifier("TIME")); //$NON-NLS-1$
+ convert.addConvert(FunctionModifier.TIMESTAMP, FunctionModifier.DATE, new CastModifier("DATE")); //$NON-NLS-1$
+ convert.addConvert(FunctionModifier.TIME, FunctionModifier.TIMESTAMP, new CastModifier("TIMESTAMP")); //$NON-NLS-1$
+ convert.addConvert(FunctionModifier.DATE, FunctionModifier.TIMESTAMP, new CastModifier("TIMESTAMP")); //$NON-NLS-1$
+
+ convert.addConvert(FunctionModifier.STRING, FunctionModifier.INTEGER, new CastModifier("integer")); //$NON-NLS-1$
+ convert.addConvert(FunctionModifier.STRING, FunctionModifier.BIGDECIMAL, new CastModifier("decimal(37,5)"));//$NON-NLS-1$
+ convert.addConvert(FunctionModifier.STRING, FunctionModifier.BIGINTEGER, new CastModifier("numeric(18,0)"));//$NON-NLS-1$
+ convert.addConvert(FunctionModifier.STRING, FunctionModifier.FLOAT, new CastModifier("float"));//$NON-NLS-1$
+ convert.addConvert(FunctionModifier.STRING, FunctionModifier.BOOLEAN, new CastModifier("byteint"));//$NON-NLS-1$
+ convert.addConvert(FunctionModifier.STRING, FunctionModifier.LONG, new CastModifier("numeric(18,0)"));//$NON-NLS-1$
+ convert.addConvert(FunctionModifier.STRING, FunctionModifier.SHORT, new CastModifier("smallint"));//$NON-NLS-1$
+ convert.addConvert(FunctionModifier.STRING, FunctionModifier.DOUBLE, new CastModifier("double precision"));//$NON-NLS-1$
+ convert.addConvert(FunctionModifier.STRING, FunctionModifier.BYTE, new CastModifier("byteint")); //$NON-NLS-1$
+
+ convert.addConvert(FunctionModifier.TIMESTAMP, FunctionModifier.STRING, new FunctionModifier() {
+ @Override
+ public List<?> translate(Function function) {
+ return Arrays.asList("cast(cast(", function.getParameters().get(0), " AS FORMAT 'Y4-MM-DDBHH:MI:SSDS(6)') AS VARCHAR(26))"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ });
+ convert.addConvert(FunctionModifier.TIME, FunctionModifier.STRING, new FunctionModifier() {
+ @Override
+ public List<?> translate(Function function) {
+ return Arrays.asList("cast(cast(", function.getParameters().get(0), " AS FORMAT 'HH:MI:SS') AS VARCHAR(9))"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ });
+ convert.addConvert(FunctionModifier.DATE, FunctionModifier.STRING, new FunctionModifier() {
+ @Override
+ public List<?> translate(Function function) {
+ return Arrays.asList("cast(cast(", function.getParameters().get(0), " AS FORMAT 'YYYY-MM-DD') AS VARCHAR(11))"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ });
+
+ convert.addTypeMapping("varchar(4000)", FunctionModifier.STRING); //$NON-NLS-1$
+ convert.addNumericBooleanConversions();
+
+ registerFunctionModifier(SourceSystemFunctions.CONVERT, convert);
+ registerFunctionModifier(SourceSystemFunctions.SUBSTRING, new SubstrModifier(this.convert));
+ registerFunctionModifier(SourceSystemFunctions.RAND, new AliasModifier("random")); //$NON-NLS-1$
+ registerFunctionModifier(SourceSystemFunctions.LOG, new AliasModifier("LN")); //$NON-NLS-1$
+ registerFunctionModifier(SourceSystemFunctions.LCASE, new StringOnlyModifier("LOWER", this.convert)); //$NON-NLS-1$
+ registerFunctionModifier(SourceSystemFunctions.UCASE, new StringOnlyModifier("UPPER", this.convert)); //$NON-NLS-1$
+ registerFunctionModifier(SourceSystemFunctions.LENGTH, new FunctionModifier() {
+ @Override
+ public List<?> translate(Function function) {
+ ArrayList target = new ArrayList();
+ target.add("character_length("); //$NON-NLS-1$
+ target.addAll(expressionToString(function.getParameters().get(0), convert));
+ target.add(")"); //$NON-NLS-1$
+ return target;
+ }
+ });
+ registerFunctionModifier(SourceSystemFunctions.CURDATE, new AliasModifier("CURRENT_DATE")); //$NON-NLS-1$
+ registerFunctionModifier(SourceSystemFunctions.CURTIME, new AliasModifier("CURRENT_TIME")); //$NON-NLS-1$
+ registerFunctionModifier(SourceSystemFunctions.YEAR, new ExtractModifier("YEAR")); //$NON-NLS-1$
+ registerFunctionModifier(SourceSystemFunctions.MONTH, new ExtractModifier("MONTH")); //$NON-NLS-1$
+ registerFunctionModifier(SourceSystemFunctions.DAYOFMONTH, new ExtractModifier("DAY")); //$NON-NLS-1$
+ registerFunctionModifier(SourceSystemFunctions.HOUR, new ExtractModifier("HOUR")); //$NON-NLS-1$
+ registerFunctionModifier(SourceSystemFunctions.MINUTE, new ExtractModifier("MINUTE")); //$NON-NLS-1$
+ registerFunctionModifier(SourceSystemFunctions.SECOND, new ExtractModifier("SECOND")); //$NON-NLS-1$
+ registerFunctionModifier(SourceSystemFunctions.LOCATE, new LocateModifier(this.convert));
+ registerFunctionModifier(SourceSystemFunctions.LEFT, new LeftOrRightFunctionModifier(getLanguageFactory(), this.convert));
+ registerFunctionModifier(SourceSystemFunctions.RIGHT, new LeftOrRightFunctionModifier(getLanguageFactory(), this.convert));
+ registerFunctionModifier(SourceSystemFunctions.COT, new FunctionModifier() {
+ @Override
+ public List<?> translate(Function function) {
+ function.setName(SourceSystemFunctions.TAN);
+ return Arrays.asList(getLanguageFactory().createFunction(SourceSystemFunctions.DIVIDE_OP, new Expression[] {new Literal(1, TypeFacility.RUNTIME_TYPES.INTEGER), function}, TypeFacility.RUNTIME_TYPES.DOUBLE));
+ }
+ });
+ registerFunctionModifier(SourceSystemFunctions.LTRIM, new FunctionModifier() {
+ @Override
+ public List<?> translate(Function function) {
+ ArrayList target = new ArrayList();
+ target.add("TRIM(LEADING FROM ");//$NON-NLS-1$
+ target.addAll(expressionToString(function.getParameters().get(0), convert));
+ target.add(")"); //$NON-NLS-1$
+ return target;
+ }
+ });
+ registerFunctionModifier(SourceSystemFunctions.RTRIM, new FunctionModifier() {
+ @Override
+ public List<?> translate(Function function) {
+ ArrayList target = new ArrayList();
+ target.add("TRIM(TRAILING FROM ");//$NON-NLS-1$
+ target.addAll(expressionToString(function.getParameters().get(0), convert));
+ target.add(")"); //$NON-NLS-1$
+ return target;
+ }
+ });
+ registerFunctionModifier(SourceSystemFunctions.MOD, new FunctionModifier() {
+ @Override
+ public List<?> translate(Function function) {
+ return Arrays.asList(function.getParameters().get(0), " MOD ", function.getParameters().get(1)); //$NON-NLS-1$
+ }
+ });
+
+ /* Push down support only available from 7.4
+ addPushDownFunction(TERADATA, "COSH", FLOAT, FLOAT); //$NON-NLS-1$
+ addPushDownFunction(TERADATA, "TANH", FLOAT, FLOAT); //$NON-NLS-1$
+ addPushDownFunction(TERADATA, "ACOSH", FLOAT, FLOAT); //$NON-NLS-1$
+ addPushDownFunction(TERADATA, "ASINH", FLOAT, FLOAT); //$NON-NLS-1$
+ addPushDownFunction(TERADATA, "ATANH", FLOAT, FLOAT); //$NON-NLS-1$
+ addPushDownFunction(TERADATA, "CHAR2HEXINT", STRING, STRING); //$NON-NLS-1$
+ addPushDownFunction(TERADATA, "INDEX", INTEGER, STRING, STRING); //$NON-NLS-1$
+ addPushDownFunction(TERADATA, "BYTES", INTEGER, STRING); //$NON-NLS-1$
+ addPushDownFunction(TERADATA, "OCTET_LENGTH", INTEGER, STRING); //$NON-NLS-1$
+ addPushDownFunction(TERADATA, "HASHAMP", INTEGER, STRING); //$NON-NLS-1$
+ addPushDownFunction(TERADATA, "HASHBAKAMP", INTEGER, STRING); //$NON-NLS-1$
+ addPushDownFunction(TERADATA, "HASHBUCKET", INTEGER, STRING); //$NON-NLS-1$
+ addPushDownFunction(TERADATA, "HASHROW", INTEGER, STRING); //$NON-NLS-1$
+ addPushDownFunction(TERADATA, "NULLIFZERO", BIG_DECIMAL, BIG_DECIMAL); //$NON-NLS-1$
+ addPushDownFunction(TERADATA, "ZEROIFNULL", BIG_DECIMAL, BIG_DECIMAL); //$NON-NLS-1$
+ */
+ }
+
+ @Override
+ public SQLConversionVisitor getSQLConversionVisitor() {
+ return new TeradataSQLConversionVisitor(this);
+ }
+
+
+ @Override
+ public List getSupportedFunctions() {
+ List<String> supportedFunctions = new ArrayList<String>();
+ supportedFunctions.addAll(super.getSupportedFunctions());
+
+ supportedFunctions.add(SourceSystemFunctions.ABS);
+ supportedFunctions.add(SourceSystemFunctions.ACOS);
+ supportedFunctions.add(SourceSystemFunctions.ASIN);
+ supportedFunctions.add(SourceSystemFunctions.ATAN);
+ supportedFunctions.add(SourceSystemFunctions.ATAN2);
+ supportedFunctions.add(SourceSystemFunctions.COALESCE);
+ supportedFunctions.add(SourceSystemFunctions.COS);
+ supportedFunctions.add(SourceSystemFunctions.COT);
+ supportedFunctions.add(SourceSystemFunctions.CONVERT);
+ supportedFunctions.add(SourceSystemFunctions.CURDATE);
+ supportedFunctions.add(SourceSystemFunctions.CURTIME);
+ supportedFunctions.add(SourceSystemFunctions.DAYOFMONTH);
+ supportedFunctions.add(SourceSystemFunctions.EXP);
+ supportedFunctions.add(SourceSystemFunctions.HOUR);
+ supportedFunctions.add(SourceSystemFunctions.LEFT);
+ supportedFunctions.add(SourceSystemFunctions.LOCATE);
+ supportedFunctions.add(SourceSystemFunctions.LOG);
+ supportedFunctions.add(SourceSystemFunctions.LCASE);
+ supportedFunctions.add(SourceSystemFunctions.LTRIM);
+ supportedFunctions.add(SourceSystemFunctions.LENGTH);
+ supportedFunctions.add(SourceSystemFunctions.MINUTE);
+ supportedFunctions.add(SourceSystemFunctions.MOD);
+ supportedFunctions.add(SourceSystemFunctions.MONTH);
+ supportedFunctions.add(SourceSystemFunctions.NULLIF);
+ supportedFunctions.add(SourceSystemFunctions.RAND);
+ supportedFunctions.add(SourceSystemFunctions.RIGHT);
+ supportedFunctions.add(SourceSystemFunctions.RTRIM);
+ supportedFunctions.add(SourceSystemFunctions.SECOND);
+ supportedFunctions.add(SourceSystemFunctions.SIN);
+ supportedFunctions.add(SourceSystemFunctions.SQRT);
+ supportedFunctions.add(SourceSystemFunctions.SUBSTRING);
+ supportedFunctions.add(SourceSystemFunctions.TAN);
+ supportedFunctions.add(SourceSystemFunctions.UCASE);
+ supportedFunctions.add(SourceSystemFunctions.YEAR);
+
+ return supportedFunctions;
+ }
+
+ @Override
+ public String translateLiteralDate(Date dateValue) {
+ return "cast('" + formatDateValue(dateValue) + "' AS DATE FORMAT 'yyyy-mm-dd')"; //$NON-NLS-1$//$NON-NLS-2$
+ }
+
+ @Override
+ public String translateLiteralTime(Time timeValue) {
+ return "cast('" + formatDateValue(timeValue) + "' AS TIME(0) FORMAT 'hh:mi:ss')"; //$NON-NLS-1$//$NON-NLS-2$
+ }
+
+ @Override
+ public String translateLiteralTimestamp(Timestamp timestampValue) {
+ return "cast('" + formatDateValue(timestampValue) + "' AS TIMESTAMP(6))"; //$NON-NLS-1$//$NON-NLS-2$
+ }
+
+ // Teradata also supports MINUS & ALL set operators
+ // more aggregates available
+
+ @Override
+ public boolean supportsScalarSubqueries() {
+ return false;
+ }
+
+ @Override
+ public boolean supportsUnions() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsIntersect() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsExcept() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsInlineViews() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsAggregatesEnhancedNumeric() {
+ return true;
+ }
+
+ /* only in 7.4
+ @Override
+ public boolean supportsCommonTableExpressions() {
+ return false;
+ }
+ */
+
+ @Override
+ public NullOrder getDefaultNullOrder() {
+ return NullOrder.FIRST;
+ }
+
+ @Override
+ public boolean supportsSetQueryOrderBy() {
+ return false;
+ }
+
+ public static class LocateModifier extends FunctionModifier {
+ ConvertModifier convertModifier;
+
+ public LocateModifier(ConvertModifier convertModifier) {
+ this.convertModifier = convertModifier;
+ }
+
+ @Override
+ public List<?> translate(Function function) {
+ ArrayList target = new ArrayList();
+ Expression expr1 = function.getParameters().get(0);
+ Expression expr2 = function.getParameters().get(1);
+ if (function.getParameters().size() > 2) {
+ Expression expr3 = function.getParameters().get(2);
+ target.add("position("); //$NON-NLS-1$
+ target.addAll(expressionToString(expr1, this.convertModifier));
+ target.add( " in "); //$NON-NLS-1$
+ target.add("substr("); //$NON-NLS-1$
+ target.addAll(expressionToString(expr2, this.convertModifier));
+ target.add(","); //$NON-NLS-1$
+ target.add(expr3);
+ target.add("))"); //$NON-NLS-1$
+ }
+ else {
+ target.add("position("); //$NON-NLS-1$
+ target.addAll(expressionToString(expr1, this.convertModifier));
+ target.add( " in "); //$NON-NLS-1$
+ target.addAll(expressionToString(expr2, this.convertModifier));
+ target.add(")"); //$NON-NLS-1$
+ }
+ return target;
+ }
+ }
+
+ private static List<?> expressionToString(Expression expr, ConvertModifier modifier) {
+ Class tgtType = expr.getType();
+ if (tgtType.equals(String.class) && ((expr instanceof Literal) || expr instanceof ColumnReference)) {
+ return Arrays.asList(expr);
+ }
+ else if (tgtType.equals(String.class) && (expr instanceof Function)) {
+
+ Function func = (Function)expr;
+ while(true) {
+ Expression arg1 = func.getParameters().get(0);
+ if ((arg1 instanceof Function) && ((Function)arg1).getName().equals("convert")) { //$NON-NLS-1$
+ func = (Function)arg1;
+ }
+ else {
+ break;
+ }
+ }
+ Expression arg1 = func.getParameters().get(0);
+ if (arg1 instanceof ColumnReference) {
+ ColumnReference ref = (ColumnReference)func.getParameters().get(0);
+ if(Number.class.isAssignableFrom(ref.getType())) {
+ ArrayList target = new ArrayList();
+ target.add("cast("); //$NON-NLS-1$
+ target.add(func.getParameters().get(0));
+ target.add(" AS varchar(100))"); //$NON-NLS-1$
+ return target;
+ }
+ else if (String.class.isAssignableFrom(ref.getType())) {
+ return Arrays.asList(ref);
+ }
+ }
+ return modifier.translate(func);
+ }
+ return Arrays.asList("cast(" , expr, " AS varchar(100))"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ public static class ExtractModifier extends FunctionModifier {
+ private String type;
+ public ExtractModifier(String type) {
+ this.type = type;
+ }
+ @Override
+ public List<?> translate(Function function) {
+ return Arrays.asList("extract(",this.type," from ",function.getParameters().get(0) ,")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ }
+ }
+
+ public static class CastModifier extends FunctionModifier {
+ private String target;
+ public CastModifier(String target) {
+ this.target = target;
+ }
+ @Override
+ public List<?> translate(Function function) {
+ return Arrays.asList("cast(", function.getParameters().get(0), " AS "+this.target+")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ }
+ }
+
+ public static class StringOnlyModifier extends FunctionModifier {
+ String funcName;
+ ConvertModifier convertModifier;
+ public StringOnlyModifier(String name, ConvertModifier converModifier) {
+ this.funcName = name;
+ this.convertModifier = converModifier;
+ }
+ @Override
+ public List<?> translate(Function function) {
+ Expression expr = function.getParameters().get(0);
+ ArrayList target = new ArrayList();
+ target.add(this.funcName);
+ target.add("("); //$NON-NLS-1$
+ target.addAll(expressionToString(expr, this.convertModifier));
+ target.add(")"); //$NON-NLS-1$
+ return target;
+ }
+ }
+
+ public static class SubstrModifier extends FunctionModifier {
+ ConvertModifier convertModifier;
+ public SubstrModifier(ConvertModifier converModifier) {
+ this.convertModifier = converModifier;
+ }
+ @Override
+ public List<?> translate(Function function) {
+ Expression expr = function.getParameters().get(0);
+ ArrayList target = new ArrayList();
+ target.add("substr("); //$NON-NLS-1$
+ target.addAll(expressionToString(expr, this.convertModifier));
+ target.add(","); //$NON-NLS-1$
+ target.add(function.getParameters().get(1));
+ if (function.getParameters().size() > 2 ) {
+ target.add(","); //$NON-NLS-1$
+ target.add(function.getParameters().get(2));
+ }
+ target.add(")"); //$NON-NLS-1$
+ return target;
+ }
+ }
+
+ public static class LeftOrRightFunctionModifier extends FunctionModifier {
+ private LanguageFactory langFactory;
+ ConvertModifier convertModifier;
+
+ public LeftOrRightFunctionModifier(LanguageFactory langFactory, ConvertModifier converModifier) {
+ this.langFactory = langFactory;
+ this.convertModifier = converModifier;
+ }
+
+ @Override
+ public List<?> translate(Function function) {
+ List<Expression> args = function.getParameters();
+ ArrayList target = new ArrayList();
+ if (function.getName().equalsIgnoreCase("left")) { //$NON-NLS-1$
+ //substr(string, 1, length)
+ target.add("substr("); //$NON-NLS-1$
+ target.addAll(expressionToString(args.get(0), this.convertModifier));
+ target.add(","); //$NON-NLS-1$
+ target.add(langFactory.createLiteral(Integer.valueOf(1), TypeFacility.RUNTIME_TYPES.INTEGER));
+ target.add(","); //$NON-NLS-1$
+ target.add(args.get(1));
+ target.add(")"); //$NON-NLS-1$
+ } else if (function.getName().equalsIgnoreCase("right")) { //$NON-NLS-1$
+ //substr(case_size, character_length(case_size) -4)
+ target.add("substr("); //$NON-NLS-1$
+ target.addAll(expressionToString(args.get(0), this.convertModifier));
+
+ target.add(",(character_length("); //$NON-NLS-1$
+ target.addAll(expressionToString(args.get(0), this.convertModifier));
+ target.add(")-"); //$NON-NLS-1$
+ target.add(args.get(1));
+ target.add("+1))"); //$NON-NLS-1$ // offset for 1 based index
+ }
+ return target;
+ }
+ }
+}
Added: branches/7.1.1.CP2/connectors/sandbox/translator-teradata/src/main/java/org/teiid/translator/jdbc/teradata/TeradataSQLConversionVisitor.java
===================================================================
--- branches/7.1.1.CP2/connectors/sandbox/translator-teradata/src/main/java/org/teiid/translator/jdbc/teradata/TeradataSQLConversionVisitor.java (rev 0)
+++ branches/7.1.1.CP2/connectors/sandbox/translator-teradata/src/main/java/org/teiid/translator/jdbc/teradata/TeradataSQLConversionVisitor.java 2011-06-10 19:23:01 UTC (rev 3243)
@@ -0,0 +1,72 @@
+/*
+ * 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.translator.jdbc.teradata;
+
+import java.util.List;
+
+import org.teiid.language.AndOr;
+import org.teiid.language.Comparison;
+import org.teiid.language.Condition;
+import org.teiid.language.Expression;
+import org.teiid.language.In;
+import org.teiid.language.LanguageFactory;
+import org.teiid.language.AndOr.Operator;
+import org.teiid.translator.jdbc.SQLConversionVisitor;
+
+public class TeradataSQLConversionVisitor extends SQLConversionVisitor {
+
+ public TeradataSQLConversionVisitor(TeradataExecutionFactory ef) {
+ super(ef);
+ }
+
+ @Override
+ public void visit(In obj) {
+ List<Expression> exprs = obj.getRightExpressions();
+
+ Class expectedType = obj.getLeftExpression().getType();
+
+ boolean decompose = false;
+ for (Expression expr:exprs) {
+ if (!(expr.getType().equals(expectedType)) || (!(expr.getType().isAssignableFrom(Number.class)) && !expr.getType().isAssignableFrom(String.class))) {
+ decompose = true;
+ }
+ }
+
+ if (decompose) {
+ Comparison.Operator opCode = obj.isNegated()?Comparison.Operator.NE:Comparison.Operator.EQ;
+ if (exprs.size() > 1) {
+ Condition left = LanguageFactory.INSTANCE.createCompareCriteria(opCode, obj.getLeftExpression(), exprs.get(0));
+ for (int i = 1; i < exprs.size(); i++) {
+ AndOr replace = LanguageFactory.INSTANCE.createAndOr(obj.isNegated()?Operator.AND:Operator.OR, left, LanguageFactory.INSTANCE.createCompareCriteria(opCode, obj.getLeftExpression(), exprs.get(i)));
+ left = replace;
+ }
+ super.visit((AndOr)left);
+ }
+ else {
+ super.visit(LanguageFactory.INSTANCE.createCompareCriteria(opCode, obj.getLeftExpression(), exprs.get(0)));
+ }
+ }
+ else {
+ super.visit(obj);
+ }
+ }
+}
Added: branches/7.1.1.CP2/connectors/sandbox/translator-teradata/src/main/resources/META-INF/jboss-beans.xml
===================================================================
--- branches/7.1.1.CP2/connectors/sandbox/translator-teradata/src/main/resources/META-INF/jboss-beans.xml (rev 0)
+++ branches/7.1.1.CP2/connectors/sandbox/translator-teradata/src/main/resources/META-INF/jboss-beans.xml 2011-06-10 19:23:01 UTC (rev 3243)
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<deployment xmlns="urn:jboss:bean-deployer:2.0">
+ <!-- TERADATA -->
+ <bean name="translator-teradata-template" class="org.teiid.templates.TranslatorDeploymentTemplate">
+ <property name="info"><inject bean="translator-teradata" /> </property>
+ <property name="managedObjectFactory"> <inject bean="ManagedObjectFactory" /> </property>
+ </bean>
+
+ <bean name="translator-teradata" class="org.teiid.templates.TranslatorTemplateInfo">
+ <constructor factoryMethod="createTemplateInfo">
+ <factory bean="TranslatorDeploymentTemplateInfoFactory" />
+ <parameter class="java.lang.Class">org.teiid.templates.TranslatorTemplateInfo</parameter>
+ <parameter class="java.lang.Class">org.teiid.translator.jdbc.teradata.TeradataExecutionFactory</parameter>
+ <parameter class="java.lang.String">translator-teradata</parameter>
+ <parameter class="java.lang.String">teradata</parameter>
+ </constructor>
+ </bean>
+</deployment>
Added: branches/7.1.1.CP2/connectors/sandbox/translator-teradata/src/test/java/org/teiid/translator/jdbc/teradata/TestTeradataTranslator.java
===================================================================
--- branches/7.1.1.CP2/connectors/sandbox/translator-teradata/src/test/java/org/teiid/translator/jdbc/teradata/TestTeradataTranslator.java (rev 0)
+++ branches/7.1.1.CP2/connectors/sandbox/translator-teradata/src/test/java/org/teiid/translator/jdbc/teradata/TestTeradataTranslator.java 2011-06-10 19:23:01 UTC (rev 3243)
@@ -0,0 +1,207 @@
+/*
+ * 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.translator.jdbc.teradata;
+
+import static org.junit.Assert.assertEquals;
+
+import java.sql.Date;
+import java.sql.Timestamp;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.teiid.language.Expression;
+import org.teiid.language.Function;
+import org.teiid.language.In;
+import org.teiid.language.LanguageFactory;
+import org.teiid.query.unittest.TimestampUtil;
+import org.teiid.translator.TranslatorException;
+import org.teiid.translator.TypeFacility;
+import org.teiid.translator.jdbc.SQLConversionVisitor;
+import org.teiid.translator.jdbc.TranslationHelper;
+
+@SuppressWarnings("nls")
+public class TestTeradataTranslator {
+
+ private static TeradataExecutionFactory TRANSLATOR;
+ private static final LanguageFactory LANG_FACTORY = new LanguageFactory();
+
+ @BeforeClass
+ public static void setUp() throws TranslatorException {
+ TRANSLATOR = new TeradataExecutionFactory();
+ TRANSLATOR.setUseBindVariables(false);
+ TRANSLATOR.start();
+ }
+
+ public void helpTest(Expression srcExpression, String tgtType, String expectedExpression) throws Exception {
+ Function func = LANG_FACTORY.createFunction("convert",
+ Arrays.asList( srcExpression,LANG_FACTORY.createLiteral(tgtType, String.class)),TypeFacility.getDataTypeClass(tgtType));
+
+ assertEquals("Error converting from " + srcExpression.getType() + " to " + tgtType,
+ expectedExpression, helpGetString(func));
+ }
+
+ public String helpGetString(Expression expr) throws Exception {
+ SQLConversionVisitor sqlVisitor = TRANSLATOR.getSQLConversionVisitor();
+ sqlVisitor.append(expr);
+
+ return sqlVisitor.toString();
+ }
+
+ @Test public void testSubstring1() throws Exception {
+ String input = "SELECT dayofmonth(datevalue) FROM BQT1.SMALLA";
+ String output = "SELECT extract(DAY from SmallA.DateValue) FROM SmallA";
+
+ TranslationHelper.helpTestVisitor(TranslationHelper.BQT_VDB, input, output, TRANSLATOR);
+ }
+
+ @Test public void testTimestampToTime() throws Exception {
+ helpTest(LANG_FACTORY.createLiteral(TimestampUtil.createTimestamp(111, 4, 5, 9, 16, 34, 220000000), Timestamp.class), "time", "cast(cast('2011-05-05 09:16:34.22' AS TIMESTAMP(6)) AS TIME)");
+ }
+
+ @Test public void testIntegerToString() throws Exception {
+ String input = "SELECT lcase(bigdecimalvalue) FROM BQT1.SMALLA";
+ String output = "SELECT LOWER(cast(SmallA.BigDecimalValue AS varchar(100))) FROM SmallA";
+ TranslationHelper.helpTestVisitor(TranslationHelper.BQT_VDB, input, output, TRANSLATOR);
+ }
+
+ @Test public void testSubString() throws Exception {
+ String input = "SELECT intkey FROM BQT1.SmallA WHERE SUBSTRING(BQT1.SmallA.IntKey, 1) = '1' ORDER BY intkey";
+ String output = "SELECT SmallA.IntKey FROM SmallA WHERE substr(cast(SmallA.IntKey AS varchar(100)),1) = '1' ORDER BY SmallA.IntKey";
+ TranslationHelper.helpTestVisitor(TranslationHelper.BQT_VDB, input, output, TRANSLATOR);
+ }
+
+ @Test public void testSubString2() throws Exception {
+ String input = "SELECT intkey FROM BQT1.SmallA WHERE SUBSTRING(BQT1.SmallA.IntKey, 1, 2) = '1' ORDER BY intkey";
+ String output = "SELECT SmallA.IntKey FROM SmallA WHERE substr(cast(SmallA.IntKey AS varchar(100)),1,2) = '1' ORDER BY SmallA.IntKey";
+ TranslationHelper.helpTestVisitor(TranslationHelper.BQT_VDB, input, output, TRANSLATOR);
+ }
+
+ @Test public void testDateToString() throws Exception {
+ String input = "SELECT intkey, UPPER(timevalue) AS UPPER FROM BQT1.SmallA ORDER BY intkey";
+ String output = "SELECT SmallA.IntKey, UPPER(cast(cast(SmallA.TimeValue AS FORMAT 'HH:MI:SS') AS VARCHAR(9))) AS UPPER FROM SmallA ORDER BY SmallA.IntKey";
+ TranslationHelper.helpTestVisitor(TranslationHelper.BQT_VDB, input, output, TRANSLATOR);
+ }
+
+ @Test public void testLocate() throws Exception {
+ String input = "SELECT INTKEY, BIGDECIMALVALUE FROM BQT1.SmallA WHERE LOCATE('-', BIGDECIMALVALUE) = 1 ORDER BY intkey";
+ String output = "SELECT SmallA.IntKey, SmallA.BigDecimalValue FROM SmallA WHERE position('-' in cast(SmallA.BigDecimalValue AS varchar(100))) = 1 ORDER BY SmallA.IntKey";
+ TranslationHelper.helpTestVisitor(TranslationHelper.BQT_VDB, input, output, TRANSLATOR);
+ }
+
+
+ @Test public void testByteToString() throws Exception {
+ helpTest(LANG_FACTORY.createLiteral(new Byte((byte)1), Byte.class), "string", "cast(1 AS varchar(4000))");
+ }
+
+ @Test public void testByte2ToString() throws Exception {
+ helpTest(LANG_FACTORY.createLiteral(new Byte((byte)-1), Byte.class), "string", "cast(-1 AS varchar(4000))");
+ }
+
+ @Test public void testDoubleToString() throws Exception {
+ helpTest(LANG_FACTORY.createLiteral(new Double(1.0), Double.class), "string", "cast(1.0 AS varchar(4000))");
+ }
+
+ @Test public void testStringToDouble() throws Exception {
+ helpTest(LANG_FACTORY.createLiteral("1.0", String.class), "double", "cast('1.0' AS double precision)");
+ }
+
+ @Test public void testInDecompose() throws Exception {
+ Expression left = LANG_FACTORY.createLiteral("1", String.class);
+ List<Expression> right = new ArrayList<Expression>();
+ right.add(LANG_FACTORY.createLiteral("2", String.class));
+ right.add(LANG_FACTORY.createLiteral("3", String.class));
+
+ In expr = LANG_FACTORY.createIn(left,right, false);
+
+ assertEquals("'1' IN ('2', '3')", helpGetString(expr));
+ }
+
+ @Test public void testSingleInDecompose() throws Exception {
+ Expression left = LANG_FACTORY.createLiteral("1", String.class);
+ List<Expression> right = new ArrayList<Expression>();
+ right.add(LANG_FACTORY.createLiteral("2", String.class));
+
+ In expr = LANG_FACTORY.createIn(left,right, false);
+
+ assertEquals("'1' IN ('2')", helpGetString(expr));
+ }
+
+ @Test public void testInDecomposeNonLiterals() throws Exception {
+ Expression left = LANG_FACTORY.createLiteral("1", String.class);
+ List<Expression> right = new ArrayList<Expression>();
+ right.add(LANG_FACTORY.createFunction("func", new Expression[] {}, Date.class));
+ right.add(LANG_FACTORY.createLiteral("3", String.class));
+
+ In expr = LANG_FACTORY.createIn(left,right, false);
+
+ assertEquals("'1' = func() OR '1' = '3'", helpGetString(expr));
+ }
+
+ @Test public void testNegatedInDecomposeNonLiterals() throws Exception {
+ Expression left = LANG_FACTORY.createLiteral("1", String.class);
+ List<Expression> right = new ArrayList<Expression>();
+ right.add(LANG_FACTORY.createFunction("func", new Expression[] {}, Date.class));
+ right.add(LANG_FACTORY.createLiteral("3", String.class));
+
+ In expr = LANG_FACTORY.createIn(left,right, true);
+
+ assertEquals("'1' <> func() AND '1' <> '3'", helpGetString(expr));
+ }
+
+ @Test public void testsingleInDecomposeNonLiterals() throws Exception {
+ Expression left = LANG_FACTORY.createLiteral("1", String.class);
+ List<Expression> right = new ArrayList<Expression>();
+ right.add(LANG_FACTORY.createFunction("func", new Expression[] {}, Date.class));
+
+ In expr = LANG_FACTORY.createIn(left,right, false);
+
+ assertEquals("'1' = func()", helpGetString(expr));
+ }
+
+ /* only 7.4
+ @Test public void testNullComapreNull() throws Exception {
+ String input = "SELECT INTKEY, STRINGKEY, DOUBLENUM FROM bqt1.smalla WHERE NULL <> NULL";
+ String out = "SELECT SmallA.IntKey, SmallA.StringKey, SmallA.DoubleNum FROM SmallA WHERE 1 = 0";
+ TranslationHelper.helpTestVisitor(TranslationHelper.BQT_VDB, null, input, out, TRANSLATOR);
+ }
+ @Test public void testPushDownFunction() throws Exception {
+ String input = "SELECT teradata.HASHBAKAMP(STRINGKEY) DOUBLENUM FROM bqt1.smalla";
+ String out = "SELECT HASHBAKAMP(SmallA.StringKey) AS DOUBLENUM FROM SmallA";
+ TranslationHelper.helpTestVisitor(TranslationHelper.BQT_VDB, null, input, out, TRANSLATOR);
+ }
+ */
+
+ @Test public void testRightFunction() throws Exception {
+ String input = "SELECT INTKEY, FLOATNUM FROM BQT1.SmallA WHERE right(FLOATNUM, 2) <> 0 ORDER BY INTKEY";
+ String out = "SELECT SmallA.IntKey, SmallA.FloatNum FROM SmallA WHERE substr(cast(SmallA.FloatNum AS varchar(100)),(character_length(cast(SmallA.FloatNum AS varchar(100)))-2+1)) <> '0' ORDER BY SmallA.IntKey";
+ TranslationHelper.helpTestVisitor(TranslationHelper.BQT_VDB, null, input, out, TRANSLATOR);
+ }
+
+ @Test public void testLocateFunction() throws Exception {
+ String input = "SELECT INTKEY, STRINGKEY, SHORTVALUE FROM BQT1.SmallA WHERE (LOCATE(0, STRINGKEY) = 2) OR (LOCATE(2, SHORTVALUE, 4) = 6) ORDER BY intkey";
+ String out = "SELECT SmallA.IntKey, SmallA.StringKey, SmallA.ShortValue FROM SmallA WHERE position('0' in SmallA.StringKey) = 2 OR position('2' in substr(cast(SmallA.ShortValue AS varchar(100)),4)) = 6 ORDER BY SmallA.IntKey";
+ TranslationHelper.helpTestVisitor(TranslationHelper.BQT_VDB, null, input, out, TRANSLATOR);
+ }
+}
13 years, 7 months
teiid SVN: r3242 - in branches/7.4.x: documentation/reference/src/main/docbook/en-US/content and 7 other directories.
by teiid-commits@lists.jboss.org
Author: shawkins
Date: 2011-06-10 13:50:13 -0400 (Fri, 10 Jun 2011)
New Revision: 3242
Added:
branches/7.4.x/engine/src/main/java/org/teiid/query/xquery/saxon/DocumentWrapper.java
branches/7.4.x/engine/src/main/java/org/teiid/query/xquery/saxon/NodeWrapper.java
branches/7.4.x/engine/src/main/java/org/teiid/query/xquery/saxon/StreamingUtils.java
Modified:
branches/7.4.x/build/kits/jboss-container/teiid-releasenotes.html
branches/7.4.x/documentation/reference/src/main/docbook/en-US/content/federated_planning.xml
branches/7.4.x/documentation/reference/src/main/docbook/en-US/content/scalar_functions.xml
branches/7.4.x/documentation/reference/src/main/docbook/en-US/content/sql_support.xml
branches/7.4.x/engine/pom.xml
branches/7.4.x/engine/src/main/java/org/teiid/query/eval/Evaluator.java
branches/7.4.x/engine/src/main/java/org/teiid/query/function/source/XMLSystemFunctions.java
branches/7.4.x/engine/src/main/java/org/teiid/query/processor/relational/XMLTableNode.java
branches/7.4.x/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java
branches/7.4.x/engine/src/main/java/org/teiid/query/xquery/saxon/PathMapFilter.java
branches/7.4.x/engine/src/main/java/org/teiid/query/xquery/saxon/SaxonXQueryExpression.java
branches/7.4.x/engine/src/test/java/org/teiid/query/processor/TestSQLXMLProcessing.java
Log:
TEIID-1448 adding the ability to stream docs for xquery processing
Modified: branches/7.4.x/build/kits/jboss-container/teiid-releasenotes.html
===================================================================
--- branches/7.4.x/build/kits/jboss-container/teiid-releasenotes.html 2011-06-10 16:28:08 UTC (rev 3241)
+++ branches/7.4.x/build/kits/jboss-container/teiid-releasenotes.html 2011-06-10 17:50:13 UTC (rev 3242)
@@ -60,6 +60,7 @@
<LI><B>ODBC SSL</B> - added support for SSL encrypted ODBC connections.
<LI><B>Reauthentication Statement</B> - SET SESSION AUTHORIZATION can now be used to perform a reauthentication via JDBC or ODBC.
<LI><B>Pluggable Authorization</B> - an alternative PolicyDecider can be defined in the teiid-jboss-beans.xml file to customize authorization decisions.
+ <LI><B>Streaming XQuery</B> - in situations where document projection applies if the XMLQUERY/XMLTABLE path expressions meet certian conditions, then the incoming document will not only be projected, but the independent subtrees will be processed without loading the entire document. This allows for nearly arbitrarily large XML documents to be processed. See the Reference for more.
</UL>
<h2><a name="Compatibility">Compatibility Issues</a></h2>
@@ -206,6 +207,11 @@
<h2><a name="LibraryUpdates">Thirdparty Library Updates</a></h2>
The following components have been updated:
+
+<h4>From 7.4</h4>
+<ul>
+ <li>nux 1.6, and xom 1.2 were added.
+</ul>
<h4>From 7.1</h4>
<ul>
<li>json-simple 1.1 was added.
Modified: branches/7.4.x/documentation/reference/src/main/docbook/en-US/content/federated_planning.xml
===================================================================
--- branches/7.4.x/documentation/reference/src/main/docbook/en-US/content/federated_planning.xml 2011-06-10 16:28:08 UTC (rev 3241)
+++ branches/7.4.x/documentation/reference/src/main/docbook/en-US/content/federated_planning.xml 2011-06-10 17:50:13 UTC (rev 3242)
@@ -377,6 +377,41 @@
</listitem>
</itemizedlist>
</section>
+ <section id="xquery_optimization">
+ <title>XQuery Optimization</title>
+ <para>A technique known as document projection is used to reduce the memory footprint of the context item document.
+ Document projection loads only the parts of the document needed by the relevant XQuery and path expressions.
+ Since document projection analysis uses all relevant path expressions, even 1 expression that could potentially use many nodes, e.g. //x rather than /a/b/x will cause a larger memory footprint.
+ With the relevant content removed the entire document will still be loaded into memory for processing.
+ Document projection will only be used when there is a context item (unnamed PASSING clause item) passed to XMLTABLE/XMLQUERY. A named variable will not have document projection performed.
+ In some cases the expressions used may be too complex for the optimizer to use document projection. You should check the SHOWPLAN DEBUG full plan output to see if the appropriate optimization has been performed.</para>
+ <para>With additional restrictions, simple context path expressions allow the processor to evaluate document subtrees independently - without loading the full document in memory.
+ A simple context path expression can be of the form "[/][ns:]root/[ns1:]elem/...", where a namespace prefix or element name can also be the * wild card. As with normal XQuery processing if namespace prefixes are used in the XQuery expression, they should be declared using the XMLNAMESPACES clause.</para>
+ <example>
+ <title>Streaming Eligible XMLQUERY</title>
+ <programlisting>XMLQUERY('/*:root/*:child' PASSING doc)</programlisting>
+ <para>Rather than loading the entire doc in-memory as a DOM tree, each child element will be independently added to the result.</para>
+ </example>
+ <example>
+ <title>Streaming Ineligible XMLQUERY</title>
+ <programlisting>XMLQUERY('//child' PASSING doc)</programlisting>
+ <para>The use of the descendent axis prevents the streaming optimization, but document projection can still be performed.</para>
+ </example>
+ <para>When using XMLTABLE, the COLUMN PATH expressions have additional restrictions.
+ They are allowed to reference any part of the element subtree formed by the context expression and they may use any attribute value from their direct parentage.
+ Any path expression where it is possible to reference a non-direct ancestor or sibling of the current context item prevent streaming from being used.
+ </para>
+ <example>
+ <title>Streaming Eligible XMLTABLE</title>
+ <programlisting>XMLTABLE('/*:root/*:child' PASSING doc COLUMNS fullchild XML PATH '.', parent_attr string PATH '../@attr', child_val integer)</programlisting>
+ <para>The context XQuery and the column path expression allow the streaming optimization, rather than loading the entire doc in-memory as a DOM tree, each child element will be independently added to the result.</para>
+ </example>
+ <example>
+ <title>Streaming Ineligible XMLTABLE</title>
+ <programlisting>XMLTABLE('/*:root/*:child' PASSING doc COLUMNS sibling_attr string PATH '../other_child/@attr')</programlisting>
+ <para>The reference of an element outside of the child subtree in the sibling_attr path prevents the streaming optimization from being used, but document projection can still be performed.</para>
+ </example>
+ </section>
<section>
<title>Federated Failure Modes</title>
<section>
Modified: branches/7.4.x/documentation/reference/src/main/docbook/en-US/content/scalar_functions.xml
===================================================================
--- branches/7.4.x/documentation/reference/src/main/docbook/en-US/content/scalar_functions.xml 2011-06-10 16:28:08 UTC (rev 3241)
+++ branches/7.4.x/documentation/reference/src/main/docbook/en-US/content/scalar_functions.xml 2011-06-10 17:50:13 UTC (rev 3242)
@@ -2036,9 +2036,7 @@
<para>xquery in string. Return value is xml.</para>
<para>XMLQUERY is part of the SQL/XML 2006 specification.</para>
<para>See also <link linkend="xmltable">XMLTABLE</link></para>
- <note><para>A technique known as document projection is used to reduce the memory footprint of the context item document.
- Only the parts of the document needed by the XQuery path expressions will be loaded into memory. Since document projection analysis uses all relevant path expressions, even 1 expression that could potentially use many nodes, e.g. //x rather than /a/b/x will cause a larger memory footprint.</para></note>
-
+ <note><para>See also <xref linkend="xquery_optimization"/></para></note>
</section>
<section id="xmlserialize">
<title>XMLSERIALIZE</title>
Modified: branches/7.4.x/documentation/reference/src/main/docbook/en-US/content/sql_support.xml
===================================================================
--- branches/7.4.x/documentation/reference/src/main/docbook/en-US/content/sql_support.xml 2011-06-10 16:28:08 UTC (rev 3241)
+++ branches/7.4.x/documentation/reference/src/main/docbook/en-US/content/sql_support.xml 2011-06-10 17:50:13 UTC (rev 3242)
@@ -838,6 +838,7 @@
<para>See XMLELEMENT for the definition of NSP - <link linkend="xmlnamespaces">XMLNAMESPACES</link>.</para>
<para>See XMLQUERY for the definition of <link linkend="passing">PASSING</link>.</para>
<para>See also <link linkend="xmlquery">XMLQUERY</link></para>
+ <note><para>See also <xref linkend="xquery_optimization"/></para></note>
<itemizedlist>
<para>Parameters</para>
<listitem>
@@ -849,10 +850,21 @@
</para>
</listitem>
<listitem>
- <para>If COLUMNS is not specified, then that is the same as having the COLUMNS clause: "COLUMNS OBJECT_VALUE XML PATH '.'", which returns the entire item as an XML value. Each non-ordinality column specifies a type and optionally a PATH and a DEFAULT expression.
- If PATH is not specified, then the path will be the same as the column name. A FOR ORDINALITY column is typed as integer and will return the 1-based item number as its value.
+ <para>If COLUMNS is not specified, then that is the same as having the COLUMNS clause: "COLUMNS OBJECT_VALUE XML PATH '.'", which returns the entire item as an XML value.
</para>
</listitem>
+ <listitem>
+ <para>A FOR ORDINALITY column is typed as integer and will return the 1-based item number as its value.
+ </para>
+ </listitem>
+ <listitem>
+ <para>Each non-ordinality column specifies a type and optionally a PATH and a DEFAULT expression.
+ </para>
+ </listitem>
+ <listitem>
+ <para>If PATH is not specified, then the path will be the same as the column name.
+ </para>
+ </listitem>
</itemizedlist>
<itemizedlist>
<para>Syntax Rules:
Modified: branches/7.4.x/engine/pom.xml
===================================================================
--- branches/7.4.x/engine/pom.xml 2011-06-10 16:28:08 UTC (rev 3241)
+++ branches/7.4.x/engine/pom.xml 2011-06-10 17:50:13 UTC (rev 3242)
@@ -91,7 +91,19 @@
<groupId>com.googlecode.json-simple</groupId>
<artifactId>json-simple</artifactId>
</dependency>
+
+ <dependency>
+ <groupId>nux</groupId>
+ <artifactId>nux</artifactId>
+ <version>1.6</version>
+ </dependency>
+ <dependency>
+ <groupId>xom</groupId>
+ <artifactId>xom</artifactId>
+ <version>1.2</version>
+ </dependency>
+
</dependencies>
</project>
\ No newline at end of file
Modified: branches/7.4.x/engine/src/main/java/org/teiid/query/eval/Evaluator.java
===================================================================
--- branches/7.4.x/engine/src/main/java/org/teiid/query/eval/Evaluator.java 2011-06-10 16:28:08 UTC (rev 3241)
+++ branches/7.4.x/engine/src/main/java/org/teiid/query/eval/Evaluator.java 2011-06-10 17:50:13 UTC (rev 3242)
@@ -42,6 +42,10 @@
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
+import javax.xml.transform.stream.StreamResult;
+
+import net.sf.saxon.om.NodeInfo;
+import net.sf.saxon.query.QueryResult;
import net.sf.saxon.trans.XPathException;
import org.teiid.api.exception.query.ExpressionEvaluationException;
@@ -50,6 +54,7 @@
import org.teiid.core.ComponentNotFoundException;
import org.teiid.core.TeiidComponentException;
import org.teiid.core.TeiidProcessingException;
+import org.teiid.core.TeiidRuntimeException;
import org.teiid.core.types.BlobType;
import org.teiid.core.types.ClobImpl;
import org.teiid.core.types.ClobType;
@@ -68,6 +73,7 @@
import org.teiid.query.function.FunctionDescriptor;
import org.teiid.query.function.FunctionLibrary;
import org.teiid.query.function.source.XMLSystemFunctions;
+import org.teiid.query.function.source.XMLSystemFunctions.XmlConcat;
import org.teiid.query.processor.ProcessorDataManager;
import org.teiid.query.sql.LanguageObject;
import org.teiid.query.sql.lang.AbstractSetCriteria;
@@ -113,11 +119,37 @@
import org.teiid.query.util.CommandContext;
import org.teiid.query.xquery.saxon.SaxonXQueryExpression;
import org.teiid.query.xquery.saxon.SaxonXQueryExpression.Result;
+import org.teiid.query.xquery.saxon.SaxonXQueryExpression.RowProcessor;
import org.teiid.translator.WSConnection.Util;
public class Evaluator {
- private final class SequenceReader extends Reader {
+ private final class XMLQueryRowProcessor implements RowProcessor {
+ XmlConcat concat; //just used to get a writer
+ Type type;
+ private javax.xml.transform.Result result;
+
+ private XMLQueryRowProcessor() throws TeiidProcessingException {
+ concat = new XmlConcat(context.getBufferManager());
+ result = new StreamResult(concat.getWriter());
+ }
+
+ @Override
+ public void processRow(NodeInfo row) {
+ if (type == null) {
+ type = SaxonXQueryExpression.getType(row);
+ } else {
+ type = Type.CONTENT;
+ }
+ try {
+ QueryResult.serialize(row, result, SaxonXQueryExpression.DEFAULT_OUTPUT_PROPERTIES);
+ } catch (XPathException e) {
+ throw new TeiidRuntimeException(e);
+ }
+ }
+ }
+
+ private final class SequenceReader extends Reader {
private LinkedList<Reader> readers;
private Reader current = null;
@@ -759,13 +791,33 @@
private Object evaluateXMLQuery(List<?> tuple, XMLQuery xmlQuery)
throws BlockedException, TeiidComponentException,
FunctionExecutionException {
- boolean emptyOnEmpty = true;
- if (xmlQuery.getEmptyOnEmpty() != null) {
- emptyOnEmpty = xmlQuery.getEmptyOnEmpty();
- }
+ boolean emptyOnEmpty = xmlQuery.getEmptyOnEmpty() == null || xmlQuery.getEmptyOnEmpty();
Result result = null;
try {
- result = evaluateXQuery(xmlQuery.getXQueryExpression(), xmlQuery.getPassing(), tuple);
+ XMLQueryRowProcessor rp = null;
+ if (xmlQuery.getXQueryExpression().isStreaming()) {
+ rp = new XMLQueryRowProcessor();
+ }
+ try {
+ result = evaluateXQuery(xmlQuery.getXQueryExpression(), xmlQuery.getPassing(), tuple, rp);
+ } catch (TeiidRuntimeException e) {
+ if (e.getCause() instanceof XPathException) {
+ throw (XPathException)e.getCause();
+ }
+ throw e;
+ }
+ if (rp != null) {
+ XMLType.Type type = rp.type;
+ if (type == null) {
+ if (!emptyOnEmpty) {
+ return null;
+ }
+ type = Type.CONTENT;
+ }
+ XMLType val = rp.concat.close();
+ val.setType(rp.type);
+ return val;
+ }
return xmlQuery.getXQueryExpression().createXMLType(result.iter, this.context.getBufferManager(), emptyOnEmpty);
} catch (TeiidProcessingException e) {
throw new FunctionExecutionException(e, QueryPlugin.Util.getString("Evaluator.xmlquery", e.getMessage())); //$NON-NLS-1$
@@ -859,7 +911,7 @@
}
}
- public Result evaluateXQuery(SaxonXQueryExpression xquery, List<DerivedColumn> cols, List<?> tuple)
+ public Result evaluateXQuery(SaxonXQueryExpression xquery, List<DerivedColumn> cols, List<?> tuple, RowProcessor processor)
throws BlockedException, TeiidComponentException, TeiidProcessingException {
HashMap<String, Object> parameters = new HashMap<String, Object>();
Object contextItem = null;
@@ -871,7 +923,7 @@
parameters.put(passing.getAlias(), value);
}
}
- return xquery.evaluateXQuery(contextItem, parameters);
+ return xquery.evaluateXQuery(contextItem, parameters, processor, context);
}
private Evaluator.NameValuePair<Object>[] getNameValuePairs(List<?> tuple, List<DerivedColumn> args, boolean xmlNames)
Modified: branches/7.4.x/engine/src/main/java/org/teiid/query/function/source/XMLSystemFunctions.java
===================================================================
--- branches/7.4.x/engine/src/main/java/org/teiid/query/function/source/XMLSystemFunctions.java 2011-06-10 16:28:08 UTC (rev 3241)
+++ branches/7.4.x/engine/src/main/java/org/teiid/query/function/source/XMLSystemFunctions.java 2011-06-10 17:50:13 UTC (rev 3242)
@@ -401,6 +401,7 @@
private Writer writer;
private FileStoreInputStreamFactory fsisf;
private FileStore fs;
+ private Type type;
public XmlConcat(BufferManager bm) throws TeiidProcessingException {
fs = bm.createFileStore("xml"); //$NON-NLS-1$
@@ -417,6 +418,13 @@
}
public void addValue(Object object) throws TeiidProcessingException {
+ if (type == null) {
+ if (object instanceof XMLType) {
+ type = ((XMLType)object).getType();
+ }
+ } else {
+ type = Type.CONTENT;
+ }
try {
convertValue(writer, eventWriter, eventFactory, object);
} catch (IOException e) {
@@ -431,6 +439,10 @@
}
}
+ public Writer getWriter() {
+ return writer;
+ }
+
public XMLType close() throws TeiidProcessingException {
try {
eventWriter.flush();
@@ -443,7 +455,11 @@
throw new TeiidProcessingException(e);
}
XMLType result = new XMLType(new SQLXMLImpl(fsisf));
- result.setType(Type.CONTENT);
+ if (type == null) {
+ result.setType(Type.CONTENT);
+ } else {
+ result.setType(type);
+ }
return result;
}
Modified: branches/7.4.x/engine/src/main/java/org/teiid/query/processor/relational/XMLTableNode.java
===================================================================
--- branches/7.4.x/engine/src/main/java/org/teiid/query/processor/relational/XMLTableNode.java 2011-06-10 16:28:08 UTC (rev 3241)
+++ branches/7.4.x/engine/src/main/java/org/teiid/query/processor/relational/XMLTableNode.java 2011-06-10 17:50:13 UTC (rev 3242)
@@ -29,6 +29,7 @@
import java.util.Map;
import net.sf.saxon.om.Item;
+import net.sf.saxon.om.NodeInfo;
import net.sf.saxon.om.SequenceIterator;
import net.sf.saxon.sxpath.XPathDynamicContext;
import net.sf.saxon.sxpath.XPathExpression;
@@ -42,8 +43,12 @@
import org.teiid.api.exception.query.ExpressionEvaluationException;
import org.teiid.common.buffer.BlockedException;
import org.teiid.common.buffer.TupleBatch;
+import org.teiid.common.buffer.TupleBuffer;
+import org.teiid.common.buffer.BufferManager.TupleSourceType;
import org.teiid.core.TeiidComponentException;
+import org.teiid.core.TeiidException;
import org.teiid.core.TeiidProcessingException;
+import org.teiid.core.TeiidRuntimeException;
import org.teiid.core.types.DataTypeManager;
import org.teiid.core.types.XMLType;
import org.teiid.query.QueryPlugin;
@@ -51,11 +56,15 @@
import org.teiid.query.sql.lang.XMLTable;
import org.teiid.query.sql.lang.XMLTable.XMLColumn;
import org.teiid.query.xquery.saxon.SaxonXQueryExpression.Result;
+import org.teiid.query.xquery.saxon.SaxonXQueryExpression.RowProcessor;
/**
* Handles xml table processing.
+ *
+ * When streaming the results will be fully built and stored in a buffer
+ * before being returned
*/
-public class XMLTableNode extends SubqueryAwareRelationalNode {
+public class XMLTableNode extends SubqueryAwareRelationalNode implements RowProcessor {
private static Map<Class<?>, BuiltInAtomicType> typeMapping = new HashMap<Class<?>, BuiltInAtomicType>();
@@ -74,6 +83,10 @@
private int rowCount = 0;
private Item item;
+ private TupleBuffer buffer;
+ private int outputRow = 1;
+ private boolean usingOutput;
+
public XMLTableNode(int nodeID) {
super(nodeID);
}
@@ -81,6 +94,10 @@
@Override
public void closeDirect() {
super.closeDirect();
+ if(this.buffer != null) {
+ this.buffer.remove();
+ this.buffer = null;
+ }
reset();
}
@@ -93,6 +110,9 @@
}
item = null;
rowCount = 0;
+ outputRow = 1;
+ usingOutput = false;
+ this.buffer = null;
}
public void setTable(XMLTable table) {
@@ -116,31 +136,62 @@
protected TupleBatch nextBatchDirect() throws BlockedException,
TeiidComponentException, TeiidProcessingException {
- if (result == null) {
- setReferenceValues(this.table);
- result = getEvaluator(Collections.emptyMap()).evaluateXQuery(this.table.getXQueryExpression(), this.table.getPassing(), null);
+ evaluate();
+
+ if (this.table.getXQueryExpression().isStreaming()) {
+ TupleBatch batch = this.buffer.getBatch(outputRow);
+ outputRow = batch.getEndRow() + 1;
+ return batch;
}
while (!isBatchFull() && !isLastBatch()) {
- processRow();
+ if (item == null) {
+ try {
+ item = result.iter.next();
+ } catch (XPathException e) {
+ throw new TeiidProcessingException(e, QueryPlugin.Util.getString("XMLTableNode.error", e.getMessage())); //$NON-NLS-1$
+ }
+ rowCount++;
+ if (item == null) {
+ terminateBatches();
+ break;
+ }
+ }
+ addBatchRow(processRow());
}
return pullBatch();
}
- private void processRow() throws ExpressionEvaluationException, BlockedException,
- TeiidComponentException, TeiidProcessingException {
- if (item == null) {
+ private void evaluate() throws TeiidComponentException,
+ ExpressionEvaluationException, BlockedException,
+ TeiidProcessingException {
+ if (result == null) {
+ if (this.buffer == null && this.table.getXQueryExpression().isStreaming()) {
+ this.buffer = this.getBufferManager().createTupleBuffer(getOutputElements(), getConnectionID(), TupleSourceType.PROCESSOR);
+ }
+ setReferenceValues(this.table);
try {
- item = result.iter.next();
- } catch (XPathException e) {
- throw new TeiidProcessingException(e, QueryPlugin.Util.getString("XMLTableNode.error", e.getMessage())); //$NON-NLS-1$
+ result = getEvaluator(Collections.emptyMap()).evaluateXQuery(this.table.getXQueryExpression(), this.table.getPassing(), null, this);
+ if (this.buffer != null) {
+ this.buffer.close();
+ if (!usingOutput) {
+ this.buffer.setForwardOnly(true);
+ }
+ }
+ } catch (TeiidRuntimeException e) {
+ if (e.getCause() instanceof TeiidComponentException) {
+ throw (TeiidComponentException)e.getCause();
+ }
+ if (e.getCause() instanceof TeiidProcessingException) {
+ throw (TeiidProcessingException)e.getCause();
+ }
+ throw e;
}
- rowCount++;
- if (item == null) {
- terminateBatches();
- return;
- }
}
+ }
+
+ private List<?> processRow() throws ExpressionEvaluationException, BlockedException,
+ TeiidComponentException, TeiidProcessingException {
List<Object> tuple = new ArrayList<Object>(projectedColumns.size());
for (XMLColumn proColumn : projectedColumns) {
if (proColumn.isOrdinal()) {
@@ -167,8 +218,10 @@
if (pathIter.next() != null) {
throw new TeiidProcessingException(QueryPlugin.Util.getString("XMLTableName.multi_value", proColumn.getName())); //$NON-NLS-1$
}
- Object value = Value.convertToJava(colItem);
- if (value instanceof Item) {
+ Object value = colItem;
+ if (value instanceof AtomicValue) {
+ value = Value.convertToJava(colItem);
+ } else if (value instanceof Item) {
Item i = (Item)value;
BuiltInAtomicType bat = typeMapping.get(proColumn.getSymbol().getType());
if (bat != null) {
@@ -190,7 +243,37 @@
}
}
item = null;
- addBatchRow(tuple);
+ return tuple;
}
+
+ @Override
+ public boolean hasFinalBuffer() {
+ return this.table.getXQueryExpression().isStreaming();
+ }
+
+ @Override
+ public TupleBuffer getFinalBuffer() throws BlockedException,
+ TeiidComponentException, TeiidProcessingException {
+ evaluate();
+ usingOutput = true;
+ TupleBuffer finalBuffer = this.buffer;
+ this.buffer = null;
+ close();
+ return finalBuffer;
+ }
+
+ @Override
+ public void processRow(NodeInfo row) {
+ this.item = row;
+ rowCount++;
+ if (rowCount % 100 == 0) {
+ System.out.println(System.currentTimeMillis() + " " + rowCount);
+ }
+ try {
+ this.buffer.addTuple(processRow());
+ } catch (TeiidException e) {
+ throw new TeiidRuntimeException(e);
+ }
+ }
}
\ No newline at end of file
Modified: branches/7.4.x/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java
===================================================================
--- branches/7.4.x/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java 2011-06-10 16:28:08 UTC (rev 3241)
+++ branches/7.4.x/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java 2011-06-10 17:50:13 UTC (rev 3242)
@@ -789,8 +789,8 @@
}
protected void validateInsert(Insert obj) {
- Collection vars = obj.getVariables();
- Iterator varIter = vars.iterator();
+ Collection<ElementSymbol> vars = obj.getVariables();
+ Iterator<ElementSymbol> varIter = vars.iterator();
Collection values = obj.getValues();
Iterator valIter = values.iterator();
GroupSymbol insertGroup = obj.getGroup();
@@ -798,9 +798,7 @@
try {
// Validate that all elements in variable list are updatable
- Iterator elementIter = vars.iterator();
- while(elementIter.hasNext()) {
- ElementSymbol insertElem = (ElementSymbol) elementIter.next();
+ for (ElementSymbol insertElem : vars) {
if(! getMetadata().elementSupports(insertElem.getMetadataID(), SupportConstants.Element.UPDATE)) {
handleValidationError(QueryPlugin.Util.getString("ERR.015.012.0052", insertElem), insertElem); //$NON-NLS-1$
}
@@ -825,7 +823,7 @@
// if any of the value present in the insert are null
while(valIter.hasNext() && varIter.hasNext()) {
Expression nextValue = (Expression) valIter.next();
- ElementSymbol nextVar = (ElementSymbol) varIter.next();
+ ElementSymbol nextVar = varIter.next();
if (!(nextValue instanceof Constant) && getMetadata().isMultiSourceElement(nextVar.getMetadataID())) {
handleValidationError(QueryPlugin.Util.getString("ValidationVisitor.multisource_constant", nextVar), nextVar); //$NON-NLS-1$
Added: branches/7.4.x/engine/src/main/java/org/teiid/query/xquery/saxon/DocumentWrapper.java
===================================================================
--- branches/7.4.x/engine/src/main/java/org/teiid/query/xquery/saxon/DocumentWrapper.java (rev 0)
+++ branches/7.4.x/engine/src/main/java/org/teiid/query/xquery/saxon/DocumentWrapper.java 2011-06-10 17:50:13 UTC (rev 3242)
@@ -0,0 +1,268 @@
+package org.teiid.query.xquery.saxon;
+
+import java.lang.reflect.Method;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+
+import net.sf.saxon.Configuration;
+import net.sf.saxon.om.DocumentInfo;
+import net.sf.saxon.om.NamePool;
+import net.sf.saxon.om.NodeInfo;
+import net.sf.saxon.type.Type;
+import nu.xom.Attribute;
+import nu.xom.Document;
+import nu.xom.Element;
+import nu.xom.Node;
+
+/**
+ * The root node of an XPath tree. (Or equivalently, the tree itself).
+ * <P>
+ * This class is used not only for a document, but also for the root
+ * of a document-less tree fragment.
+ *
+ * @author Michael H. Kay
+ * @author Wolfgang Hoschek (ported net.sf.saxon.jdom to XOM)
+ * @author Steve Hawkins (Ported to Saxon 9.1 for Teiid)
+ */
+
+public class DocumentWrapper extends NodeWrapper implements DocumentInfo {
+
+ protected Configuration config;
+
+ protected String baseURI;
+
+ protected int documentNumber;
+
+ private HashMap idIndex;
+
+ /**
+ * Create a Saxon wrapper for a XOM root node
+ *
+ * @param root
+ * The XOM root node
+ * @param baseURI
+ * The base URI for all the nodes in the tree
+ * @param config
+ * The configuration which defines the name pool used for all
+ * names in this tree
+ */
+ public DocumentWrapper(Node root, String baseURI, Configuration config) {
+ super(root, null, 0);
+ if (root.getParent() != null)
+ throw new IllegalArgumentException("root node must not have a parent node");
+ this.baseURI = baseURI;
+ this.docWrapper = this;
+ setConfiguration(config);
+ }
+
+ /**
+ * Wrap a node in the XOM document.
+ *
+ * @param node
+ * The node to be wrapped. This must be a node in the same
+ * document (the system does not check for this).
+ * @return the wrapping NodeInfo object
+ */
+
+ public NodeInfo wrap(Node node) {
+ if (node == this.node) {
+ return this;
+ }
+ return makeWrapper(node, this);
+ }
+
+ /**
+ * Set the configuration, which defines the name pool used for all names in
+ * this document. This is always called after a new document has been
+ * created. The implementation must register the name pool with the
+ * document, so that it can be retrieved using getNamePool(). It must also
+ * call NamePool.allocateDocumentNumber(), and return the relevant document
+ * number when getDocumentNumber() is subsequently called.
+ *
+ * @param config
+ * The configuration to be used
+ */
+
+ public void setConfiguration(Configuration config) {
+ this.config = config;
+ this.documentNumber = allocateDocumentNumber(config);
+ }
+
+ /**
+ * Get the configuration previously set using setConfiguration
+ */
+
+ public Configuration getConfiguration() {
+ return config;
+ }
+
+ /**
+ * Get the name pool used for the names in this document
+ *
+ * @return the name pool in which all the names used in this document are
+ * registered
+ */
+
+ public NamePool getNamePool() {
+ return config.getNamePool();
+ }
+
+ /**
+ * Get the unique document number for this document (the number is unique
+ * for all documents within a NamePool)
+ *
+ * @return the unique number identifying this document within the name pool
+ */
+
+ public int getDocumentNumber() {
+ return documentNumber;
+ }
+
+ /**
+ * Get the element with a given ID, if any
+ *
+ * @param id
+ * the required ID value
+ * @return the element with the given ID, or null if there is no such ID
+ * present (or if the parser has not notified attributes as being of
+ * type ID).
+ */
+
+ public NodeInfo selectID(String id) {
+ if (idIndex == null) {
+ Element elem;
+ switch (nodeKind) {
+ case Type.DOCUMENT :
+ elem = ((Document) node).getRootElement();
+ break;
+ case Type.ELEMENT :
+ elem = (Element) node;
+ break;
+ default:
+ return null;
+ }
+ idIndex = new HashMap(50);
+ buildIDIndex(elem);
+ }
+ return (NodeInfo) idIndex.get(id);
+ }
+
+
+ private void buildIDIndex(Element elem) {
+ // walk the tree in reverse document order, to satisfy the XPath 1.0 rule
+ // that says if an ID appears twice, the first one wins
+ for (int i=elem.getChildCount(); --i >= 0 ; ) {
+ Node child = elem.getChild(i);
+ if (child instanceof Element) {
+ buildIDIndex((Element)child);
+ }
+ }
+ for (int i=elem.getAttributeCount(); --i >= 0 ; ) {
+ Attribute att = elem.getAttribute(i);
+ if (att.getType() == Attribute.Type.ID) {
+ idIndex.put(att.getValue(), wrap(elem));
+ }
+ }
+ }
+
+ /**
+ * Get the unparsed entity with a given name
+ *
+ * @param name
+ * the name of the entity
+ * @return null: XOM does not provide access to unparsed entities
+ * @return if the entity exists, return an array of two Strings, the first
+ * holding the system ID of the entity, the second holding the
+ * public ID if there is one, or null if not. If the entity does not
+ * exist, return null.
+ */
+
+ public String[] getUnparsedEntity(String name) {
+ return null;
+ }
+
+ private static final Method saxon85Method = findAllocateDocumentNumberMethod85();
+
+ // work-around for incompatibility introduced in saxon-8.5.1
+ private int allocateDocumentNumber(Configuration config) {
+ if (saxon85Method == null) {
+ try { // saxon >= 8.5.1
+ return allocateDocumentNumber851(config);
+ } catch (Throwable t) {
+ throw new RuntimeException(t);
+ }
+ }
+
+ // saxon < 8.5.1
+ try {
+ // return config.getNamePool().allocateDocumentNumber(this);
+ Object result = saxon85Method.invoke(config.getNamePool(), new Object[] {this});
+ return ((Integer) result).intValue();
+ } catch (Throwable t) {
+ throw new RuntimeException(t);
+ }
+
+ }
+
+ // saxon >= 8.5.1
+ private int allocateDocumentNumber851(Configuration config) {
+ return config.getDocumentNumberAllocator().allocateDocumentNumber();
+ }
+
+ private static Method findAllocateDocumentNumberMethod85() {
+ try {
+ return NamePool.class.getMethod("allocateDocumentNumber", new Class[] {NodeInfo.class});
+ } catch (Throwable t) {
+ return null;
+ }
+ }
+
+ @Override
+ public Iterator getUnparsedEntityNames() {
+ return Collections.EMPTY_LIST.iterator();
+ }
+
+ @Override
+ public int getColumnNumber() {
+ return -1;
+ }
+
+ @Override
+ public boolean isId() {
+ return false;
+ }
+
+ @Override
+ public boolean isIdref() {
+ return false;
+ }
+
+ @Override
+ public boolean isNilled() {
+ return false;
+ }
+
+}
+
+//
+// The contents of this file are subject to the Mozilla Public License Version
+// 1.0 (the "License");
+// you may not use this file except in compliance with the License. You may
+// obtain a copy of the
+// License at http://www.mozilla.org/MPL/
+//
+// Software distributed under the License is distributed on an "AS IS" basis,
+// WITHOUT WARRANTY OF ANY KIND, either express or implied.
+// See the License for the specific language governing rights and limitations
+// under the License.
+//
+// The Original Code is: all this file.
+//
+// The Initial Developer of the Original Code is Michael Kay
+//
+// Portions created by (your name) are Copyright (C) (your legal entity). All
+// Rights Reserved.
+//
+// Contributor(s): none.
+//
Property changes on: branches/7.4.x/engine/src/main/java/org/teiid/query/xquery/saxon/DocumentWrapper.java
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: branches/7.4.x/engine/src/main/java/org/teiid/query/xquery/saxon/NodeWrapper.java
===================================================================
--- branches/7.4.x/engine/src/main/java/org/teiid/query/xquery/saxon/NodeWrapper.java (rev 0)
+++ branches/7.4.x/engine/src/main/java/org/teiid/query/xquery/saxon/NodeWrapper.java 2011-06-10 17:50:13 UTC (rev 3242)
@@ -0,0 +1,1387 @@
+package org.teiid.query.xquery.saxon;
+
+import net.sf.saxon.Configuration;
+import net.sf.saxon.event.Receiver;
+import net.sf.saxon.om.Axis;
+import net.sf.saxon.om.AxisIterator;
+import net.sf.saxon.om.AxisIteratorImpl;
+import net.sf.saxon.om.DocumentInfo;
+import net.sf.saxon.om.EmptyIterator;
+import net.sf.saxon.om.FastStringBuffer;
+import net.sf.saxon.om.Item;
+import net.sf.saxon.om.NamePool;
+import net.sf.saxon.om.NamespaceIterator;
+import net.sf.saxon.om.Navigator;
+import net.sf.saxon.om.NodeInfo;
+import net.sf.saxon.om.SequenceIterator;
+import net.sf.saxon.om.SiblingCountingNode;
+import net.sf.saxon.om.SingleNodeIterator;
+import net.sf.saxon.om.SingletonIterator;
+import net.sf.saxon.om.StandardNames;
+import net.sf.saxon.om.VirtualNode;
+import net.sf.saxon.pattern.AnyNodeTest;
+import net.sf.saxon.pattern.NameTest;
+import net.sf.saxon.pattern.NodeKindTest;
+import net.sf.saxon.pattern.NodeTest;
+import net.sf.saxon.trans.XPathException;
+import net.sf.saxon.type.Type;
+import net.sf.saxon.value.AtomicValue;
+import net.sf.saxon.value.StringValue;
+import net.sf.saxon.value.UntypedAtomicValue;
+import net.sf.saxon.value.Value;
+import nu.xom.Attribute;
+import nu.xom.Comment;
+import nu.xom.DocType;
+import nu.xom.Document;
+import nu.xom.Element;
+import nu.xom.Node;
+import nu.xom.ParentNode;
+import nu.xom.ProcessingInstruction;
+import nu.xom.Text;
+
+/**
+ * A node in the XML parse tree representing an XML element, character content,
+ * or attribute.
+ * <P>
+ * This is the implementation of the NodeInfo interface used as a wrapper for
+ * XOM nodes.
+ *
+ * @author Michael H. Kay
+ * @author Wolfgang Hoschek (ported net.sf.saxon.jdom to XOM)
+ * @author Steve Hawkins (Ported to Saxon 9.1 for Teiid and fixed a bug with the buffer usage in getDeclaredNamespaces)
+ */
+
+public class NodeWrapper implements NodeInfo, VirtualNode, SiblingCountingNode {
+
+ protected Node node;
+
+ protected short nodeKind;
+
+ private NodeWrapper parent; // null means unknown
+
+ protected DocumentWrapper docWrapper;
+
+ protected int index; // -1 means unknown
+
+ /**
+ * This constructor is protected: nodes should be created using the wrap
+ * factory method on the DocumentWrapper class
+ *
+ * @param node
+ * The XOM node to be wrapped
+ * @param parent
+ * The NodeWrapper that wraps the parent of this node
+ * @param index
+ * Position of this node among its siblings
+ */
+ protected NodeWrapper(Node node, NodeWrapper parent, int index) {
+ short kind;
+ if (node instanceof Element) {
+ kind = Type.ELEMENT;
+ } else if (node instanceof Text) {
+ kind = Type.TEXT;
+ } else if (node instanceof Attribute) {
+ kind = Type.ATTRIBUTE;
+ } else if (node instanceof Comment) {
+ kind = Type.COMMENT;
+ } else if (node instanceof ProcessingInstruction) {
+ kind = Type.PROCESSING_INSTRUCTION;
+ } else if (node instanceof Document) {
+ kind = Type.DOCUMENT;
+ } else {
+ throwIllegalNode(node); // moved out of fast path to enable better inlining
+ return; // keep compiler happy
+ }
+ this.nodeKind = kind;
+ this.node = node;
+ this.parent = parent;
+ this.index = index;
+ }
+
+ /**
+ * Factory method to wrap a XOM node with a wrapper that implements the
+ * Saxon NodeInfo interface.
+ *
+ * @param node
+ * The XOM node
+ * @param docWrapper
+ * The wrapper for the Document containing this node
+ * @return The new wrapper for the supplied node
+ */
+ protected final NodeWrapper makeWrapper(Node node, DocumentWrapper docWrapper) {
+ return makeWrapper(node, docWrapper, null, -1);
+ }
+
+ /**
+ * Factory method to wrap a XOM node with a wrapper that implements the
+ * Saxon NodeInfo interface.
+ *
+ * @param node
+ * The XOM node
+ * @param docWrapper
+ * The wrapper for the Document containing this node
+ * @param parent
+ * The wrapper for the parent of the XOM node
+ * @param index
+ * The position of this node relative to its siblings
+ * @return The new wrapper for the supplied node
+ */
+
+ protected final NodeWrapper makeWrapper(Node node, DocumentWrapper docWrapper,
+ NodeWrapper parent, int index) {
+
+ if (node == docWrapper.node) return docWrapper;
+ NodeWrapper wrapper = new NodeWrapper(node, parent, index);
+ wrapper.docWrapper = docWrapper;
+ return wrapper;
+ }
+
+ private static void throwIllegalNode(Node node) {
+ String str = node == null ?
+ "NULL" :
+ node.getClass() + " instance " + node.toString();
+ throw new IllegalArgumentException("Bad node type in XOM! " + str);
+ }
+
+ /**
+ * Get the configuration
+ */
+
+ public Configuration getConfiguration() {
+ return docWrapper.getConfiguration();
+ }
+
+ /**
+ * Get the underlying XOM node, to implement the VirtualNode interface
+ */
+
+ public Object getUnderlyingNode() {
+ return node;
+ }
+
+ /**
+ * Get the name pool for this node
+ *
+ * @return the NamePool
+ */
+
+ public NamePool getNamePool() {
+ return docWrapper.getNamePool();
+ }
+
+ /**
+ * Return the type of node.
+ *
+ * @return one of the values Node.ELEMENT, Node.TEXT, Node.ATTRIBUTE, etc.
+ */
+
+ public int getNodeKind() {
+ return nodeKind;
+ }
+
+ /**
+ * Get the typed value of the item
+ */
+
+ public SequenceIterator getTypedValue() {
+ return SingletonIterator.makeIterator((AtomicValue)atomize());
+ }
+
+ /**
+ * Get the typed value. The result of this method will always be consistent
+ * with the method {@link net.sf.saxon.om.Item#getTypedValue()}. However,
+ * this method is often more convenient and may be more efficient,
+ * especially in the common case where the value is expected to be a
+ * singleton.
+ *
+ * @return the typed value. If requireSingleton is set to true, the result
+ * will always be an AtomicValue. In other cases it may be a Value
+ * representing a sequence whose items are atomic values.
+ * @since 8.5
+ */
+
+ public Value atomize() {
+ switch (getNodeKind()) {
+ case Type.COMMENT:
+ case Type.PROCESSING_INSTRUCTION:
+ return new StringValue(getStringValueCS());
+ default:
+ return new UntypedAtomicValue(getStringValueCS());
+ }
+ }
+
+ /**
+ * Get the type annotation of this node, if any. Returns -1 for kinds of
+ * nodes that have no annotation, and for elements annotated as untyped, and
+ * attributes annotated as untypedAtomic.
+ *
+ * @return the type annotation of the node.
+ * @see net.sf.saxon.type.Type
+ */
+
+ public int getTypeAnnotation() {
+ if (getNodeKind() == Type.ATTRIBUTE) {
+ return StandardNames.XS_UNTYPED_ATOMIC;
+ }
+ return StandardNames.XS_UNTYPED;
+ }
+
+ /**
+ * Determine whether this is the same node as another node. <br />
+ * Note: a.isSameNode(b) if and only if generateId(a)==generateId(b)
+ *
+ * @return true if this Node object and the supplied Node object represent
+ * the same node in the tree.
+ */
+
+ public boolean isSameNodeInfo(NodeInfo other) {
+ if (other instanceof NodeWrapper) {
+ return node == ((NodeWrapper) other).node; // In XOM equality means identity
+ }
+ return false;
+ }
+
+ /**
+ * The equals() method compares nodes for identity. It is defined to give the same result
+ * as isSameNodeInfo().
+ *
+ * @param other the node to be compared with this node
+ * @return true if this NodeInfo object and the supplied NodeInfo object represent
+ * the same node in the tree.
+ * @since 8.7 Previously, the effect of the equals() method was not defined. Callers
+ * should therefore be aware that third party implementations of the NodeInfo interface may
+ * not implement the correct semantics. It is safer to use isSameNodeInfo() for this reason.
+ * The equals() method has been defined because it is useful in contexts such as a Java Set or HashMap.
+ */
+
+ public boolean equals(Object other) {
+ if (other instanceof NodeInfo) {
+ return isSameNodeInfo((NodeInfo)other);
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * The hashCode() method obeys the contract for hashCode(): that is, if two objects are equal
+ * (represent the same node) then they must have the same hashCode()
+ * @since 8.7 Previously, the effect of the equals() and hashCode() methods was not defined. Callers
+ * should therefore be aware that third party implementations of the NodeInfo interface may
+ * not implement the correct semantics.
+ */
+
+ public int hashCode() {
+ return node.hashCode();
+ }
+
+ /**
+ * Get the System ID for the node.
+ *
+ * @return the System Identifier of the entity in the source document
+ * containing the node, or null if not known. Note this is not the
+ * same as the base URI: the base URI can be modified by xml:base,
+ * but the system ID cannot.
+ */
+
+ public String getSystemId() {
+ return docWrapper.baseURI;
+ }
+
+ public void setSystemId(String uri) {
+ docWrapper.baseURI = uri;
+ }
+
+ /**
+ * Get the Base URI for the node, that is, the URI used for resolving a
+ * relative URI contained in the node.
+ */
+
+ public String getBaseURI() {
+ return node.getBaseURI();
+ }
+
+ /**
+ * Get line number
+ *
+ * @return the line number of the node in its original source document; or
+ * -1 if not available
+ */
+
+ public int getLineNumber() {
+ return -1;
+ }
+
+ /**
+ * Determine the relative position of this node and another node, in
+ * document order. The other node will always be in the same document.
+ *
+ * @param other
+ * The other node, whose position is to be compared with this
+ * node
+ * @return -1 if this node precedes the other node, +1 if it follows the
+ * other node, or 0 if they are the same node. (In this case,
+ * isSameNode() will always return true, and the two nodes will
+ * produce the same result for generateId())
+ */
+
+ public int compareOrder(NodeInfo other) {
+ if (other instanceof NodeWrapper) {
+ return compareOrderFast(node,((NodeWrapper) other).node);
+// }
+// if (other instanceof SiblingCountingNode) {
+// return Navigator.compareOrder(this, (SiblingCountingNode) other);
+ } else {
+ // it must be a namespace node
+ return -other.compareOrder(this);
+ }
+ }
+
+ private static int compareOrderFast(Node first, Node second) {
+ /*
+ * Unfortunately we do not have a sequence number for each node at hand;
+ * this would allow to turn the comparison into a simple sequence number
+ * subtraction. Walking the entire tree and batch-generating sequence
+ * numbers on the fly is no good option either. However, this rewritten
+ * implementation turns out to be more than fast enough.
+ */
+
+ // assert first != null && second != null
+ // assert first and second MUST NOT be namespace nodes
+ if (first == second) return 0;
+
+ ParentNode firstParent = first.getParent();
+ ParentNode secondParent = second.getParent();
+ if (firstParent == null) {
+ if (secondParent != null) return -1; // first node is the root
+ // both nodes are parentless, use arbitrary but fixed order:
+ return first.hashCode() - second.hashCode();
+ }
+
+ if (secondParent == null) return +1; // second node is the root
+
+ // do they have the same parent (common case)?
+ if (firstParent == secondParent) {
+ int i1 = firstParent.indexOf(first);
+ int i2 = firstParent.indexOf(second);
+
+ // note that attributes and namespaces are not children
+ // of their own parent (i = -1).
+ // attribute (if any) comes before child
+ if (i1 != -1) return (i2 != -1) ? i1 - i2 : +1;
+ if (i2 != -1) return -1;
+
+ // assert: i1 == -1 && i2 == -1
+ // i.e. both nodes are attributes
+ Element elem = (Element) firstParent;
+ for (int i = elem.getAttributeCount(); --i >= 0;) {
+ Attribute attr = elem.getAttribute(i);
+ if (attr == second) return -1;
+ if (attr == first) return +1;
+ }
+ throw new IllegalStateException("should be unreachable");
+ }
+
+ // find the depths of both nodes in the tree
+ int depth1 = 0;
+ int depth2 = 0;
+ Node p1 = first;
+ Node p2 = second;
+ while (p1 != null) {
+ depth1++;
+ p1 = p1.getParent();
+ if (p1 == second) return +1;
+ }
+ while (p2 != null) {
+ depth2++;
+ p2 = p2.getParent();
+ if (p2 == first) return -1;
+ }
+
+ // move up one branch of the tree so we have two nodes on the same level
+ p1 = first;
+ while (depth1 > depth2) {
+ p1 = p1.getParent();
+ depth1--;
+ }
+ p2 = second;
+ while (depth2 > depth1) {
+ p2 = p2.getParent();
+ depth2--;
+ }
+
+ // now move up both branches in sync until we find a common parent
+ while (true) {
+ firstParent = p1.getParent();
+ secondParent = p2.getParent();
+ if (firstParent == null || secondParent == null) {
+ // both nodes are documentless, use arbitrary but fixed order
+ // based on their root elements
+ return p1.hashCode() - p2.hashCode();
+ // throw new NullPointerException("XOM tree compare - internal error");
+ }
+ if (firstParent == secondParent) {
+ return firstParent.indexOf(p1) - firstParent.indexOf(p2);
+ }
+ p1 = firstParent;
+ p2 = secondParent;
+ }
+ }
+
+ /**
+ * Return the string value of the node. The interpretation of this depends
+ * on the type of node. For an element it is the accumulated character
+ * content of the element, including descendant elements.
+ *
+ * @return the string value of the node
+ */
+
+ public String getStringValue() {
+ return node.getValue();
+ }
+
+ /**
+ * Get the value of the item as a CharSequence. This is in some cases more efficient than
+ * the version of the method that returns a String.
+ */
+
+ public CharSequence getStringValueCS() {
+ return node.getValue();
+ }
+
+ /**
+ * Get name code. The name code is a coded form of the node name: two nodes
+ * with the same name code have the same namespace URI, the same local name,
+ * and the same prefix. By masking the name code with &0xfffff, you get a
+ * fingerprint: two nodes with the same fingerprint have the same local name
+ * and namespace URI.
+ *
+ * @see net.sf.saxon.om.NamePool#allocate allocate
+ */
+
+ public int getNameCode() {
+ switch (nodeKind) {
+ case Type.ELEMENT:
+ case Type.ATTRIBUTE:
+ case Type.PROCESSING_INSTRUCTION:
+ return docWrapper.getNamePool().allocate(getPrefix(), getURI(),
+ getLocalPart());
+ default:
+ return -1;
+ }
+ }
+
+ /**
+ * Get fingerprint. The fingerprint is a coded form of the expanded name of
+ * the node: two nodes with the same name code have the same namespace URI
+ * and the same local name. A fingerprint of -1 should be returned for a
+ * node with no name.
+ */
+
+ public int getFingerprint() {
+ int nc = getNameCode();
+ if (nc == -1) return -1;
+ return nc & 0xfffff;
+ }
+
+ /**
+ * Get the local part of the name of this node. This is the name after the
+ * ":" if any.
+ *
+ * @return the local part of the name. For an unnamed node, returns "".
+ */
+
+ public String getLocalPart() {
+ switch (nodeKind) {
+ case Type.ELEMENT:
+ return ((Element) node).getLocalName();
+ case Type.ATTRIBUTE:
+ return ((Attribute) node).getLocalName();
+ case Type.PROCESSING_INSTRUCTION:
+ return ((ProcessingInstruction) node).getTarget();
+ default:
+ return "";
+ }
+ }
+
+ /**
+ * Get the prefix of the name of the node. This is defined only for elements and attributes.
+ * If the node has no prefix, or for other kinds of node, return a zero-length string.
+ * @return The prefix of the name of the node.
+ */
+
+ public String getPrefix() {
+ switch (nodeKind) {
+ case Type.ELEMENT:
+ return ((Element) node).getNamespacePrefix();
+ case Type.ATTRIBUTE:
+ return ((Attribute) node).getNamespacePrefix();
+ default:
+ return "";
+ }
+ }
+
+ /**
+ * Get the URI part of the name of this node. This is the URI corresponding
+ * to the prefix, or the URI of the default namespace if appropriate.
+ *
+ * @return The URI of the namespace of this node. For an unnamed node, or
+ * for a node with an empty prefix, return an empty string.
+ */
+
+ public String getURI() {
+ switch (nodeKind) {
+ case Type.ELEMENT:
+ return ((Element) node).getNamespaceURI();
+ case Type.ATTRIBUTE:
+ return ((Attribute) node).getNamespaceURI();
+ default:
+ return "";
+ }
+ }
+
+ /**
+ * Get the display name of this node. For elements and attributes this is
+ * [prefix:]localname. For unnamed nodes, it is an empty string.
+ *
+ * @return The display name of this node. For a node with no name, return an
+ * empty string.
+ */
+
+ public String getDisplayName() {
+ switch (nodeKind) {
+ case Type.ELEMENT:
+ return ((Element) node).getQualifiedName();
+ case Type.ATTRIBUTE:
+ return ((Attribute) node).getQualifiedName();
+ case Type.PROCESSING_INSTRUCTION:
+ return ((ProcessingInstruction) node).getTarget();
+ default:
+ return "";
+ }
+ }
+
+ /**
+ * Get the NodeInfo object representing the parent of this node
+ */
+
+ public NodeInfo getParent() {
+ if (parent == null) {
+ ParentNode p = node.getParent();
+ if (p != null) parent = makeWrapper(p, docWrapper);
+ }
+ return parent;
+ }
+
+ /**
+ * Get the index position of this node among its siblings (starting from 0)
+ */
+
+ public int getSiblingPosition() {
+ if (index != -1) return index;
+ switch (nodeKind) {
+ case Type.ATTRIBUTE: {
+ Attribute att = (Attribute) node;
+ Element p = (Element) att.getParent();
+ if (p == null) return 0;
+ for (int i=p.getAttributeCount(); --i >= 0;) {
+ if (p.getAttribute(i) == att) {
+ index = i;
+ return i;
+ }
+ }
+ throw new IllegalStateException("XOM node not linked to parent node");
+ }
+
+ default: {
+ ParentNode p = node.getParent();
+ int i = (p == null ? 0 : p.indexOf(node));
+ if (i == -1) throw new IllegalStateException("XOM node not linked to parent node");
+ index = i;
+ return index;
+ }
+ }
+ }
+
+ /**
+ * Return an iteration over the nodes reached by the given axis from this
+ * node
+ *
+ * @param axisNumber
+ * the axis to be used
+ * @return a SequenceIterator that scans the nodes reached by the axis in
+ * turn.
+ */
+
+ public AxisIterator iterateAxis(byte axisNumber) {
+ return iterateAxis(axisNumber, AnyNodeTest.getInstance());
+ }
+
+ /**
+ * Return an iteration over the nodes reached by the given axis from this
+ * node
+ *
+ * @param axisNumber
+ * the axis to be used
+ * @param nodeTest
+ * A pattern to be matched by the returned nodes
+ * @return a SequenceIterator that scans the nodes reached by the axis in
+ * turn.
+ */
+
+ public AxisIterator iterateAxis(byte axisNumber, NodeTest nodeTest) {
+ // for clarifications, see the W3C specs or:
+ // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/xmlsdk/h...
+ switch (axisNumber) {
+ case Axis.ANCESTOR:
+ return new AncestorAxisIterator(this, false, nodeTest);
+
+ case Axis.ANCESTOR_OR_SELF:
+ return new AncestorAxisIterator(this, true, nodeTest);
+
+ case Axis.ATTRIBUTE:
+ if (nodeKind != Type.ELEMENT || ((Element) node).getAttributeCount() == 0) {
+ return EmptyIterator.getInstance();
+ } else {
+ return new AttributeAxisIterator(this, nodeTest);
+ }
+
+ case Axis.CHILD:
+ if (hasChildNodes()) {
+ return new ChildAxisIterator(this, true, true, nodeTest);
+ } else {
+ return EmptyIterator.getInstance();
+ }
+
+ case Axis.DESCENDANT:
+ if (hasChildNodes()) {
+ return new DescendantAxisIterator(this, false, false, nodeTest);
+ } else {
+ return EmptyIterator.getInstance();
+ }
+
+ case Axis.DESCENDANT_OR_SELF:
+ if (hasChildNodes()) {
+ return new DescendantAxisIterator(this, true, false, nodeTest);
+ } else {
+ return filteredSingleton(this, nodeTest);
+ }
+
+ case Axis.FOLLOWING:
+ if (getParent() == null) {
+ return EmptyIterator.getInstance();
+ } else {
+ return new DescendantAxisIterator(this, false, true, nodeTest);
+ }
+
+ case Axis.FOLLOWING_SIBLING:
+ if (nodeKind == Type.ATTRIBUTE || getParent() == null) {
+ return EmptyIterator.getInstance();
+ } else {
+ return new ChildAxisIterator(this, false, true, nodeTest);
+ }
+
+ case Axis.NAMESPACE:
+ if (nodeKind == Type.ELEMENT) {
+ return NamespaceIterator.makeIterator(this, nodeTest);
+ } else {
+ return EmptyIterator.getInstance();
+ }
+
+ case Axis.PARENT:
+ if (getParent() == null) {
+ return EmptyIterator.getInstance();
+ } else {
+ return filteredSingleton(getParent(), nodeTest);
+ }
+
+ case Axis.PRECEDING:
+ return new PrecedingAxisIterator(this, false, nodeTest);
+// return new Navigator.AxisFilter(
+// new Navigator.PrecedingEnumeration(this, false), nodeTest);
+
+ case Axis.PRECEDING_SIBLING:
+ if (nodeKind == Type.ATTRIBUTE || getParent() == null) {
+ return EmptyIterator.getInstance();
+ } else {
+ return new ChildAxisIterator(this, false, false, nodeTest);
+ }
+
+ case Axis.SELF:
+ return filteredSingleton(this, nodeTest);
+
+ case Axis.PRECEDING_OR_ANCESTOR:
+ // This axis is used internally by saxon for the xsl:number implementation,
+ // it returns the union of the preceding axis and the ancestor axis.
+ return new PrecedingAxisIterator(this, true, nodeTest);
+// return new Navigator.AxisFilter(new Navigator.PrecedingEnumeration(
+// this, true), nodeTest);
+
+ default:
+ throw new IllegalArgumentException("Unknown axis number " + axisNumber);
+ }
+ }
+
+// private static AxisIterator makeSingleIterator(NodeWrapper wrapper, NodeTest nodeTest) {
+// if (nodeTest == AnyNodeTest.getInstance() || nodeTest.matches(wrapper))
+// return SingletonIterator.makeIterator(wrapper);
+// else
+// return EmptyIterator.getInstance();
+// }
+
+ /**
+ * Get the value of a given attribute of this node
+ *
+ * @param fingerprint
+ * The fingerprint of the attribute name
+ * @return the attribute value if it exists or null if not
+ */
+
+ public String getAttributeValue(int fingerprint) {
+ if (nodeKind == Type.ELEMENT) {
+ NamePool pool = docWrapper.getNamePool();
+ String localName = pool.getLocalName(fingerprint);
+ String uri = pool.getURI(fingerprint);
+ Attribute att = ((Element) node).getAttribute(localName, uri);
+ if (att != null) return att.getValue();
+ }
+ return null;
+ }
+
+ /**
+ * Get the root node of the tree containing this node
+ *
+ * @return the NodeInfo representing the top-level ancestor of this node.
+ * This will not necessarily be a document node
+ */
+
+ public NodeInfo getRoot() {
+ return docWrapper;
+ }
+
+ /**
+ * Get the root node, if it is a document node.
+ *
+ * @return the DocumentInfo representing the containing document.
+ */
+
+ public DocumentInfo getDocumentRoot() {
+ if (docWrapper.node instanceof Document) {
+ return docWrapper;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Determine whether the node has any children. <br />
+ * Note: the result is equivalent to <br />
+ * getEnumeration(Axis.CHILD, AnyNodeTest.getInstance()).hasNext()
+ */
+
+ public boolean hasChildNodes() {
+ return node.getChildCount() > 0;
+ }
+
+ /**
+ * Get a character string that uniquely identifies this node. Note:
+ * a.isSameNode(b) if and only if generateId(a)==generateId(b)
+ *
+ * @param buffer a buffer to contain a string that uniquely identifies this node, across all documents
+ */
+
+ public void generateId(FastStringBuffer buffer) {
+ Navigator.appendSequentialKey(this, buffer, true);
+ //buffer.append(Navigator.getSequentialKey(this));
+ }
+
+ /**
+ * Get the document number of the document containing this node. For a
+ * free-standing orphan node, just return the hashcode.
+ */
+
+ public int getDocumentNumber() {
+ return docWrapper.getDocumentNumber();
+ }
+
+ /**
+ * Copy this node to a given outputter (deep copy)
+ */
+
+ public void copy(Receiver out, int whichNamespaces,
+ boolean copyAnnotations, int locationId) throws XPathException {
+ Navigator.copy(this, out, docWrapper.getNamePool(), whichNamespaces,
+ copyAnnotations, locationId);
+ }
+
+ /**
+ * Get all namespace undeclarations and undeclarations defined on this element.
+ *
+ * @param buffer If this is non-null, and the result array fits in this buffer, then the result
+ * may overwrite the contents of this array, to avoid the cost of allocating a new array on the heap.
+ * @return An array of integers representing the namespace declarations and undeclarations present on
+ * this element. For a node other than an element, return null. Otherwise, the returned array is a
+ * sequence of namespace codes, whose meaning may be interpreted by reference to the name pool. The
+ * top half word of each namespace code represents the prefix, the bottom half represents the URI.
+ * If the bottom half is zero, then this is a namespace undeclaration rather than a declaration.
+ * The XML namespace is never included in the list. If the supplied array is larger than required,
+ * then the first unused entry will be set to -1.
+ * <p/>
+ * <p>For a node other than an element, the method returns null.</p>
+ */
+
+ public int[] getDeclaredNamespaces(int[] buffer) {
+ if (node instanceof Element) {
+ Element elem = (Element)node;
+ int size = elem.getNamespaceDeclarationCount();
+ if (size == 0) {
+ return EMPTY_NAMESPACE_LIST;
+ }
+ int[] result = (buffer != null && size <= buffer.length ? buffer : new int[size]);
+ NamePool pool = getNamePool();
+ for (int i=0; i < size; i++) {
+ String prefix = elem.getNamespacePrefix(i);
+ String uri = elem.getNamespaceURI(prefix);
+ result[i] = pool.allocateNamespaceCode(prefix, uri);
+ }
+ if (size < result.length) {
+ result[size] = -1;
+ }
+ return result;
+ } else {
+ return null;
+ }
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // Axis enumeration classes
+ ///////////////////////////////////////////////////////////////////////////////
+
+ /**
+ * Handles the ancestor axis in a rather direct manner.
+ */
+ private final class AncestorAxisIterator extends AxisIteratorImpl {
+
+ private NodeWrapper start;
+ private boolean includeSelf;
+
+ private NodeTest nodeTest;
+
+ public AncestorAxisIterator(NodeWrapper start, boolean includeSelf, NodeTest test) {
+ // use lazy instead of eager materialization (performance)
+ this.start = start;
+ if (test == AnyNodeTest.getInstance()) test = null;
+ this.nodeTest = test;
+ if (!includeSelf) this.current = start;
+ this.includeSelf = includeSelf;
+ this.position = 0;
+ }
+
+ public Item next() {
+ NodeInfo curr;
+ do { // until we find a match
+ curr = advance();
+ }
+ while (curr != null && nodeTest != null && (! nodeTest.matches(curr)));
+
+ if (curr != null) position++;
+ current = curr;
+ return curr;
+ }
+
+ private NodeInfo advance() {
+ if (current == null)
+ current = start;
+ else
+ current = current.getParent();
+
+ return current;
+ }
+
+ public Item current() {
+ return current;
+ }
+
+ public SequenceIterator getAnother() {
+ return new AncestorAxisIterator(start, includeSelf, nodeTest);
+ }
+
+ public int getProperties() {
+ return 0;
+ }
+
+ } // end of class AncestorAxisIterator
+
+ /**
+ * Handles the attribute axis in a rather direct manner.
+ */
+ private final class AttributeAxisIterator extends AxisIteratorImpl {
+
+ private NodeWrapper start;
+
+ private int cursor;
+
+ private NodeTest nodeTest;
+
+ public AttributeAxisIterator(NodeWrapper start, NodeTest test) {
+ // use lazy instead of eager materialization (performance)
+ this.start = start;
+ if (test == AnyNodeTest.getInstance()) test = null;
+ this.nodeTest = test;
+ this.position = 0;
+ this.cursor = 0;
+ }
+
+ public Item next() {
+ NodeInfo curr;
+ do { // until we find a match
+ curr = advance();
+ }
+ while (curr != null && nodeTest != null && (! nodeTest.matches(curr)));
+
+ if (curr != null) position++;
+ current = curr;
+ return curr;
+ }
+
+ private NodeInfo advance() {
+ Element elem = (Element) start.node;
+ if (cursor == elem.getAttributeCount()) return null;
+ NodeInfo curr = makeWrapper(elem.getAttribute(cursor), docWrapper, start, cursor);
+ cursor++;
+ return curr;
+ }
+
+ public Item current() {
+ return current;
+ }
+
+ public SequenceIterator getAnother() {
+ return new AttributeAxisIterator(start, nodeTest);
+ }
+
+ public int getProperties() {
+ return 0;
+ }
+
+ } // end of class AttributeAxisIterator
+
+ /**
+ * The class ChildAxisIterator handles not only the child axis, but also the
+ * following-sibling and preceding-sibling axes. It can also iterate the
+ * children of the start node in reverse order, something that is needed to
+ * support the preceding and preceding-or-ancestor axes (the latter being
+ * used by xsl:number)
+ */
+ private final class ChildAxisIterator extends AxisIteratorImpl {
+
+ private NodeWrapper start;
+ private NodeWrapper commonParent;
+ private int ix;
+ private boolean downwards; // iterate children of start node (not siblings)
+ private boolean forwards; // iterate in document order (not reverse order)
+
+ private ParentNode par;
+ private int cursor;
+
+ private NodeTest nodeTest;
+
+ private ChildAxisIterator(NodeWrapper start, boolean downwards, boolean forwards, NodeTest test) {
+ this.start = start;
+ this.downwards = downwards;
+ this.forwards = forwards;
+
+ if (test == AnyNodeTest.getInstance()) test = null;
+ this.nodeTest = test;
+ this.position = 0;
+
+ if (downwards)
+ commonParent = start;
+ else
+ commonParent = (NodeWrapper) start.getParent();
+
+ par = (ParentNode) commonParent.node;
+ if (downwards) {
+ ix = (forwards ? 0 : par.getChildCount());
+ } else {
+ // find the start node among the list of siblings
+// ix = start.getSiblingPosition();
+ ix = par.indexOf(start.node);
+ if (forwards) ix++;
+ }
+ cursor = ix;
+ if (!downwards && !forwards) ix--;
+ }
+
+ public Item next() {
+ NodeInfo curr;
+ do { // until we find a match
+ curr = advance();
+ }
+ while (curr != null && nodeTest != null && (! nodeTest.matches(curr)));
+
+ if (curr != null) position++;
+ current = curr;
+ return curr;
+ }
+
+ private NodeInfo advance() {
+ Node nextChild;
+ do {
+ if (forwards) {
+ if (cursor == par.getChildCount()) return null;
+ nextChild = par.getChild(cursor++);
+ } else { // backwards
+ if (cursor == 0) return null;
+ nextChild = par.getChild(--cursor);
+ }
+ } while (nextChild instanceof DocType);
+ // DocType is not an XPath node; can occur for /child::node()
+
+ NodeInfo curr = makeWrapper(nextChild, docWrapper, commonParent, ix);
+ ix += (forwards ? 1 : -1);
+ return curr;
+ }
+
+ public Item current() {
+ return current;
+ }
+
+ public SequenceIterator getAnother() {
+ return new ChildAxisIterator(start, downwards, forwards, nodeTest);
+ }
+
+ public int getProperties() {
+ return 0;
+ }
+ }
+
+ /**
+ * A bit of a misnomer; efficiently takes care of descendants,
+ * descentants-or-self as well as "following" axis.
+ * "includeSelf" must be false for the following axis.
+ * Uses simple and effective O(1) backtracking via indexOf().
+ */
+ private final class DescendantAxisIterator extends AxisIteratorImpl {
+
+ private NodeWrapper start;
+ private boolean includeSelf;
+ private boolean following;
+
+ private Node anchor; // so we know where to stop the scan
+ private Node currNode;
+ private boolean moveToNextSibling;
+
+ private NodeTest nodeTest;
+
+ private String testLocalName;
+ private String testURI;
+
+ public DescendantAxisIterator(NodeWrapper start, boolean includeSelf, boolean following, NodeTest test) {
+ this.start = start;
+ this.includeSelf = includeSelf;
+ this.following = following;
+ this.moveToNextSibling = following;
+
+ if (!following) anchor = start.node;
+ if (!includeSelf) currNode = start.node;
+
+ if (test == AnyNodeTest.getInstance()) { // performance hack
+ test = null; // mark as AnyNodeTest
+ }
+ else if (test instanceof NameTest) {
+ NameTest nt = (NameTest) test;
+ if (nt.getPrimitiveType() == Type.ELEMENT) { // performance hack
+ // mark as element name test
+ NamePool pool = getNamePool();
+ this.testLocalName = pool.getLocalName(nt.getFingerprint());
+ this.testURI = pool.getURI(nt.getFingerprint());
+ }
+ }
+ else if (test instanceof NodeKindTest) {
+ if (test.getPrimitiveType() == Type.ELEMENT) { // performance hack
+ // mark as element type test
+ this.testLocalName = "";
+ this.testURI = null;
+ }
+ }
+ this.nodeTest = test;
+ this.position = 0;
+ }
+
+ public Item next() {
+ NodeInfo curr;
+ do { // until we find a match
+ curr = advance();
+ }
+ while (curr != null && nodeTest != null && (! nodeTest.matches(curr)));
+
+ if (curr != null) position++;
+ current = curr;
+ return curr;
+ }
+
+ // might look expensive at first glance - but it's not
+ private NodeInfo advance() {
+ if (currNode == null) { // if includeSelf
+ currNode = start.node;
+ return start;
+ }
+
+ int i;
+ do {
+ i = 0;
+ Node p = currNode;
+
+ if (p.getChildCount() == 0 || moveToNextSibling) { // move to next sibling
+
+ moveToNextSibling = false; // do it just once
+ while (true) {
+ // if we've reached the root we're done scanning
+ p = currNode.getParent();
+ if (p == null) return null;
+
+ // Note: correct even if currNode is an attribute.
+ // Performance is particularly good with the O(1) patch
+ // for XOM's ParentNode.indexOf()
+ i = currNode.getParent().indexOf(currNode) + 1;
+
+ if (i < p.getChildCount()) {
+ break; // break out of while(true) loop; move to next sibling
+ }
+ else { // reached last sibling; move up
+ currNode = p;
+ // if we've come all the way back to the start anchor we're done
+ if (p == anchor) return null;
+ }
+ }
+ }
+ currNode = p.getChild(i);
+ } while (!conforms(currNode));
+
+ // note the null here: makeNodeWrapper(parent, ...) is fast, so it
+ // doesn't really matter that we don't keep a link to it.
+ // In fact, it makes objects more short lived, easing pressure on
+ // the VM allocator and collector for tenured heaps.
+ return makeWrapper(currNode, docWrapper, null, i);
+ }
+
+ // avoids NodeWrapper allocation when there's clearly a mismatch (common case)
+ private boolean conforms(Node node) {
+ if (this.testLocalName != null) { // element test?
+ if (!(node instanceof Element)) return false;
+ if (this.testURI == null) return true; // pure element type test
+
+ // element name test
+ Element elem = (Element) node;
+ return this.testLocalName.equals(elem.getLocalName()) &&
+ this.testURI.equals(elem.getNamespaceURI());
+ }
+ else { // DocType is not an XPath node; can occur for /descendants::node()
+ return !(node instanceof DocType);
+ }
+ }
+
+ public Item current() {
+ return current;
+ }
+
+ public SequenceIterator getAnother() {
+ return new DescendantAxisIterator(start, includeSelf, following, nodeTest);
+ }
+
+ public int getProperties() {
+ return 0;
+ }
+ }
+
+ /**
+ * Efficiently takes care of preceding axis and Saxon internal preceding-or-ancestor axis.
+ * Uses simple and effective O(1) backtracking via indexOf().
+ * Implemented along similar lines as DescendantAxisIterator.
+ */
+ private final class PrecedingAxisIterator extends AxisIteratorImpl {
+
+ private NodeWrapper start;
+ private boolean includeAncestors;
+
+ private Node currNode;
+ private ParentNode nextAncestor; // next ancestors to skip if !includeAncestors
+
+ private NodeTest nodeTest;
+
+ private String testLocalName;
+ private String testURI;
+
+ public PrecedingAxisIterator(NodeWrapper start, boolean includeAncestors, NodeTest test) {
+ this.start = start;
+ this.includeAncestors = includeAncestors;
+ this.currNode = start.node;
+ if (includeAncestors)
+ nextAncestor = null;
+ else
+ nextAncestor = start.node.getParent();
+
+ if (test == AnyNodeTest.getInstance()) { // performance hack
+ test = null; // mark as AnyNodeTest
+ }
+ else if (test instanceof NameTest) {
+ NameTest nt = (NameTest) test;
+ if (nt.getPrimitiveType() == Type.ELEMENT) { // performance hack
+ // mark as element name test
+ NamePool pool = getNamePool();
+ this.testLocalName = pool.getLocalName(nt.getFingerprint());
+ this.testURI = pool.getURI(nt.getFingerprint());
+ }
+ }
+ else if (test instanceof NodeKindTest) {
+ if (test.getPrimitiveType() == Type.ELEMENT) { // performance hack
+ // mark as element type test
+ this.testLocalName = "";
+ this.testURI = null;
+ }
+ }
+ this.nodeTest = test;
+ this.position = 0;
+ }
+
+ public Item next() {
+ NodeInfo curr;
+ do { // until we find a match
+ curr = advance();
+ }
+ while (curr != null && nodeTest != null && (! nodeTest.matches(curr)));
+
+ if (curr != null) position++;
+ current = curr;
+ return curr;
+ }
+
+ // might look expensive at first glance - but it's not
+ private NodeInfo advance() {
+ int i;
+ do {
+ Node p;
+
+ while (true) {
+ // if we've reached the root we're done scanning
+// System.out.println("p="+p);
+ p = currNode.getParent();
+ if (p == null) return null;
+
+ // Note: correct even if currNode is an attribute.
+ // Performance is particularly good with the O(1) patch
+ // for XOM's ParentNode.indexOf()
+ i = currNode.getParent().indexOf(currNode) - 1;
+
+ if (i >= 0) { // move to next sibling's last descendant node
+ p = p.getChild(i); // move to next sibling
+ int j;
+ while ((j = p.getChildCount()-1) >= 0) { // move to last descendant node
+ p = p.getChild(j);
+ i = j;
+ }
+ break; // break out of while(true) loop
+ }
+ else { // there are no more siblings; move up
+ // if !includeAncestors skip the ancestors of the start node
+ // assert p != null
+ if (p != nextAncestor) break; // break out of while(true) loop
+
+ nextAncestor = nextAncestor.getParent();
+ currNode = p;
+ }
+ }
+ currNode = p;
+
+ } while (!conforms(currNode));
+
+ // note the null here: makeNodeWrapper(parent, ...) is fast, so it
+ // doesn't really matter that we don't keep a link to it.
+ // In fact, it makes objects more short lived, easing pressure on
+ // the VM allocator and collector for tenured heaps.
+ return makeWrapper(currNode, docWrapper, null, i);
+ }
+
+ // avoids NodeWrapper allocation when there's clearly a mismatch (common case)
+ // same as for DescendantAxisIterator
+ private boolean conforms(Node node) {
+ if (this.testLocalName != null) { // element test?
+ if (!(node instanceof Element)) return false;
+ if (this.testURI == null) return true; // pure element type test
+
+ // element name test
+ Element elem = (Element) node;
+ return this.testLocalName.equals(elem.getLocalName()) &&
+ this.testURI.equals(elem.getNamespaceURI());
+ }
+ else { // DocType is not an XPath node
+ return !(node instanceof DocType);
+ }
+ }
+
+ public Item current() {
+ return current;
+ }
+
+ public SequenceIterator getAnother() {
+ return new PrecedingAxisIterator(start, includeAncestors, nodeTest);
+ }
+
+ public int getProperties() {
+ return 0;
+ }
+ }
+
+ private static AxisIterator filteredSingleton(NodeInfo node, NodeTest nodeTest) {
+// return Navigator.filteredSingleton(node, nodeTest); // saxon >= 8.7
+ if (node != null && (nodeTest == AnyNodeTest.getInstance() || nodeTest.matches(node))) {
+ return SingleNodeIterator.makeIterator(node);
+ } else {
+ return EmptyIterator.getInstance();
+ }
+ }
+
+ @Override
+ public int getColumnNumber() {
+ return -1;
+ }
+
+ @Override
+ public boolean isId() {
+ return false;
+ }
+
+ @Override
+ public boolean isIdref() {
+ return false;
+ }
+
+ @Override
+ public boolean isNilled() {
+ return false;
+ }
+
+}
+
+//
+// The contents of this file are subject to the Mozilla Public License Version
+// 1.0 (the "License");
+// you may not use this file except in compliance with the License. You may
+// obtain a copy of the
+// License at http://www.mozilla.org/MPL/
+//
+// Software distributed under the License is distributed on an "AS IS" basis,
+// WITHOUT WARRANTY OF ANY KIND, either express or implied.
+// See the License for the specific language governing rights and limitations
+// under the License.
+//
+// The Original Code is: all this file.
+//
+// The Initial Developer of the Original Code is Michael Kay, with extensive
+// rewriting by Wolfgang Hoschek
+//
+// Portions created by (your name) are Copyright (C) (your legal entity). All
+// Rights Reserved.
+//
+// Contributor(s): none.
+//
Property changes on: branches/7.4.x/engine/src/main/java/org/teiid/query/xquery/saxon/NodeWrapper.java
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Modified: branches/7.4.x/engine/src/main/java/org/teiid/query/xquery/saxon/PathMapFilter.java
===================================================================
--- branches/7.4.x/engine/src/main/java/org/teiid/query/xquery/saxon/PathMapFilter.java 2011-06-10 16:28:08 UTC (rev 3241)
+++ branches/7.4.x/engine/src/main/java/org/teiid/query/xquery/saxon/PathMapFilter.java 2011-06-10 17:50:13 UTC (rev 3242)
@@ -184,5 +184,13 @@
super.endElement();
}
}
+
+ @Override
+ public void startContent() throws XPathException {
+ MatchContext context = matchContext.getLast();
+ if (context.matchedElement) {
+ super.startContent();
+ }
+ }
}
\ No newline at end of file
Modified: branches/7.4.x/engine/src/main/java/org/teiid/query/xquery/saxon/SaxonXQueryExpression.java
===================================================================
--- branches/7.4.x/engine/src/main/java/org/teiid/query/xquery/saxon/SaxonXQueryExpression.java 2011-06-10 16:28:08 UTC (rev 3241)
+++ branches/7.4.x/engine/src/main/java/org/teiid/query/xquery/saxon/SaxonXQueryExpression.java 2011-06-10 17:50:13 UTC (rev 3242)
@@ -23,9 +23,11 @@
package org.teiid.query.xquery.saxon;
import java.io.IOException;
+import java.io.InputStream;
import java.io.Writer;
import java.sql.SQLXML;
import java.util.Arrays;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
@@ -61,6 +63,7 @@
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;
@@ -69,6 +72,12 @@
import net.sf.saxon.type.ItemType;
import net.sf.saxon.type.TypeHierarchy;
import net.sf.saxon.value.SequenceType;
+import nu.xom.Builder;
+import nu.xom.Element;
+import nu.xom.Nodes;
+import nu.xom.ParsingException;
+import nux.xom.xquery.StreamingPathFilter;
+import nux.xom.xquery.StreamingTransform;
import org.teiid.api.exception.query.QueryResolverException;
import org.teiid.common.buffer.BufferManager;
@@ -80,6 +89,9 @@
import org.teiid.core.types.XMLTranslator;
import org.teiid.core.types.XMLType;
import org.teiid.core.types.XMLType.Type;
+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.function.source.XMLSystemFunctions;
@@ -88,11 +100,34 @@
import org.teiid.query.sql.symbol.DerivedColumn;
import org.teiid.query.sql.symbol.XMLNamespaces;
import org.teiid.query.sql.symbol.XMLNamespaces.NamespaceItem;
+import org.teiid.query.util.CommandContext;
import org.teiid.translator.WSConnection.Util;
@SuppressWarnings("serial")
public class SaxonXQueryExpression {
+ public static final Properties DEFAULT_OUTPUT_PROPERTIES = new Properties();
+ {
+ DEFAULT_OUTPUT_PROPERTIES.setProperty(OutputKeys.METHOD, "xml"); //$NON-NLS-1$
+ //props.setProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
+ DEFAULT_OUTPUT_PROPERTIES.setProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); //$NON-NLS-1$
+ }
+
+ private static Nodes NONE = new Nodes();
+ private static InputStream FAKE_IS = new InputStream() {
+
+ @Override
+ public int read() throws IOException {
+ return 0;
+ }
+ };
+
+ public interface RowProcessor {
+
+ void processRow(NodeInfo row);
+
+ }
+
public static class Result {
public SequenceIterator iter;
public List<Source> sources = new LinkedList<Source>();
@@ -147,16 +182,20 @@
}
};
- private net.sf.saxon.query.XQueryExpression xQuery;
+ private XQueryExpression xQuery;
+ private String xQueryString;
+ private Map<String, String> namespaceMap = new HashMap<String, String>();
private Configuration config = new Configuration();
private PathMapRoot contextRoot;
+ private StreamingPathFilter streamingPathFilter;
public SaxonXQueryExpression(String xQueryString, XMLNamespaces namespaces, List<DerivedColumn> passing, List<XMLTable.XMLColumn> columns)
throws QueryResolverException {
config.setErrorListener(ERROR_LISTENER);
+ this.xQueryString = xQueryString;
StaticQueryContext context = new StaticQueryContext(config);
IndependentContext ic = new IndependentContext(config);
-
+ namespaceMap.put("", ""); //$NON-NLS-1$ //$NON-NLS-2$
if (namespaces != null) {
for (NamespaceItem item : namespaces.getNamespaceItems()) {
if (item.getPrefix() == null) {
@@ -166,10 +205,12 @@
} else {
context.setDefaultElementNamespace(item.getUri());
ic.setDefaultElementNamespace(item.getUri());
+ namespaceMap.put("", item.getUri()); //$NON-NLS-1$
}
} else {
context.declareNamespace(item.getPrefix(), item.getUri());
ic.declareNamespace(item.getPrefix(), item.getUri());
+ namespaceMap.put(item.getPrefix(), item.getUri());
}
}
}
@@ -211,6 +252,13 @@
}
public void useDocumentProjection(List<XMLTable.XMLColumn> columns, AnalysisRecord record) {
+ try {
+ streamingPathFilter = StreamingUtils.getStreamingPathFilter(xQueryString, namespaceMap);
+ } catch (IllegalArgumentException e) {
+ if (record.recordDebug()) {
+ record.println("Document streaming will not be used: " + e.getMessage()); //$NON-NLS-1$
+ }
+ }
this.contextRoot = null;
PathMap map = this.xQuery.getPathMap();
PathMapRoot parentRoot;
@@ -246,8 +294,8 @@
return;
}
} else {
- for (Iterator iter = finalNodes.iterator(); iter.hasNext(); ) {
- PathMapNode subNode = (PathMapNode)iter.next();
+ for (Iterator<PathMapNode> iter = finalNodes.iterator(); iter.hasNext(); ) {
+ PathMapNode subNode = iter.next();
subNode.createArc(new AxisExpression(Axis.DESCENDANT_OR_SELF, AnyNodeTest.getInstance()));
}
}
@@ -265,6 +313,24 @@
}
this.contextRoot = parentRoot;
}
+
+ public static final boolean[] isValidAncestorAxis =
+ {
+ false, // ANCESTOR
+ false, // ANCESTOR_OR_SELF;
+ true, // ATTRIBUTE;
+ false, // CHILD;
+ false, // DESCENDANT;
+ false, // DESCENDANT_OR_SELF;
+ false, // FOLLOWING;
+ false, // FOLLOWING_SIBLING;
+ true, // NAMESPACE;
+ true, // PARENT;
+ false, // PRECEDING;
+ false, // PRECEDING_SIBLING;
+ true, // SELF;
+ false, // PRECEDING_OR_ANCESTOR;
+ };
private PathMapRoot projectColumns(PathMapRoot parentRoot, List<XMLTable.XMLColumn> columns, PathMapNode finalNode, AnalysisRecord record) {
for (XMLColumn xmlColumn : columns) {
@@ -293,6 +359,9 @@
continue;
}
for (PathMapArc arc : subContextRoot.getArcs()) {
+ if (streamingPathFilter != null && !validateColumnForStreaming(record, xmlColumn, arc)) {
+ streamingPathFilter = null;
+ }
finalNode.createArc(arc.getStep(), arc.getTarget());
}
HashSet<PathMapNode> subFinalNodes = new HashSet<PathMapNode>();
@@ -319,6 +388,54 @@
return newMap.reduceToDownwardsAxes(newRoot);
}
+ private boolean validateColumnForStreaming(AnalysisRecord record,
+ XMLColumn xmlColumn, PathMapArc arc) {
+ boolean ancestor = false;
+ LinkedList<PathMapArc> arcStack = new LinkedList<PathMapArc>();
+ arcStack.add(arc);
+ while (!arcStack.isEmpty()) {
+ PathMapArc current = arcStack.removeFirst();
+ byte axis = current.getStep().getAxis();
+ if (ancestor) {
+ if (current.getTarget().isReturnable()) {
+ if (axis != Axis.NAMESPACE && axis != Axis.ATTRIBUTE) {
+ if (record.recordDebug()) {
+ record.println("Document streaming will not be used, since the column path contains an invalid reverse axis " + xmlColumn.getPath()); //$NON-NLS-1$
+ }
+ return false;
+ }
+ }
+ if (!isValidAncestorAxis[axis]) {
+ if (record.recordDebug()) {
+ record.println("Document streaming will not be used, since the column path contains an invalid reverse axis " + xmlColumn.getPath()); //$NON-NLS-1$
+ }
+ return false;
+ }
+ } else if (!Axis.isSubtreeAxis[axis]) {
+ if (axis == Axis.PARENT
+ || axis == Axis.ANCESTOR
+ || axis == Axis.ANCESTOR_OR_SELF) {
+ if (current.getTarget().isReturnable()) {
+ if (record.recordDebug()) {
+ record.println("Document streaming will not be used, since the column path contains an invalid reverse axis " + xmlColumn.getPath()); //$NON-NLS-1$
+ }
+ return false;
+ }
+ ancestor = true;
+ } else {
+ if (record.recordDebug()) {
+ record.println("Document streaming will not be used, since the column path may not reference an ancestor or subtree " + xmlColumn.getPath()); //$NON-NLS-1$
+ }
+ return false;
+ }
+ }
+ for (PathMapArc pathMapArc : current.getTarget().getArcs()) {
+ arcStack.add(pathMapArc);
+ }
+ }
+ return true;
+ }
+
private void addReturnedArcs(XMLColumn xmlColumn, PathMapNode subNode) {
if (xmlColumn.getSymbol().getType() == DataTypeManager.DefaultDataClasses.XML) {
subNode.createArc(new AxisExpression(Axis.DESCENDANT_OR_SELF, AnyNodeTest.getInstance()));
@@ -371,7 +488,7 @@
}
}
- public Result evaluateXQuery(Object context, Map<String, Object> parameterValues) throws TeiidProcessingException {
+ public Result evaluateXQuery(Object context, Map<String, Object> parameterValues, final RowProcessor processor, CommandContext commandContext) throws TeiidProcessingException {
DynamicQueryContext dynamicContext = new DynamicQueryContext(config);
Result result = new Result();
@@ -399,6 +516,39 @@
AugmentedSource sourceInput = AugmentedSource.makeAugmentedSource(source);
sourceInput.addFilter(filter);
source = sourceInput;
+
+ //use streamable processing instead
+ if (streamingPathFilter != null && processor != null) {
+ if (LogManager.isMessageToBeRecorded(LogConstants.CTX_DQP, MessageLevel.DETAIL)) {
+ LogManager.logDetail(LogConstants.CTX_DQP, "Using stream processing for evaluation of", this.xQueryString); //$NON-NLS-1$
+ }
+ //set to non-blocking in case default expression evaluation blocks
+ boolean isNonBlocking = commandContext.isNonBlocking();
+ commandContext.setNonBlocking(true);
+
+ final StreamingTransform myTransform = new StreamingTransform() {
+ public Nodes transform(Element elem) {
+ processor.processRow(StreamingUtils.wrap(elem, config));
+ return NONE;
+ }
+ };
+
+ Builder builder = new Builder(new SaxonReader(config, sourceInput), false,
+ streamingPathFilter.createNodeFactory(null, myTransform));
+ try {
+ //the builder is hard wired to parse the source, but the api will throw an exception if the stream is null
+ builder.build(FAKE_IS);
+ return result;
+ } catch (ParsingException e) {
+ throw new TeiidProcessingException(e, QueryPlugin.Util.getString("SaxonXQueryExpression.bad_context")); //$NON-NLS-1$
+ } catch (IOException e) {
+ throw new TeiidProcessingException(e, QueryPlugin.Util.getString("SaxonXQueryExpression.bad_context")); //$NON-NLS-1$
+ } finally {
+ if (!isNonBlocking) {
+ commandContext.setNonBlocking(false);
+ }
+ }
+ }
}
DocumentInfo doc;
try {
@@ -429,17 +579,7 @@
XMLType.Type type = Type.CONTENT;
if (item instanceof NodeInfo) {
NodeInfo info = (NodeInfo)item;
- switch (info.getNodeKind()) {
- case net.sf.saxon.type.Type.DOCUMENT:
- type = Type.DOCUMENT;
- break;
- case net.sf.saxon.type.Type.ELEMENT:
- type = Type.ELEMENT;
- break;
- case net.sf.saxon.type.Type.TEXT:
- type = Type.TEXT;
- break;
- }
+ type = getType(info);
}
Item next = iter.next();
if (next != null) {
@@ -450,17 +590,29 @@
@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(iter.getAnother(), config, writer, props);
+ QueryResult.serializeSequence(iter.getAnother(), config, writer, DEFAULT_OUTPUT_PROPERTIES);
}
});
XMLType value = new XMLType(xml);
value.setType(type);
return value;
}
+
+ public static XMLType.Type getType(NodeInfo info) {
+ switch (info.getNodeKind()) {
+ case net.sf.saxon.type.Type.DOCUMENT:
+ return Type.DOCUMENT;
+ case net.sf.saxon.type.Type.ELEMENT:
+ return Type.ELEMENT;
+ case net.sf.saxon.type.Type.TEXT:
+ return Type.TEXT;
+ case net.sf.saxon.type.Type.COMMENT:
+ return Type.COMMENT;
+ case net.sf.saxon.type.Type.PROCESSING_INSTRUCTION:
+ return Type.PI;
+ }
+ return Type.CONTENT;
+ }
public Configuration getConfig() {
return config;
@@ -477,5 +629,9 @@
showArcs(sb, node, level + 1);
}
}
+
+ public boolean isStreaming() {
+ return streamingPathFilter != null;
+ }
}
Added: branches/7.4.x/engine/src/main/java/org/teiid/query/xquery/saxon/StreamingUtils.java
===================================================================
--- branches/7.4.x/engine/src/main/java/org/teiid/query/xquery/saxon/StreamingUtils.java (rev 0)
+++ branches/7.4.x/engine/src/main/java/org/teiid/query/xquery/saxon/StreamingUtils.java 2011-06-10 17:50:13 UTC (rev 3242)
@@ -0,0 +1,322 @@
+/*
+ * 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.query.xquery.saxon;
+
+import java.io.IOException;
+import java.util.Map;
+
+import net.sf.saxon.AugmentedSource;
+import net.sf.saxon.Configuration;
+import net.sf.saxon.event.ContentHandlerProxy;
+import net.sf.saxon.event.PipelineConfiguration;
+import net.sf.saxon.event.ProxyReceiver;
+import net.sf.saxon.event.Receiver;
+import net.sf.saxon.om.Name11Checker;
+import net.sf.saxon.om.NodeInfo;
+import net.sf.saxon.trans.XPathException;
+import nu.xom.DocType;
+import nu.xom.Node;
+import nux.xom.xquery.StreamingPathFilter;
+
+import org.xml.sax.ContentHandler;
+import org.xml.sax.DTDHandler;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXNotRecognizedException;
+import org.xml.sax.SAXNotSupportedException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.ext.LexicalHandler;
+
+final class StreamingUtils {
+ /**
+ * Converts a xom node into something readable by Saxon
+ * @param node
+ * @param config
+ * @return
+ */
+ static NodeInfo wrap(Node node, Configuration config) {
+ if (node == null)
+ throw new IllegalArgumentException("node must not be null"); //$NON-NLS-1$
+ if (node instanceof DocType)
+ throw new IllegalArgumentException("DocType can't be queried by XQuery/XPath"); //$NON-NLS-1$
+
+ Node root = node;
+ while (root.getParent() != null) {
+ root = root.getParent();
+ }
+
+ DocumentWrapper docWrapper = new DocumentWrapper(root, root.getBaseURI(), config);
+
+ return docWrapper.wrap(node);
+ }
+
+ /**
+ * Pre-parser that adds validation and handles a default name space
+ *
+ * TODO: add support for more general paths including node tests
+ * this could be done as a secondary expression applied to the
+ * context item
+ *
+ * @param locationPath
+ * @param prefixMap
+ * @return
+ */
+ public static StreamingPathFilter getStreamingPathFilter(String locationPath, Map<String, String> prefixMap) {
+ if (locationPath.indexOf("//") >= 0) //$NON-NLS-1$
+ throw new IllegalArgumentException("DESCENDANT axis is not supported"); //$NON-NLS-1$
+
+ String path = locationPath.trim();
+ if (path.startsWith("/")) path = path.substring(1); //$NON-NLS-1$
+ if (path.endsWith("/")) path = path.substring(0, path.length() - 1); //$NON-NLS-1$
+ path = path.trim();
+ String[] localNames = path.split("/"); //$NON-NLS-1$
+
+ if (localNames.length == 1) {
+ throw new IllegalArgumentException(locationPath + " refers to only the root element"); //$NON-NLS-1$
+ }
+
+ String fixedPath = ""; //$NON-NLS-1$
+
+ // parse prefix:localName pairs and resolve prefixes to namespaceURIs
+ for (int i = 0; i < localNames.length; i++) {
+ fixedPath += "/"; //$NON-NLS-1$
+ int k = localNames[i].indexOf(':');
+ if (k >= 0 && localNames[i].indexOf(':', k+1) >= 0)
+ throw new IllegalArgumentException(
+ "QName must not contain more than one colon: " //$NON-NLS-1$
+ + "qname='" + localNames[i] + "', path='" + path + "'"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ if (k <= 0) {
+ fixedPath += " :"; //$NON-NLS-1$
+ } else {
+ String prefix = localNames[i].substring(0, k).trim();
+ if (k >= localNames[i].length() - 1)
+ throw new IllegalArgumentException(
+ "Missing localName for prefix: " + "prefix='" //$NON-NLS-1$ //$NON-NLS-2$
+ + prefix + "', path='" + path + "', prefixes=" + prefixMap); //$NON-NLS-1$ //$NON-NLS-2$
+ fixedPath += prefix + ":"; //$NON-NLS-1$
+ } // end if
+
+ localNames[i] = localNames[i].substring(k + 1).trim();
+ if (!localNames[i].equals("*") && !Name11Checker.getInstance().isValidNCName(localNames[i])) { //$NON-NLS-1$
+ throw new IllegalArgumentException(localNames[i] + " is not a valid local name."); //$NON-NLS-1$
+ }
+ fixedPath += localNames[i];
+ }
+ return new StreamingPathFilter(fixedPath, prefixMap);
+ }
+
+}
+
+/**
+ * An {@link XMLReader} designed to bridge between the Saxon document projection logic and the XOM/NUX streaming logic.
+ */
+final class SaxonReader implements XMLReader {
+
+ private ContentHandler handler;
+ private LexicalHandler lexicalHandler;
+
+ private Configuration config;
+ private AugmentedSource source;
+
+ public SaxonReader(Configuration config, AugmentedSource source) {
+ this.config = config;
+ this.source = source;
+ }
+
+ @Override
+ public void setProperty(String name, Object value)
+ throws SAXNotRecognizedException, SAXNotSupportedException {
+ if ("http://xml.org/sax/properties/lexical-handler".equals(name)) { //$NON-NLS-1$
+ this.lexicalHandler = (LexicalHandler) value;
+ }
+ }
+
+ @Override
+ public void setFeature(String name, boolean value)
+ throws SAXNotRecognizedException, SAXNotSupportedException {
+ }
+
+ @Override
+ public void setErrorHandler(ErrorHandler handler) {
+ throw new UnsupportedOperationException();
+
+ }
+
+ @Override
+ public void setEntityResolver(EntityResolver resolver) {
+ throw new UnsupportedOperationException();
+
+ }
+
+ @Override
+ public void setDTDHandler(DTDHandler handler) {
+
+ }
+
+ @Override
+ public void setContentHandler(ContentHandler handler) {
+ this.handler = handler;
+ }
+
+ @Override
+ public void parse(String systemId) throws IOException, SAXException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void parse(InputSource input) throws IOException, SAXException {
+ ContentHandlerProxy chp = new ContentHandlerProxy();
+ chp.setLexicalHandler(lexicalHandler);
+ chp.setUnderlyingContentHandler(handler);
+ this.source.addFilter(new ContentHandlerProxyReceiver(chp));
+ try {
+ config.buildDocument(source);
+ } catch (XPathException e) {
+ throw new SAXException(e);
+ }
+ }
+
+ @Override
+ public Object getProperty(String name) throws SAXNotRecognizedException,
+ SAXNotSupportedException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean getFeature(String name) throws SAXNotRecognizedException,
+ SAXNotSupportedException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public ErrorHandler getErrorHandler() {
+ return null;
+ }
+
+ @Override
+ public EntityResolver getEntityResolver() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public DTDHandler getDTDHandler() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public ContentHandler getContentHandler() {
+ return this.handler;
+ }
+
+}
+
+/**
+ * Adapts the {@link ContentHandlerProxy} to be a {@link ProxyReceiver}
+ */
+final class ContentHandlerProxyReceiver extends ProxyReceiver {
+
+ private Receiver reciever;
+
+ public ContentHandlerProxyReceiver(Receiver reciever) {
+ this.reciever = reciever;
+ }
+
+ public void attribute(int nameCode, int typeCode, CharSequence value,
+ int locationId, int properties) throws XPathException {
+ reciever.attribute(nameCode, typeCode, value, locationId,
+ properties);
+ }
+
+ public void characters(CharSequence chars, int locationId,
+ int properties) throws XPathException {
+ reciever.characters(chars, locationId, properties);
+ }
+
+ public void close() throws XPathException {
+ reciever.close();
+ }
+
+ public void comment(CharSequence content, int locationId, int properties)
+ throws XPathException {
+ reciever.comment(content, locationId, properties);
+ }
+
+ public void endDocument() throws XPathException {
+ reciever.endDocument();
+ }
+
+ public void endElement() throws XPathException {
+ reciever.endElement();
+ }
+
+ public PipelineConfiguration getPipelineConfiguration() {
+ return reciever.getPipelineConfiguration();
+ }
+
+ public String getSystemId() {
+ return reciever.getSystemId();
+ }
+
+ public void namespace(int namespaceCode, int properties)
+ throws XPathException {
+ reciever.namespace(namespaceCode, properties);
+ }
+
+ public void open() throws XPathException {
+ reciever.open();
+ }
+
+ public void processingInstruction(String name, CharSequence data,
+ int locationId, int properties) throws XPathException {
+ reciever.processingInstruction(name, data, locationId, properties);
+ }
+
+ public void setPipelineConfiguration(PipelineConfiguration config) {
+ reciever.setPipelineConfiguration(config);
+ }
+
+ public void setSystemId(String systemId) {
+ reciever.setSystemId(systemId);
+ }
+
+ public void setUnparsedEntity(String name, String systemID,
+ String publicID) throws XPathException {
+ reciever.setUnparsedEntity(name, systemID, publicID);
+ }
+
+ public void startContent() throws XPathException {
+ reciever.startContent();
+ }
+
+ public void startDocument(int properties) throws XPathException {
+ reciever.startDocument(properties);
+ }
+
+ public void startElement(int nameCode, int typeCode, int locationId,
+ int properties) throws XPathException {
+ reciever.startElement(nameCode, typeCode, locationId, properties);
+ }
+
+}
\ No newline at end of file
Property changes on: branches/7.4.x/engine/src/main/java/org/teiid/query/xquery/saxon/StreamingUtils.java
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Modified: branches/7.4.x/engine/src/test/java/org/teiid/query/processor/TestSQLXMLProcessing.java
===================================================================
--- branches/7.4.x/engine/src/test/java/org/teiid/query/processor/TestSQLXMLProcessing.java 2011-06-10 16:28:08 UTC (rev 3241)
+++ branches/7.4.x/engine/src/test/java/org/teiid/query/processor/TestSQLXMLProcessing.java 2011-06-10 17:50:13 UTC (rev 3242)
@@ -271,7 +271,27 @@
process(sql, expected);
}
+
+ @Test public void testXmlQueryEmptyNullString() throws Exception {
+ String sql = "select xmlquery('/a/b' passing xmlparse(document '<x/>') null on empty)"; //$NON-NLS-1$
+
+ List<?>[] expected = new List<?>[] {
+ Arrays.asList((String)null)
+ };
+ process(sql, expected);
+ }
+
+ @Test public void testXmlQueryStreaming() throws Exception {
+ String sql = "select xmlquery('/a/b' passing xmlparse(document '<a><b x=''1''/><b x=''2''/></a>') null on empty)"; //$NON-NLS-1$
+
+ List<?>[] expected = new List<?>[] {
+ Arrays.asList("<b x=\"1\"/><b x=\"2\"/>")
+ };
+
+ process(sql, expected);
+ }
+
@Test public void testXmlNameEscaping() throws Exception {
String sql = "select xmlforest(\"xml\") from (select 1 as \"xml\") x"; //$NON-NLS-1$
@@ -371,6 +391,27 @@
process(sql, expected);
}
+ @Test public void testXmlTableStreamingParentAttributes() throws Exception {
+ String sql = "select * from xmltable('/a/b' passing xmlparse(document '<a x=''1''><b>foo</b></a>') columns y string path '.', x integer path '../@x') as x"; //$NON-NLS-1$
+ List<?>[] expected = new List<?>[] {
+ Arrays.asList("foo", 1),
+ };
+ process(sql, expected);
+ }
+
+ /**
+ * Highlights that the PathMapFilter needs to be selective in calling startContent
+ * @throws Exception
+ */
+ @Test public void testXmlStreamingError() throws Exception {
+ String sql = "select * from xmltable('/a/a' passing xmlparse(document '<a><a>2000-01-01T01:01:00.2-06:00<a></a></a></a>') columns x timestamp path 'xs:dateTime(./text())') as x"; //$NON-NLS-1$
+ Timestamp ts = TimestampUtil.createTimestamp(100, 0, 1, 1, 1, 0, 200000000);
+ List<?>[] expected = new List<?>[] {
+ Arrays.asList(ts),
+ };
+ process(sql, expected);
+ }
+
@Test public void testXmlTableSubquery() throws Exception {
String sql = "select * from xmltable('/a/b' passing convert('<a><b>first</b><b x=\"attr\">c</b></a>', xml) columns x string path '@x', val string path '/.') as x where val = (select max(e1) from pm1.g1 as x)";
13 years, 7 months
teiid SVN: r3241 - in branches/7.4.x/engine/src: test/java/org/teiid/query/processor and 1 other directory.
by teiid-commits@lists.jboss.org
Author: shawkins
Date: 2011-06-10 12:28:08 -0400 (Fri, 10 Jun 2011)
New Revision: 3241
Modified:
branches/7.4.x/engine/src/main/java/org/teiid/query/processor/relational/AccessNode.java
branches/7.4.x/engine/src/test/java/org/teiid/query/processor/TestProcessor.java
Log:
TEIID-1630 correcting final project minimization
Modified: branches/7.4.x/engine/src/main/java/org/teiid/query/processor/relational/AccessNode.java
===================================================================
--- branches/7.4.x/engine/src/main/java/org/teiid/query/processor/relational/AccessNode.java 2011-06-09 19:23:59 UTC (rev 3240)
+++ branches/7.4.x/engine/src/main/java/org/teiid/query/processor/relational/AccessNode.java 2011-06-10 16:28:08 UTC (rev 3241)
@@ -45,6 +45,7 @@
import org.teiid.query.processor.ProcessorDataManager;
import org.teiid.query.rewriter.QueryRewriter;
import org.teiid.query.sql.lang.Command;
+import org.teiid.query.sql.lang.OrderByItem;
import org.teiid.query.sql.lang.Query;
import org.teiid.query.sql.lang.Select;
import org.teiid.query.sql.symbol.Constant;
@@ -204,6 +205,14 @@
}
if (!shouldProject) {
this.projection = new Object[0];
+ } else if (query.getOrderBy() != null) {
+ for (OrderByItem item : query.getOrderBy().getOrderByItems()) {
+ Integer index = uniqueSymbols.get(SymbolMap.getExpression(item.getSymbol()));
+ if (index != null) {
+ item.setExpressionPosition(index);
+ item.setSymbol((SingleElementSymbol) select.getSymbols().get(index));
+ }
+ }
}
}
Modified: branches/7.4.x/engine/src/test/java/org/teiid/query/processor/TestProcessor.java
===================================================================
--- branches/7.4.x/engine/src/test/java/org/teiid/query/processor/TestProcessor.java 2011-06-09 19:23:59 UTC (rev 3240)
+++ branches/7.4.x/engine/src/test/java/org/teiid/query/processor/TestProcessor.java 2011-06-10 16:28:08 UTC (rev 3241)
@@ -7512,7 +7512,6 @@
helpProcess(plan, dataManager, expected);
}
-
@Test public void testDupSelect() throws Exception {
String sql = "select e1, e1 from pm1.g1";
@@ -7537,5 +7536,18 @@
helpProcess(plan, dataManager, new List[] {Arrays.asList(1, 2)});
}
+ @Test public void testDupSelectWithOrderBy() throws Exception {
+ String sql = "select e1 as a, e1 as b from pm1.g1 order by b";
+
+ HardcodedDataManager dataManager = new HardcodedDataManager();
+
+ //note that the command is referencing c_0
+ dataManager.addData("SELECT g_0.e1 AS c_0 FROM pm1.g1 AS g_0 ORDER BY c_0", new List[] {Arrays.asList(1)});
+
+ ProcessorPlan plan = helpGetPlan(sql, RealMetadataFactory.example1Cached(), TestOptimizer.getGenericFinder());
+
+ helpProcess(plan, dataManager, new List[] {Arrays.asList(1, 1)});
+ }
+
private static final boolean DEBUG = false;
}
13 years, 7 months
teiid SVN: r3240 - branches/7.4.x/engine/src/main/java/org/teiid/dqp/internal/process.
by teiid-commits@lists.jboss.org
Author: rareddy
Date: 2011-06-09 15:23:59 -0400 (Thu, 09 Jun 2011)
New Revision: 3240
Modified:
branches/7.4.x/engine/src/main/java/org/teiid/dqp/internal/process/RequestWorkItem.java
Log:
misc: avoid a verbose logging call when the transaction is NONE and or null
Modified: branches/7.4.x/engine/src/main/java/org/teiid/dqp/internal/process/RequestWorkItem.java
===================================================================
--- branches/7.4.x/engine/src/main/java/org/teiid/dqp/internal/process/RequestWorkItem.java 2011-06-09 18:45:13 UTC (rev 3239)
+++ branches/7.4.x/engine/src/main/java/org/teiid/dqp/internal/process/RequestWorkItem.java 2011-06-09 19:23:59 UTC (rev 3240)
@@ -293,10 +293,12 @@
}
private void suspend() {
- try {
- this.transactionService.suspend(this.transactionContext);
- } catch (XATransactionException e) {
- LogManager.logDetail(LogConstants.CTX_DQP, e, "Error suspending active transaction"); //$NON-NLS-1$
+ if (this.transactionState == TransactionState.ACTIVE && this.transactionContext.getTransaction() != null) {
+ try {
+ this.transactionService.suspend(this.transactionContext);
+ } catch (XATransactionException e) {
+ LogManager.logDetail(LogConstants.CTX_DQP, e, "Error suspending active transaction"); //$NON-NLS-1$
+ }
}
}
13 years, 7 months
teiid SVN: r3239 - in branches/7.1.1.CP2/runtime/src/main/java/org/teiid: transport and 1 other directory.
by teiid-commits@lists.jboss.org
Author: mdrillin
Date: 2011-06-09 14:45:13 -0400 (Thu, 09 Jun 2011)
New Revision: 3239
Modified:
branches/7.1.1.CP2/runtime/src/main/java/org/teiid/odbc/ODBCServerRemoteImpl.java
branches/7.1.1.CP2/runtime/src/main/java/org/teiid/transport/PgBackendProtocol.java
Log:
TEIID-1631 : ODBC SQLDescribeCol was not working when used with Prepare Statement
Modified: branches/7.1.1.CP2/runtime/src/main/java/org/teiid/odbc/ODBCServerRemoteImpl.java
===================================================================
--- branches/7.1.1.CP2/runtime/src/main/java/org/teiid/odbc/ODBCServerRemoteImpl.java 2011-06-08 23:02:33 UTC (rev 3238)
+++ branches/7.1.1.CP2/runtime/src/main/java/org/teiid/odbc/ODBCServerRemoteImpl.java 2011-06-09 18:45:13 UTC (rev 3239)
@@ -462,7 +462,12 @@
}
else {
try {
+ // The response is a ParameterDescription message describing the parameters needed by the statement,
this.client.sendParameterDescription(query.stmt.getParameterMetaData(), query.paramType);
+
+ // followed by a RowDescription message describing the rows that will be returned when the statement
+ // is eventually executed (or a NoData message if the statement will not return rows).
+ this.client.sendResultSetDescription(query.stmt.getMetaData(), query.stmt);
} catch (SQLException e) {
this.client.errorOccurred(e);
}
Modified: branches/7.1.1.CP2/runtime/src/main/java/org/teiid/transport/PgBackendProtocol.java
===================================================================
--- branches/7.1.1.CP2/runtime/src/main/java/org/teiid/transport/PgBackendProtocol.java 2011-06-08 23:02:33 UTC (rev 3238)
+++ branches/7.1.1.CP2/runtime/src/main/java/org/teiid/transport/PgBackendProtocol.java 2011-06-09 18:45:13 UTC (rev 3239)
@@ -214,7 +214,7 @@
if (paramType != null && paramType[i] != 0) {
type = paramType[i];
} else {
- type = PG_TYPE_VARCHAR;
+ type = convertType(meta.getParameterType(i+1));
}
writeInt(type);
}
13 years, 7 months
teiid SVN: r3238 - branches/7.4.x/connectors/translator-olap/src/main/java/org/teiid/translator/olap.
by teiid-commits@lists.jboss.org
Author: rareddy
Date: 2011-06-08 19:02:33 -0400 (Wed, 08 Jun 2011)
New Revision: 3238
Modified:
branches/7.4.x/connectors/translator-olap/src/main/java/org/teiid/translator/olap/OlapQueryExecution.java
Log:
TEIID-1628: correct the code to extract the data rather than the label for the ROW dimention data.
Modified: branches/7.4.x/connectors/translator-olap/src/main/java/org/teiid/translator/olap/OlapQueryExecution.java
===================================================================
--- branches/7.4.x/connectors/translator-olap/src/main/java/org/teiid/translator/olap/OlapQueryExecution.java 2011-06-08 19:48:27 UTC (rev 3237)
+++ branches/7.4.x/connectors/translator-olap/src/main/java/org/teiid/translator/olap/OlapQueryExecution.java 2011-06-08 23:02:33 UTC (rev 3238)
@@ -54,9 +54,9 @@
protected OlapExecutionFactory executionFactory;
private OlapStatement stmt;
private CellSet cellSet;
- private CellSetAxis cols;
+ private CellSetAxis columnsAxis;
private int colWidth;
- private ListIterator<Position> iterator;
+ private ListIterator<Position> rowPositionIterator;
public OlapQueryExecution(Command command, OlapConnection connection, ExecutionContext context, OlapExecutionFactory executionFactory) {
this.command = command;
@@ -74,10 +74,10 @@
stmt = this.connection.createStatement();
cellSet = stmt.executeOlapQuery(mdxQuery);
- CellSetAxis rows = this.cellSet.getAxes().get(Axis.ROWS.axisOrdinal());
- iterator = rows.iterator();
- cols = cellSet.getAxes().get(Axis.COLUMNS.axisOrdinal());
- colWidth = rows.getAxisMetaData().getHierarchies().size() + this.cols.getPositions().size();
+ CellSetAxis rowAxis = this.cellSet.getAxes().get(Axis.ROWS.axisOrdinal());
+ rowPositionIterator = rowAxis.iterator();
+ columnsAxis = cellSet.getAxes().get(Axis.COLUMNS.axisOrdinal());
+ colWidth = rowAxis.getAxisMetaData().getHierarchies().size() + this.columnsAxis.getPositions().size();
} catch (SQLException e) {
throw new TranslatorException(e);
}
@@ -109,22 +109,22 @@
@Override
public List<?> next() throws TranslatorException {
- if (!iterator.hasNext()) {
+ if (!rowPositionIterator.hasNext()) {
return null;
}
- Position nextRow = iterator.next();
+ Position rowPosition = rowPositionIterator.next();
Object[] result = new Object[colWidth];
int i = 0;
// add in rows axis
- List<Member> members = nextRow.getMembers();
+ List<Member> members = rowPosition.getMembers();
for (Member member:members) {
- String columnName = member.getHierarchy().getName();
+ String columnName = member.getName();
result[i++] = columnName;
}
// add col axis
- for (Position colPos : cols) {
- Cell cell = cellSet.getCell(colPos, nextRow);
+ for (Position colPos : columnsAxis) {
+ Cell cell = cellSet.getCell(colPos, rowPosition);
result[i++] = cell.getValue();
}
ArrayList<Object[]> results = new ArrayList<Object[]>();
13 years, 7 months
teiid SVN: r3237 - branches/7.1.1.CP2/test-integration/common/src/test/resources/TestODBCSchema.
by teiid-commits@lists.jboss.org
Author: mdrillin
Date: 2011-06-08 15:48:27 -0400 (Wed, 08 Jun 2011)
New Revision: 3237
Modified:
branches/7.1.1.CP2/test-integration/common/src/test/resources/TestODBCSchema/test_PG_ATTRIBUTE.expected
Log:
TEIID-1623 - Resolves issue with ODBC precision and scale data for numeric and string types. Fixed Unit Test
Modified: branches/7.1.1.CP2/test-integration/common/src/test/resources/TestODBCSchema/test_PG_ATTRIBUTE.expected
===================================================================
--- branches/7.1.1.CP2/test-integration/common/src/test/resources/TestODBCSchema/test_PG_ATTRIBUTE.expected 2011-06-08 18:28:42 UTC (rev 3236)
+++ branches/7.1.1.CP2/test-integration/common/src/test/resources/TestODBCSchema/test_PG_ATTRIBUTE.expected 2011-06-08 19:48:27 UTC (rev 3237)
@@ -1,247 +1,247 @@
integer integer string integer short short integer boolean boolean boolean
oid attrelid attname atttypid attlen attnum atttypmod attnotnull attisdropped atthasdef
-1 1 PART_ID 1043 -1 1 4 true false false
-2 1 PART_NAME 1043 -1 2 255 false false false
-3 1 PART_COLOR 1043 -1 3 30 false false false
-4 1 PART_WEIGHT 1043 -1 4 255 false false false
-5 2 SHIPPER_ID 21 2 1 0 true false false
-6 2 SHIPPER_NAME 1043 -1 2 30 false false false
-7 3 STATUS_ID 21 2 1 0 true false false
-8 3 STATUS_NAME 1043 -1 2 30 false false false
-9 4 SUPPLIER_ID 1043 -1 1 10 true false false
-10 4 PART_ID 1043 -1 2 4 true false false
-11 4 QUANTITY 21 2 3 0 false false false
-12 4 SHIPPER_ID 21 2 4 0 false false false
-13 5 SUPPLIER_ID 1043 -1 1 10 true false false
-14 5 SUPPLIER_NAME 1043 -1 2 30 false false false
-15 5 SUPPLIER_STATUS 21 2 3 0 false false false
-16 5 SUPPLIER_CITY 1043 -1 4 30 false false false
-17 5 SUPPLIER_STATE 1043 -1 5 2 false false false
-18 6 VDBName 1043 -1 1 255 true false false
-19 6 SchemaName 1043 -1 2 255 true false false
-20 6 Name 1043 -1 3 255 true false false
-21 6 TargetSchemaName 1043 -1 4 255 false false false
-22 6 TargetName 1043 -1 5 4000 false false false
-23 6 Valid 16 1 6 0 false false false
-24 6 LoadState 1043 -1 7 255 false false false
-25 6 Updated 1114 8 8 0 false false false
-26 6 Cardinality 23 4 9 10 false false false
-27 7 resourcePath 1043 -1 1 255 false false false
-28 7 contents 14939 -1 2 0 false false false
-29 8 VDBName 1043 -1 1 255 true false false
-30 8 SchemaName 1043 -1 2 255 false false false
-31 8 TableName 1043 -1 3 255 true false false
-32 8 Name 1043 -1 4 255 true false false
-33 8 Position 23 4 5 10 true false false
-34 8 NameInSource 1043 -1 6 255 false false false
-35 8 DataType 1043 -1 7 100 true false false
-36 8 Scale 23 4 8 10 true false false
-37 8 Length 23 4 9 10 true false false
-38 8 IsLengthFixed 16 1 10 1 true false false
-39 8 SupportsSelect 16 1 11 1 true false false
-40 8 SupportsUpdates 16 1 12 1 true false false
-41 8 IsCaseSensitive 16 1 13 1 true false false
-42 8 IsSigned 16 1 14 1 true false false
-43 8 IsCurrency 16 1 15 1 true false false
-44 8 IsAutoIncremented 16 1 16 1 true false false
-45 8 NullType 1043 -1 17 20 true false false
-46 8 MinRange 1043 -1 18 50 false false false
-47 8 MaxRange 1043 -1 19 50 false false false
-48 8 SearchType 1043 -1 20 20 true false false
-49 8 Format 1043 -1 21 255 false false false
-50 8 DefaultValue 1043 -1 22 255 false false false
-51 8 JavaClass 1043 -1 23 500 true false false
-52 8 Precision 23 4 24 10 true false false
-53 8 CharOctetLength 23 4 25 10 false false false
-54 8 Radix 23 4 26 10 true false false
-55 8 UID 1043 -1 27 50 true false false
-56 8 Description 1043 -1 28 255 false false false
-57 8 OID 23 4 29 10 true false false
-58 9 Name 1043 -1 1 100 true false false
-59 9 IsStandard 16 1 2 1 false false false
-60 9 IsPhysical 16 1 3 1 false false false
-61 9 TypeName 1043 -1 4 100 true false false
-62 9 JavaClass 1043 -1 5 500 true false false
-63 9 Scale 23 4 6 10 false false false
-64 9 TypeLength 23 4 7 10 true false false
-65 9 NullType 1043 -1 8 20 true false false
-66 9 IsSigned 16 1 9 1 true false false
-67 9 IsAutoIncremented 16 1 10 1 true false false
-68 9 IsCaseSensitive 16 1 11 1 true false false
-69 9 Precision 23 4 12 10 true false false
-70 9 Radix 23 4 13 10 false false false
-71 9 SearchType 1043 -1 14 20 true false false
-72 9 UID 1043 -1 15 50 true false false
-73 9 RuntimeType 1043 -1 16 64 false false false
-74 9 BaseType 1043 -1 17 64 false false false
-75 9 Description 1043 -1 18 255 false false false
-76 9 OID 23 4 19 10 true false false
-77 10 VDBName 1043 -1 1 255 true false false
-78 10 SchemaName 1043 -1 2 255 false false false
-79 10 TableName 1043 -1 3 2048 true false false
-80 10 Name 1043 -1 4 255 true false false
-81 10 KeyName 1043 -1 5 255 false false false
-82 10 KeyType 1043 -1 6 20 true false false
-83 10 RefKeyUID 1043 -1 7 50 false false false
-84 10 UID 1043 -1 8 50 true false false
-85 10 Position 23 4 9 10 false false false
-86 10 OID 23 4 10 10 true false false
-87 11 VDBName 1043 -1 1 255 true false false
-88 11 SchemaName 1043 -1 2 255 false false false
-89 11 TableName 1043 -1 3 2048 true false false
-90 11 Name 1043 -1 4 255 true false false
-91 11 Description 1043 -1 5 255 false false false
-92 11 NameInSource 1043 -1 6 255 false false false
-93 11 Type 1043 -1 7 20 true false false
-94 11 IsIndexed 16 1 8 1 true false false
-95 11 RefKeyUID 1043 -1 9 50 false false false
-96 11 UID 1043 -1 10 50 true false false
-97 11 OID 23 4 11 10 true false false
-98 12 VDBName 1043 -1 1 255 true false false
-99 12 SchemaName 1043 -1 2 255 false false false
-100 12 ProcedureName 1043 -1 3 255 true false false
-101 12 Name 1043 -1 4 255 true false false
-102 12 DataType 1043 -1 5 25 true false false
-103 12 Position 23 4 6 10 true false false
-104 12 Type 1043 -1 7 100 true false false
-105 12 Optional 16 1 8 1 true false false
-106 12 Precision 23 4 9 10 true false false
-107 12 TypeLength 23 4 10 10 true false false
-108 12 Scale 23 4 11 10 true false false
-109 12 Radix 23 4 12 10 true false false
-110 12 NullType 1043 -1 13 10 true false false
-111 12 UID 1043 -1 14 50 false false false
-112 12 Description 1043 -1 15 255 false false false
-113 12 OID 23 4 16 10 true false false
-114 13 VDBName 1043 -1 1 255 true false false
-115 13 SchemaName 1043 -1 2 255 false false false
-116 13 Name 1043 -1 3 255 true false false
-117 13 NameInSource 1043 -1 4 255 false false false
-118 13 ReturnsResults 16 1 5 1 true false false
-119 13 UID 1043 -1 6 50 true false false
-120 13 Description 1043 -1 7 255 false false false
-121 13 OID 23 4 8 10 true false false
-122 14 Name 1043 -1 1 255 true false false
-123 14 Value 1043 -1 2 255 true false false
-124 14 UID 1043 -1 3 50 true false false
-125 14 OID 23 4 4 10 true false false
-126 15 PKTABLE_CAT 1043 -1 1 255 false false false
-127 15 PKTABLE_SCHEM 1043 -1 2 255 false false false
-128 15 PKTABLE_NAME 1043 -1 3 255 false false false
-129 15 PKCOLUMN_NAME 1043 -1 4 255 false false false
-130 15 FKTABLE_CAT 1043 -1 5 255 false false false
-131 15 FKTABLE_SCHEM 1043 -1 6 255 false false false
-132 15 FKTABLE_NAME 1043 -1 7 255 false false false
-133 15 FKCOLUMN_NAME 1043 -1 8 255 false false false
-134 15 KEY_SEQ 21 2 9 5 false false false
-135 15 UPDATE_RULE 23 4 10 10 false false false
-136 15 DELETE_RULE 23 4 11 10 false false false
-137 15 FK_NAME 1043 -1 12 255 false false false
-138 15 PK_NAME 1043 -1 13 255 false false false
-139 15 DEFERRABILITY 23 4 14 10 false false false
-140 16 VDBName 1043 -1 1 255 false false false
-141 16 Name 1043 -1 2 255 false false false
-142 16 IsPhysical 16 1 3 1 true false false
-143 16 UID 1043 -1 4 50 true false false
-144 16 Description 1043 -1 5 255 false false false
-145 16 PrimaryMetamodelURI 1043 -1 6 255 true false false
-146 16 OID 23 4 7 10 true false false
-147 17 VDBName 1043 -1 1 255 false false false
-148 17 SchemaName 1043 -1 2 255 false false false
-149 17 Name 1043 -1 3 255 true false false
-150 17 Type 1043 -1 4 20 true false false
-151 17 NameInSource 1043 -1 5 255 false false false
-152 17 IsPhysical 16 1 6 1 true false false
-153 17 SupportsUpdates 16 1 7 1 true false false
-154 17 UID 1043 -1 8 50 true false false
-155 17 Cardinality 23 4 9 10 true false false
-156 17 Description 1043 -1 10 255 false false false
-157 17 IsSystem 16 1 11 1 false false false
-158 17 IsMaterialized 16 1 12 0 true false false
-159 17 OID 23 4 13 10 true false false
-160 18 Name 1043 -1 1 255 true false false
-161 18 Version 1043 -1 2 50 true false false
-162 19 oid 23 4 1 0 false false false
-163 19 nspname 1043 -1 2 0 false false false
-164 20 oid 23 4 1 0 false false false
-165 20 relname 1043 -1 2 0 false false false
-166 20 relnamespace 23 4 3 0 false false false
-167 20 relkind 1042 1 4 0 false false false
-168 20 relam 23 4 5 0 false false false
-169 20 reltuples 700 4 6 0 false false false
-170 20 relpages 23 4 7 0 false false false
-171 20 relhasrules 16 1 8 0 false false false
-172 20 relhasoids 1043 -1 9 0 false false false
-173 21 oid 23 4 1 0 false false false
-174 21 attrelid 23 4 2 0 false false false
-175 21 attname 1043 -1 3 0 false false false
-176 21 atttypid 23 4 4 0 false false false
-177 21 attlen 21 2 5 0 false false false
-178 21 attnum 21 2 6 0 false false false
-179 21 atttypmod 23 4 7 0 false false false
-180 21 attnotnull 16 1 8 0 false false false
-181 21 attisdropped 16 1 9 0 false false false
-182 21 atthasdef 16 1 10 0 false false false
-183 22 oid 23 4 1 0 false false false
-184 22 typname 1043 -1 2 0 false false false
-185 22 typnamespace 23 4 3 0 false false false
-186 22 typlen 21 2 4 0 false false false
-187 22 typtype 1042 1 5 0 false false false
-188 22 typbasetype 23 4 6 0 false false false
-189 22 typtypmod 23 4 7 0 false false false
-190 22 typrelid 23 4 8 0 false false false
-191 23 oid 23 4 1 0 false false false
-192 23 indexrelid 23 4 2 0 false false false
-193 23 indrelid 23 4 3 0 false false false
-194 23 indisclustered 16 1 4 0 false false false
-195 23 indisunique 16 1 5 0 false false false
-196 23 indisprimary 16 1 6 0 false false false
-197 23 indexprs 1043 -1 7 0 false false false
-198 23 indkey 1043 -1 8 0 false false false
-199 24 oid 23 4 1 0 false false false
-200 24 amname 1043 -1 2 0 false false false
-201 25 oid 23 4 1 0 false false false
-202 25 proname 1043 -1 2 0 false false false
-203 25 proretset 16 1 3 0 false false false
-204 25 prorettype 23 4 4 0 false false false
-205 25 pronargs 21 2 5 0 false false false
-206 25 proargtypes <null> <null> 6 0 false false false
-207 25 proargnames <null> <null> 7 0 false false false
-208 25 proargmodes <null> <null> 8 0 false false false
-209 25 proallargtypes <null> <null> 9 0 false false false
-210 25 pronamespace 23 4 10 0 false false false
-211 26 oid 23 4 1 0 false false false
-212 26 tgconstrrelid 23 4 2 0 false false false
-213 26 tgfoid 23 4 3 0 false false false
-214 26 tgargs 23 4 4 0 false false false
-215 26 tgnargs 23 4 5 0 false false false
-216 26 tgdeferrable 16 1 6 0 false false false
-217 26 tginitdeferred 16 1 7 0 false false false
-218 26 tgconstrname 1043 -1 8 0 false false false
-219 26 tgrelid 23 4 9 0 false false false
-220 27 adrelid 23 4 1 0 false false false
-221 27 adnum 23 4 2 0 false false false
-222 27 adbin 1043 -1 3 0 false false false
-223 27 adsrc 1043 -1 4 0 false false false
-224 28 oid 23 4 1 0 false false false
-225 28 datname 1043 -1 2 0 false false false
-226 28 encoding 23 4 3 0 false false false
-227 28 datlastsysoid 23 4 4 0 false false false
-228 28 datallowconn 1042 1 5 0 false false false
-229 28 datconfig <null> <null> 6 0 false false false
-230 28 datacl <null> <null> 7 0 false false false
-231 28 datdba 23 4 8 0 false false false
-232 28 dattablespace 23 4 9 0 false false false
-233 29 oid 23 4 1 0 false false false
-234 29 usename 1043 -1 2 0 false false false
-235 29 usecreatedb 16 1 3 0 false false false
-236 29 usesuper 16 1 4 0 false false false
-237 30 attrelid 23 4 1 0 false false false
-238 30 attnum 21 2 2 0 false false false
-239 30 attname 1043 -1 3 0 false false false
-240 30 relname 1043 -1 4 0 false false false
-241 30 nspname 1043 -1 5 0 false false false
-242 30 autoinc 16 1 6 0 false false false
+1 1 PART_ID 1043 -1 1 8 true false false
+2 1 PART_NAME 1043 -1 2 259 false false false
+3 1 PART_COLOR 1043 -1 3 34 false false false
+4 1 PART_WEIGHT 1043 -1 4 259 false false false
+5 2 SHIPPER_ID 21 2 1 4 true false false
+6 2 SHIPPER_NAME 1043 -1 2 34 false false false
+7 3 STATUS_ID 21 2 1 4 true false false
+8 3 STATUS_NAME 1043 -1 2 34 false false false
+9 4 SUPPLIER_ID 1043 -1 1 14 true false false
+10 4 PART_ID 1043 -1 2 8 true false false
+11 4 QUANTITY 21 2 3 4 false false false
+12 4 SHIPPER_ID 21 2 4 4 false false false
+13 5 SUPPLIER_ID 1043 -1 1 14 true false false
+14 5 SUPPLIER_NAME 1043 -1 2 34 false false false
+15 5 SUPPLIER_STATUS 21 2 3 4 false false false
+16 5 SUPPLIER_CITY 1043 -1 4 34 false false false
+17 5 SUPPLIER_STATE 1043 -1 5 6 false false false
+18 6 VDBName 1043 -1 1 259 true false false
+19 6 SchemaName 1043 -1 2 259 true false false
+20 6 Name 1043 -1 3 259 true false false
+21 6 TargetSchemaName 1043 -1 4 259 false false false
+22 6 TargetName 1043 -1 5 4004 false false false
+23 6 Valid 16 1 6 4 false false false
+24 6 LoadState 1043 -1 7 259 false false false
+25 6 Updated 1114 8 8 4 false false false
+26 6 Cardinality 23 4 9 14 false false false
+27 7 resourcePath 1043 -1 1 259 false false false
+28 7 contents 14939 -1 2 4 false false false
+29 8 VDBName 1043 -1 1 259 true false false
+30 8 SchemaName 1043 -1 2 259 false false false
+31 8 TableName 1043 -1 3 259 true false false
+32 8 Name 1043 -1 4 259 true false false
+33 8 Position 23 4 5 14 true false false
+34 8 NameInSource 1043 -1 6 259 false false false
+35 8 DataType 1043 -1 7 104 true false false
+36 8 Scale 23 4 8 14 true false false
+37 8 Length 23 4 9 14 true false false
+38 8 IsLengthFixed 16 1 10 5 true false false
+39 8 SupportsSelect 16 1 11 5 true false false
+40 8 SupportsUpdates 16 1 12 5 true false false
+41 8 IsCaseSensitive 16 1 13 5 true false false
+42 8 IsSigned 16 1 14 5 true false false
+43 8 IsCurrency 16 1 15 5 true false false
+44 8 IsAutoIncremented 16 1 16 5 true false false
+45 8 NullType 1043 -1 17 24 true false false
+46 8 MinRange 1043 -1 18 54 false false false
+47 8 MaxRange 1043 -1 19 54 false false false
+48 8 SearchType 1043 -1 20 24 true false false
+49 8 Format 1043 -1 21 259 false false false
+50 8 DefaultValue 1043 -1 22 259 false false false
+51 8 JavaClass 1043 -1 23 504 true false false
+52 8 Precision 23 4 24 14 true false false
+53 8 CharOctetLength 23 4 25 14 false false false
+54 8 Radix 23 4 26 14 true false false
+55 8 UID 1043 -1 27 54 true false false
+56 8 Description 1043 -1 28 259 false false false
+57 8 OID 23 4 29 14 true false false
+58 9 Name 1043 -1 1 104 true false false
+59 9 IsStandard 16 1 2 5 false false false
+60 9 IsPhysical 16 1 3 5 false false false
+61 9 TypeName 1043 -1 4 104 true false false
+62 9 JavaClass 1043 -1 5 504 true false false
+63 9 Scale 23 4 6 14 false false false
+64 9 TypeLength 23 4 7 14 true false false
+65 9 NullType 1043 -1 8 24 true false false
+66 9 IsSigned 16 1 9 5 true false false
+67 9 IsAutoIncremented 16 1 10 5 true false false
+68 9 IsCaseSensitive 16 1 11 5 true false false
+69 9 Precision 23 4 12 14 true false false
+70 9 Radix 23 4 13 14 false false false
+71 9 SearchType 1043 -1 14 24 true false false
+72 9 UID 1043 -1 15 54 true false false
+73 9 RuntimeType 1043 -1 16 68 false false false
+74 9 BaseType 1043 -1 17 68 false false false
+75 9 Description 1043 -1 18 259 false false false
+76 9 OID 23 4 19 14 true false false
+77 10 VDBName 1043 -1 1 259 true false false
+78 10 SchemaName 1043 -1 2 259 false false false
+79 10 TableName 1043 -1 3 2052 true false false
+80 10 Name 1043 -1 4 259 true false false
+81 10 KeyName 1043 -1 5 259 false false false
+82 10 KeyType 1043 -1 6 24 true false false
+83 10 RefKeyUID 1043 -1 7 54 false false false
+84 10 UID 1043 -1 8 54 true false false
+85 10 Position 23 4 9 14 false false false
+86 10 OID 23 4 10 14 true false false
+87 11 VDBName 1043 -1 1 259 true false false
+88 11 SchemaName 1043 -1 2 259 false false false
+89 11 TableName 1043 -1 3 2052 true false false
+90 11 Name 1043 -1 4 259 true false false
+91 11 Description 1043 -1 5 259 false false false
+92 11 NameInSource 1043 -1 6 259 false false false
+93 11 Type 1043 -1 7 24 true false false
+94 11 IsIndexed 16 1 8 5 true false false
+95 11 RefKeyUID 1043 -1 9 54 false false false
+96 11 UID 1043 -1 10 54 true false false
+97 11 OID 23 4 11 14 true false false
+98 12 VDBName 1043 -1 1 259 true false false
+99 12 SchemaName 1043 -1 2 259 false false false
+100 12 ProcedureName 1043 -1 3 259 true false false
+101 12 Name 1043 -1 4 259 true false false
+102 12 DataType 1043 -1 5 29 true false false
+103 12 Position 23 4 6 14 true false false
+104 12 Type 1043 -1 7 104 true false false
+105 12 Optional 16 1 8 5 true false false
+106 12 Precision 23 4 9 14 true false false
+107 12 TypeLength 23 4 10 14 true false false
+108 12 Scale 23 4 11 14 true false false
+109 12 Radix 23 4 12 14 true false false
+110 12 NullType 1043 -1 13 14 true false false
+111 12 UID 1043 -1 14 54 false false false
+112 12 Description 1043 -1 15 259 false false false
+113 12 OID 23 4 16 14 true false false
+114 13 VDBName 1043 -1 1 259 true false false
+115 13 SchemaName 1043 -1 2 259 false false false
+116 13 Name 1043 -1 3 259 true false false
+117 13 NameInSource 1043 -1 4 259 false false false
+118 13 ReturnsResults 16 1 5 5 true false false
+119 13 UID 1043 -1 6 54 true false false
+120 13 Description 1043 -1 7 259 false false false
+121 13 OID 23 4 8 14 true false false
+122 14 Name 1043 -1 1 259 true false false
+123 14 Value 1043 -1 2 259 true false false
+124 14 UID 1043 -1 3 54 true false false
+125 14 OID 23 4 4 14 true false false
+126 15 PKTABLE_CAT 1043 -1 1 259 false false false
+127 15 PKTABLE_SCHEM 1043 -1 2 259 false false false
+128 15 PKTABLE_NAME 1043 -1 3 259 false false false
+129 15 PKCOLUMN_NAME 1043 -1 4 259 false false false
+130 15 FKTABLE_CAT 1043 -1 5 259 false false false
+131 15 FKTABLE_SCHEM 1043 -1 6 259 false false false
+132 15 FKTABLE_NAME 1043 -1 7 259 false false false
+133 15 FKCOLUMN_NAME 1043 -1 8 259 false false false
+134 15 KEY_SEQ 21 2 9 9 false false false
+135 15 UPDATE_RULE 23 4 10 14 false false false
+136 15 DELETE_RULE 23 4 11 14 false false false
+137 15 FK_NAME 1043 -1 12 259 false false false
+138 15 PK_NAME 1043 -1 13 259 false false false
+139 15 DEFERRABILITY 23 4 14 14 false false false
+140 16 VDBName 1043 -1 1 259 false false false
+141 16 Name 1043 -1 2 259 false false false
+142 16 IsPhysical 16 1 3 5 true false false
+143 16 UID 1043 -1 4 54 true false false
+144 16 Description 1043 -1 5 259 false false false
+145 16 PrimaryMetamodelURI 1043 -1 6 259 true false false
+146 16 OID 23 4 7 14 true false false
+147 17 VDBName 1043 -1 1 259 false false false
+148 17 SchemaName 1043 -1 2 259 false false false
+149 17 Name 1043 -1 3 259 true false false
+150 17 Type 1043 -1 4 24 true false false
+151 17 NameInSource 1043 -1 5 259 false false false
+152 17 IsPhysical 16 1 6 5 true false false
+153 17 SupportsUpdates 16 1 7 5 true false false
+154 17 UID 1043 -1 8 54 true false false
+155 17 Cardinality 23 4 9 14 true false false
+156 17 Description 1043 -1 10 259 false false false
+157 17 IsSystem 16 1 11 5 false false false
+158 17 IsMaterialized 16 1 12 4 true false false
+159 17 OID 23 4 13 14 true false false
+160 18 Name 1043 -1 1 259 true false false
+161 18 Version 1043 -1 2 54 true false false
+162 19 oid 23 4 1 4 false false false
+163 19 nspname 1043 -1 2 4 false false false
+164 20 oid 23 4 1 4 false false false
+165 20 relname 1043 -1 2 4 false false false
+166 20 relnamespace 23 4 3 4 false false false
+167 20 relkind 1042 1 4 4 false false false
+168 20 relam 23 4 5 4 false false false
+169 20 reltuples 700 4 6 4 false false false
+170 20 relpages 23 4 7 4 false false false
+171 20 relhasrules 16 1 8 4 false false false
+172 20 relhasoids 1043 -1 9 4 false false false
+173 21 oid 23 4 1 4 false false false
+174 21 attrelid 23 4 2 4 false false false
+175 21 attname 1043 -1 3 4 false false false
+176 21 atttypid 23 4 4 4 false false false
+177 21 attlen 21 2 5 4 false false false
+178 21 attnum 21 2 6 4 false false false
+179 21 atttypmod 23 4 7 4 false false false
+180 21 attnotnull 16 1 8 4 false false false
+181 21 attisdropped 16 1 9 4 false false false
+182 21 atthasdef 16 1 10 4 false false false
+183 22 oid 23 4 1 4 false false false
+184 22 typname 1043 -1 2 4 false false false
+185 22 typnamespace 23 4 3 4 false false false
+186 22 typlen 21 2 4 4 false false false
+187 22 typtype 1042 1 5 4 false false false
+188 22 typbasetype 23 4 6 4 false false false
+189 22 typtypmod 23 4 7 4 false false false
+190 22 typrelid 23 4 8 4 false false false
+191 23 oid 23 4 1 4 false false false
+192 23 indexrelid 23 4 2 4 false false false
+193 23 indrelid 23 4 3 4 false false false
+194 23 indisclustered 16 1 4 4 false false false
+195 23 indisunique 16 1 5 4 false false false
+196 23 indisprimary 16 1 6 4 false false false
+197 23 indexprs 1043 -1 7 4 false false false
+198 23 indkey 1043 -1 8 4 false false false
+199 24 oid 23 4 1 4 false false false
+200 24 amname 1043 -1 2 4 false false false
+201 25 oid 23 4 1 4 false false false
+202 25 proname 1043 -1 2 4 false false false
+203 25 proretset 16 1 3 4 false false false
+204 25 prorettype 23 4 4 4 false false false
+205 25 pronargs 21 2 5 4 false false false
+206 25 proargtypes <null> <null> 6 4 false false false
+207 25 proargnames <null> <null> 7 4 false false false
+208 25 proargmodes <null> <null> 8 4 false false false
+209 25 proallargtypes <null> <null> 9 4 false false false
+210 25 pronamespace 23 4 10 4 false false false
+211 26 oid 23 4 1 4 false false false
+212 26 tgconstrrelid 23 4 2 4 false false false
+213 26 tgfoid 23 4 3 4 false false false
+214 26 tgargs 23 4 4 4 false false false
+215 26 tgnargs 23 4 5 4 false false false
+216 26 tgdeferrable 16 1 6 4 false false false
+217 26 tginitdeferred 16 1 7 4 false false false
+218 26 tgconstrname 1043 -1 8 4 false false false
+219 26 tgrelid 23 4 9 4 false false false
+220 27 adrelid 23 4 1 4 false false false
+221 27 adnum 23 4 2 4 false false false
+222 27 adbin 1043 -1 3 4 false false false
+223 27 adsrc 1043 -1 4 4 false false false
+224 28 oid 23 4 1 4 false false false
+225 28 datname 1043 -1 2 4 false false false
+226 28 encoding 23 4 3 4 false false false
+227 28 datlastsysoid 23 4 4 4 false false false
+228 28 datallowconn 1042 1 5 4 false false false
+229 28 datconfig <null> <null> 6 4 false false false
+230 28 datacl <null> <null> 7 4 false false false
+231 28 datdba 23 4 8 4 false false false
+232 28 dattablespace 23 4 9 4 false false false
+233 29 oid 23 4 1 4 false false false
+234 29 usename 1043 -1 2 4 false false false
+235 29 usecreatedb 16 1 3 4 false false false
+236 29 usesuper 16 1 4 4 false false false
+237 30 attrelid 23 4 1 4 false false false
+238 30 attnum 21 2 2 4 false false false
+239 30 attname 1043 -1 3 4 false false false
+240 30 relname 1043 -1 4 4 false false false
+241 30 nspname 1043 -1 5 4 false false false
+242 30 autoinc 16 1 6 4 false false false
Row Count : 242
getColumnName getColumnType getCatalogName getColumnClassName getColumnLabel getColumnTypeName getSchemaName getTableName getColumnDisplaySize getPrecision getScale isAutoIncrement isCaseSensitive isCurrency isDefinitelyWritable isNullable isReadOnly isSearchable isSigned isWritable
oid 4 PartsSupplier java.lang.Integer oid integer pg_catalog pg_attribute 11 10 0 false false false false 2 true true false false
13 years, 7 months
teiid SVN: r3236 - in branches/7.4.x: client/src/test/java/org/teiid/jdbc and 4 other directories.
by teiid-commits@lists.jboss.org
Author: shawkins
Date: 2011-06-08 14:28:42 -0400 (Wed, 08 Jun 2011)
New Revision: 3236
Modified:
branches/7.4.x/client/src/main/java/org/teiid/jdbc/SQLStates.java
branches/7.4.x/client/src/main/java/org/teiid/jdbc/TeiidSQLException.java
branches/7.4.x/client/src/test/java/org/teiid/jdbc/TestSQLException.java
branches/7.4.x/common-core/src/main/java/org/teiid/core/TeiidException.java
branches/7.4.x/common-core/src/main/java/org/teiid/core/TeiidRuntimeException.java
branches/7.4.x/common-core/src/test/java/org/teiid/core/TestMetaMatrixRuntimeException.java
branches/7.4.x/engine/src/main/java/org/teiid/dqp/internal/process/DataTierTupleSource.java
branches/7.4.x/engine/src/main/java/org/teiid/dqp/internal/process/RequestWorkItem.java
branches/7.4.x/engine/src/main/java/org/teiid/query/processor/QueryProcessor.java
Log:
TEIID-97 adding state for timeout/cancel with various exception clean ups.
Modified: branches/7.4.x/client/src/main/java/org/teiid/jdbc/SQLStates.java
===================================================================
--- branches/7.4.x/client/src/main/java/org/teiid/jdbc/SQLStates.java 2011-06-08 18:23:36 UTC (rev 3235)
+++ branches/7.4.x/client/src/main/java/org/teiid/jdbc/SQLStates.java 2011-06-08 18:28:42 UTC (rev 3236)
@@ -82,6 +82,8 @@
* conforms to the subclass DataDirect uses for SocketExceptions.
*/
public static final String CONNECTION_EXCEPTION_STALE_CONNECTION = "08S01"; //$NON-NLS-1$
+
+ public static final String QUERY_CANCELED = "57014"; //$NON-NLS-1$
// Class 28 - invalid authorization specification
Modified: branches/7.4.x/client/src/main/java/org/teiid/jdbc/TeiidSQLException.java
===================================================================
--- branches/7.4.x/client/src/main/java/org/teiid/jdbc/TeiidSQLException.java 2011-06-08 18:23:36 UTC (rev 3235)
+++ branches/7.4.x/client/src/main/java/org/teiid/jdbc/TeiidSQLException.java 2011-06-08 18:28:42 UTC (rev 3236)
@@ -32,6 +32,7 @@
import org.teiid.client.ProcedureErrorInstructionException;
import org.teiid.client.security.InvalidSessionException;
import org.teiid.client.security.LogonException;
+import org.teiid.client.util.ExceptionUtil;
import org.teiid.core.TeiidProcessingException;
import org.teiid.core.TeiidException;
import org.teiid.core.TeiidRuntimeException;
@@ -102,10 +103,13 @@
return new TeiidSQLException((SQLException) exception, message, true);
}
String sqlState = SQLStates.DEFAULT;
-
- exception = findRootException(exception);
-
- sqlState = determineSQLState(exception, sqlState);
+ TeiidException te = ExceptionUtil.getExceptionOfType(exception, TeiidException.class);
+ if (te != null && te.getCode() != null) {
+ sqlState = te.getCode();
+ } else {
+ exception = findRootException(exception);
+ sqlState = determineSQLState(exception, sqlState);
+ }
return new TeiidSQLException(origException, message, sqlState);
}
Modified: branches/7.4.x/client/src/test/java/org/teiid/jdbc/TestSQLException.java
===================================================================
--- branches/7.4.x/client/src/test/java/org/teiid/jdbc/TestSQLException.java 2011-06-08 18:23:36 UTC (rev 3235)
+++ branches/7.4.x/client/src/test/java/org/teiid/jdbc/TestSQLException.java 2011-06-08 18:28:42 UTC (rev 3236)
@@ -22,6 +22,8 @@
package org.teiid.jdbc;
+import static org.junit.Assert.*;
+
import java.io.IOException;
import java.net.ConnectException;
import java.net.MalformedURLException;
@@ -31,23 +33,21 @@
import java.net.UnknownHostException;
import java.sql.SQLException;
-import junit.framework.TestCase;
-
+import org.junit.Test;
import org.teiid.client.ProcedureErrorInstructionException;
-import org.teiid.core.TeiidProcessingException;
import org.teiid.core.TeiidException;
-import org.teiid.core.TeiidException;
+import org.teiid.core.TeiidProcessingException;
import org.teiid.core.TeiidRuntimeException;
import org.teiid.net.CommunicationException;
import org.teiid.net.ConnectionException;
-public class TestSQLException extends TestCase {
+public class TestSQLException {
/*
* Test method for 'com.metamatrix.jdbc.MMSQLException.MMSQLException()'
*/
- public void testMMSQLException() {
+ @Test public void testMMSQLException() {
TeiidSQLException e = new TeiidSQLException();
String sqlState = e.getSQLState();
Throwable cause = e.getCause();
@@ -82,7 +82,7 @@
* Tests various simple exceptions to see if the expected SQLState is
* returend.
*/
- public void testCreateThrowable_01() {
+ @Test public void testCreateThrowable_01() {
testCreateThrowable(new CommunicationException(
"A test MM Communication Exception"), //$NON-NLS-1$
SQLStates.CONNECTION_EXCEPTION_STALE_CONNECTION);
@@ -133,7 +133,7 @@
* Tests various nested exceptions to see if the expected SQLState is
* returend.
*/
- public void testCreateThrowable_02() {
+ @Test public void testCreateThrowable_02() {
testCreateThrowable(
new CommunicationException(new ConnectException(
"A test java.net.ConnectException"), //$NON-NLS-1$
@@ -150,7 +150,7 @@
SQLStates.CONNECTION_EXCEPTION_STALE_CONNECTION);
}
- public void testCreateThrowable3() {
+ @Test public void testCreateThrowable3() {
TeiidSQLException e = testCreateThrowable(
new TeiidException(
new TeiidRuntimeException(
@@ -180,31 +180,15 @@
Throwable nestedException = e.getCause();
SQLException nextException = e.getNextException();
- assertTrue("Expected MMSQLException.getSQLState() to return \"" //$NON-NLS-1$
- + esqlState + "\" but got \"" + sqlState + "\" instead.", //$NON-NLS-1$ //$NON-NLS-2$
- sqlState.compareTo(esqlState) == 0);
- assertTrue("Expected MMSQLException.getCause() to return [" //$NON-NLS-1$
- + (ecause != null ? ecause.getClass().getName() : "<null>") //$NON-NLS-1$
- + "] but got [" //$NON-NLS-1$
- + (cause != null ? cause.getClass().getName() : "<unknown>") //$NON-NLS-1$
- + "] instead.", cause == ecause); //$NON-NLS-1$
- assertTrue(
- "Expected MMSQLException.getErrorCode() to return [0] but got [" //$NON-NLS-1$
- + errorCode + "] instead.", errorCode == 0); //$NON-NLS-1$
- assertTrue("Expected MMSQLException.getNestedException() to return [" //$NON-NLS-1$
- + (ecause != null ? ecause.getClass().getName() : "<null>") //$NON-NLS-1$
- + "] but got [" //$NON-NLS-1$
- + (nestedException != null ? nestedException.getClass()
- .getName() : "<unknown>") + "] instead.", //$NON-NLS-1$ //$NON-NLS-2$
- nestedException == ecause);
- assertTrue(
- "Expected MMSQLException.getNextException() to return <null> but got a SQLException with message \"" //$NON-NLS-1$
- + (nextException != null ? nextException.getMessage()
- : "") + "\" instead.", nextException == null); //$NON-NLS-1$ //$NON-NLS-2$
+ assertEquals(esqlState, sqlState);
+ assertEquals(ecause, cause);
+ assertEquals(0, errorCode);
+ assertEquals(nestedException, ecause);
+ assertNull(nextException);
return e;
}
- public void testCreate() {
+ @Test public void testCreate() {
TeiidSQLException exception = TeiidSQLException.create(new Exception());
assertEquals(exception.getMessage(), Exception.class.getName());
@@ -214,7 +198,7 @@
assertEquals(exception, TeiidSQLException.create(exception));
}
- public void testCreateFromSQLException() {
+ @Test public void testCreateFromSQLException() {
SQLException sqlexception = new SQLException("foo", "21"); //$NON-NLS-1$ //$NON-NLS-2$
SQLException nested = new SQLException("bar"); //$NON-NLS-1$
@@ -230,5 +214,15 @@
assertEquals(exception.getNextException().getMessage(), sqlexception.getMessage());
assertEquals(exception.getNextException().getNextException().getMessage(), nested.getMessage());
}
+
+ @Test public void testCodeAsSQLState() {
+ TeiidException sqlexception = new TeiidException("foo", "21"); //$NON-NLS-1$ //$NON-NLS-2$
+
+ String message = "top level message"; //$NON-NLS-1$
+
+ TeiidSQLException exception = TeiidSQLException.create(sqlexception, message);
+
+ assertEquals(sqlexception.getCode(), exception.getSQLState());
+ }
}
Modified: branches/7.4.x/common-core/src/main/java/org/teiid/core/TeiidException.java
===================================================================
--- branches/7.4.x/common-core/src/main/java/org/teiid/core/TeiidException.java 2011-06-08 18:23:36 UTC (rev 3235)
+++ branches/7.4.x/common-core/src/main/java/org/teiid/core/TeiidException.java 2011-06-08 18:28:42 UTC (rev 3236)
@@ -58,7 +58,7 @@
public TeiidException(Throwable e, String message) {
super(message, e);
- setCode(e);
+ setCode(getCode(e));
}
public TeiidException(Throwable e, String errorCode, String message) {
@@ -82,14 +82,15 @@
this.originalType = originalType;
}
- private void setCode(Throwable e) {
+ static String getCode(Throwable e) {
if (e instanceof TeiidException) {
- this.code = (((TeiidException) e).getCode());
+ return (((TeiidException) e).getCode());
} else if (e instanceof TeiidRuntimeException) {
- this.code = ((TeiidRuntimeException) e).getCode();
+ return ((TeiidRuntimeException) e).getCode();
} else if (e instanceof SQLException) {
- this.code = Integer.toString(((SQLException)e).getErrorCode());
+ return ((SQLException)e).getSQLState();
}
+ return null;
}
public String getMessage() {
Modified: branches/7.4.x/common-core/src/main/java/org/teiid/core/TeiidRuntimeException.java
===================================================================
--- branches/7.4.x/common-core/src/main/java/org/teiid/core/TeiidRuntimeException.java 2011-06-08 18:23:36 UTC (rev 3235)
+++ branches/7.4.x/common-core/src/main/java/org/teiid/core/TeiidRuntimeException.java 2011-06-08 18:28:42 UTC (rev 3236)
@@ -22,10 +22,6 @@
package org.teiid.core;
-import java.io.PrintStream;
-import java.io.PrintWriter;
-import java.sql.SQLException;
-
import org.teiid.core.util.ExceptionUtil;
@@ -40,26 +36,9 @@
public class TeiidRuntimeException extends RuntimeException {
public static final long serialVersionUID = -4035276728007979320L;
- private static final String EMPTY_STRING = ""; //$NON-NLS-1$
public static final String CAUSED_BY_STRING = CorePlugin.Util.getString("RuntimeException.Caused_by"); //$NON-NLS-1$
//############################################################################################################################
- //# Static Methods #
- //############################################################################################################################
-
- /**
- * Utility method to get the name of a class, without package information.
- *
- * @param cls The class to get the name of
- * @return The name of the class, without package info
- */
- public static String getClassShortName( Class cls ) {
- if ( cls == null ) return EMPTY_STRING;
- String className = cls.getName();
- return className.substring( className.lastIndexOf('.')+1 );
- }
-
- //############################################################################################################################
//# Variables #
//############################################################################################################################
@@ -86,19 +65,6 @@
super(message);
}
- /**
- * Construct an instance with the specified error code and message. If the message is actually a key, the actual message will
- * be retrieved from a resource bundle using the key, and the specified parameters will be substituted for placeholders within
- * the message.
- * @param code The error code
- * @param message The error message or a resource bundle key
- */
- public TeiidRuntimeException(final int code, final String message) {
- super(message);
- // The following setCode call should be executed after setting the message
- setCode(code);
- }
-
public TeiidRuntimeException(final String code, final String message) {
super(message);
// The following setCode call should be executed after setting the message
@@ -125,23 +91,10 @@
*/
public TeiidRuntimeException(final Throwable e, final String message) {
super(message, e);
- setCode(e);
+ setCode(TeiidException.getCode(e));
}
/**
- * Construct an instance with the linked exception, error code, and error message specified. If the message is actually a
- * key, the error message will be retrieved from a resource bundle using the key.
- * @param e The exception to chain to this exception
- * @param code The error code
- * @param message The error message or a resource bundle key
- */
- public TeiidRuntimeException(final Throwable e, final int code, final String message) {
- super(message, e);
- // The following setCode call should be executed after setting the message
- setCode(code);
- }
-
- /**
* Construct an instance with the linked exception, error code, and error message specified. If the specified
* exception is a {@link TeiidException} or a MetaMatrixRuntimeException, the code will
* be set to the exception's code.
@@ -164,6 +117,7 @@
* Get the exception which is linked to this exception.
*
* @return The linked exception
+ * @deprecated use {@link #getCause()} instead
*/
public Throwable getChild() {
return this.getCause();
@@ -175,47 +129,13 @@
* @return The error code
*/
public String getCode() {
- if (code == null) {
- return "0"; //$NON-NLS-1$
- }
return this.code;
}
- public int getIntCode() {
- if (code == null) {
- return 0;
- }
- try {
- return Integer.parseInt(code);
- } catch (NumberFormatException e) {
-
- }
- return 0;
- }
-
- /**
- * Set the error code.
- *
- * @param code The error code
- */
- private void setCode( int code ) {
- this.code = Integer.toString(code);
- }
-
private void setCode( String code ) {
this.code = code;
}
- private void setCode(Throwable e) {
- if (e instanceof TeiidException) {
- this.code = (((TeiidException) e).getCode());
- } else if (e instanceof TeiidRuntimeException) {
- this.code = ((TeiidRuntimeException) e).getCode();
- } else if (e instanceof SQLException) {
- this.code = Integer.toString(((SQLException)e).getErrorCode());
- }
- }
-
/**
* Returns a string representation of this class.
*
@@ -225,12 +145,4 @@
return ExceptionUtil.getLinkedMessages(this);
}
- public void superPrintStackTrace(PrintStream output) {
- super.printStackTrace(output);
- }
-
- public void superPrintStackTrace(PrintWriter output) {
- super.printStackTrace(output);
- }
-
}
Modified: branches/7.4.x/common-core/src/test/java/org/teiid/core/TestMetaMatrixRuntimeException.java
===================================================================
--- branches/7.4.x/common-core/src/test/java/org/teiid/core/TestMetaMatrixRuntimeException.java 2011-06-08 18:23:36 UTC (rev 3235)
+++ branches/7.4.x/common-core/src/test/java/org/teiid/core/TestMetaMatrixRuntimeException.java 2011-06-08 18:28:42 UTC (rev 3236)
@@ -63,16 +63,16 @@
public void testMetaMatrixRuntimeExceptionWithNullThrowable() {
final TeiidRuntimeException err = new TeiidRuntimeException((Throwable)null);
- assertNull(err.getChild());
- assertEquals("0", err.getCode()); //$NON-NLS-1$
+ assertNull(err.getCause());
+ assertNull(err.getCode());
assertNull(err.getMessage());
}
public void testMetaMatrixRuntimeExceptionWithMessage() {
final TeiidRuntimeException err = new TeiidRuntimeException("Test"); //$NON-NLS-1$
- assertNull(err.getChild());
- assertEquals("0", err.getCode()); //$NON-NLS-1$
+ assertNull(err.getCause());
+ assertNull(err.getCode());
assertEquals("Test", err.getMessage()); //$NON-NLS-1$
}
@@ -80,7 +80,7 @@
public void testMetaMatrixRuntimeExceptionWithCodeAndMessage() {
final String code = "1234"; //$NON-NLS-1$
final TeiidRuntimeException err = new TeiidRuntimeException(code, "Test"); //$NON-NLS-1$
- assertNull(err.getChild());
+ assertNull(err.getCause());
assertEquals(code, err.getCode());
assertEquals("Test", err.getMessage()); //$NON-NLS-1$
@@ -90,7 +90,7 @@
final String code = "1234"; //$NON-NLS-1$
final TeiidRuntimeException child = new TeiidRuntimeException(code, "Child"); //$NON-NLS-1$
final TeiidRuntimeException err = new TeiidRuntimeException(child, "Test"); //$NON-NLS-1$
- assertSame(child, err.getChild());
+ assertSame(child, err.getCause());
assertEquals(code, err.getCode());
assertEquals("Test", err.getMessage()); //$NON-NLS-1$
@@ -100,7 +100,7 @@
final String code = "1234"; //$NON-NLS-1$
final TeiidRuntimeException child = new TeiidRuntimeException(code, "Child"); //$NON-NLS-1$
final TeiidRuntimeException err = new TeiidRuntimeException(child, "Code", "Test"); //$NON-NLS-1$ //$NON-NLS-2$
- assertSame(child, err.getChild());
+ assertSame(child, err.getCause());
assertEquals("Code", err.getCode()); //$NON-NLS-1$
assertEquals("Test", err.getMessage()); //$NON-NLS-1$
Modified: branches/7.4.x/engine/src/main/java/org/teiid/dqp/internal/process/DataTierTupleSource.java
===================================================================
--- branches/7.4.x/engine/src/main/java/org/teiid/dqp/internal/process/DataTierTupleSource.java 2011-06-08 18:23:36 UTC (rev 3235)
+++ branches/7.4.x/engine/src/main/java/org/teiid/dqp/internal/process/DataTierTupleSource.java 2011-06-08 18:28:42 UTC (rev 3236)
@@ -57,8 +57,6 @@
import org.teiid.dqp.message.AtomicRequestMessage;
import org.teiid.dqp.message.AtomicResultsMessage;
import org.teiid.events.EventDistributor;
-import org.teiid.logging.LogConstants;
-import org.teiid.logging.LogManager;
import org.teiid.metadata.Table;
import org.teiid.query.function.source.XMLSystemFunctions;
import org.teiid.query.processor.relational.RelationalNodeUtil;
Modified: branches/7.4.x/engine/src/main/java/org/teiid/dqp/internal/process/RequestWorkItem.java
===================================================================
--- branches/7.4.x/engine/src/main/java/org/teiid/dqp/internal/process/RequestWorkItem.java 2011-06-08 18:23:36 UTC (rev 3235)
+++ branches/7.4.x/engine/src/main/java/org/teiid/dqp/internal/process/RequestWorkItem.java 2011-06-08 18:28:42 UTC (rev 3236)
@@ -58,6 +58,7 @@
import org.teiid.dqp.service.TransactionContext;
import org.teiid.dqp.service.TransactionService;
import org.teiid.dqp.service.TransactionContext.Scope;
+import org.teiid.jdbc.SQLStates;
import org.teiid.logging.LogConstants;
import org.teiid.logging.LogManager;
import org.teiid.logging.MessageLevel;
@@ -223,7 +224,7 @@
state = ProcessingState.PROCESSING;
processNew();
if (isCanceled) {
- this.processingException = new TeiidProcessingException(QueryPlugin.Util.getString("QueryProcessor.request_cancelled", this.requestID)); //$NON-NLS-1$
+ this.processingException = new TeiidProcessingException(SQLStates.QUERY_CANCELED, QueryPlugin.Util.getString("QueryProcessor.request_cancelled", this.requestID)); //$NON-NLS-1$
state = ProcessingState.CLOSE;
}
}
@@ -626,10 +627,24 @@
}
LogManager.logDetail(LogConstants.CTX_DQP, processingException, "Sending error to client", requestID); //$NON-NLS-1$
ResultsMessage response = new ResultsMessage(requestMsg);
- response.setException(processingException);
+ Throwable exception = this.processingException;
+ if (isCanceled) {
+ exception = addCancelCode(exception);
+ }
+ response.setException(exception);
setAnalysisRecords(response);
receiver.receiveResults(response);
}
+
+ private Throwable addCancelCode(Throwable exception) {
+ if (exception instanceof TeiidException) {
+ TeiidException te = (TeiidException)exception;
+ if (SQLStates.QUERY_CANCELED.equals(te.getCode())) {
+ return exception;
+ }
+ }
+ return new TeiidProcessingException(exception, SQLStates.QUERY_CANCELED, exception.getMessage());
+ }
@Override
protected boolean shouldPause() {
Modified: branches/7.4.x/engine/src/main/java/org/teiid/query/processor/QueryProcessor.java
===================================================================
--- branches/7.4.x/engine/src/main/java/org/teiid/query/processor/QueryProcessor.java 2011-06-08 18:23:36 UTC (rev 3235)
+++ branches/7.4.x/engine/src/main/java/org/teiid/query/processor/QueryProcessor.java 2011-06-08 18:28:42 UTC (rev 3236)
@@ -34,6 +34,7 @@
import org.teiid.core.TeiidProcessingException;
import org.teiid.core.TeiidRuntimeException;
import org.teiid.core.util.Assertion;
+import org.teiid.jdbc.SQLStates;
import org.teiid.logging.LogConstants;
import org.teiid.logging.LogManager;
import org.teiid.logging.MessageLevel;
@@ -130,7 +131,7 @@
while(currentTime < context.getTimeSliceEnd() || context.isNonBlocking()) {
if (requestCanceled) {
- throw new TeiidProcessingException(QueryPlugin.Util.getString("QueryProcessor.request_cancelled", getProcessID())); //$NON-NLS-1$
+ throw new TeiidProcessingException(SQLStates.QUERY_CANCELED, QueryPlugin.Util.getString("QueryProcessor.request_cancelled", getProcessID())); //$NON-NLS-1$
}
if (currentTime > context.getTimeoutEnd()) {
throw new TeiidProcessingException("Query timed out"); //$NON-NLS-1$
13 years, 7 months
teiid SVN: r3235 - in branches/7.4.x/client/src: test/java/org/teiid/jdbc and 1 other directory.
by teiid-commits@lists.jboss.org
Author: shawkins
Date: 2011-06-08 14:23:36 -0400 (Wed, 08 Jun 2011)
New Revision: 3235
Modified:
branches/7.4.x/client/src/main/java/org/teiid/jdbc/StatementImpl.java
branches/7.4.x/client/src/test/java/org/teiid/jdbc/TestStatement.java
Log:
TEIID-1626 adding a reset of the status
Modified: branches/7.4.x/client/src/main/java/org/teiid/jdbc/StatementImpl.java
===================================================================
--- branches/7.4.x/client/src/main/java/org/teiid/jdbc/StatementImpl.java 2011-06-08 16:54:23 UTC (rev 3234)
+++ branches/7.4.x/client/src/main/java/org/teiid/jdbc/StatementImpl.java 2011-06-08 18:23:36 UTC (rev 3235)
@@ -240,6 +240,7 @@
this.batchedUpdates = null;
this.updateCounts = null;
this.outParamIndexMap.clear();
+ this.commandStatus = State.RUNNING;
}
/**
Modified: branches/7.4.x/client/src/test/java/org/teiid/jdbc/TestStatement.java
===================================================================
--- branches/7.4.x/client/src/test/java/org/teiid/jdbc/TestStatement.java 2011-06-08 16:54:23 UTC (rev 3234)
+++ branches/7.4.x/client/src/test/java/org/teiid/jdbc/TestStatement.java 2011-06-08 18:23:36 UTC (rev 3235)
@@ -129,6 +129,10 @@
statement.submitExecute("select 'hello world'");
Thread.sleep(100);
Mockito.verify(dqp).cancelRequest(0);
+ statement.setQueryTimeoutMS(1);
+ statement.submitExecute("select 'hello world'");
+ Thread.sleep(100);
+ Mockito.verify(dqp, Mockito.times(2)).cancelRequest(0);
}
}
13 years, 7 months