Author: rareddy
Date: 2012-05-07 14:40:54 -0400 (Mon, 07 May 2012)
New Revision: 4069
Added:
trunk/build/kits/jboss-as7/modules/org/jboss/teiid/translator/jpa/
trunk/build/kits/jboss-as7/modules/org/jboss/teiid/translator/jpa/main/
trunk/connectors/translator-jpa/
trunk/connectors/translator-jpa/pom.xml
trunk/connectors/translator-jpa/src/
trunk/connectors/translator-jpa/src/main/
trunk/connectors/translator-jpa/src/main/java/
trunk/connectors/translator-jpa/src/main/java/org/
trunk/connectors/translator-jpa/src/main/java/org/teiid/
trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/
trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/
trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPA2ExecutionFactory.java
trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPAMetadataProcessor.java
trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPAPlugin.java
trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPQLBaseExecution.java
trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPQLQueryExecution.java
trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPQLSelectVisitor.java
trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPQLUpdateExecution.java
trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPQLUpdateQueryVisitor.java
trunk/connectors/translator-jpa/src/main/resources/
trunk/connectors/translator-jpa/src/main/resources/META-INF/
trunk/connectors/translator-jpa/src/main/resources/META-INF/MANIFEST.MF
trunk/connectors/translator-jpa/src/main/resources/META-INF/services/
trunk/connectors/translator-jpa/src/main/resources/META-INF/services/org.teiid.translator.ExecutionFactory
trunk/connectors/translator-jpa/src/main/resources/org/
trunk/connectors/translator-jpa/src/main/resources/org/teiid/
trunk/connectors/translator-jpa/src/main/resources/org/teiid/translator/
trunk/connectors/translator-jpa/src/main/resources/org/teiid/translator/jpa/
trunk/connectors/translator-jpa/src/main/resources/org/teiid/translator/jpa/i18n.properties
trunk/connectors/translator-jpa/src/test/
trunk/connectors/translator-jpa/src/test/java/
trunk/connectors/translator-jpa/src/test/java/org/
trunk/connectors/translator-jpa/src/test/java/org/teiid/
trunk/connectors/translator-jpa/src/test/java/org/teiid/translator/
trunk/connectors/translator-jpa/src/test/java/org/teiid/translator/jpa/
trunk/connectors/translator-jpa/src/test/java/org/teiid/translator/jpa/TestJSelectJPQLVisitor.java
trunk/connectors/translator-jpa/src/test/resources/
trunk/connectors/translator-jpa/src/test/resources/sakila.ddl
trunk/connectors/translator-jpa/target/
trunk/connectors/translator-jpa/target/classes/
trunk/connectors/translator-jpa/target/classes/META-INF/
trunk/connectors/translator-jpa/target/classes/META-INF/MANIFEST.MF
Modified:
trunk/api/src/main/java/org/teiid/metadata/ColumnSet.java
trunk/api/src/main/java/org/teiid/metadata/Table.java
trunk/build/assembly/jboss-as7/dist.xml
trunk/build/kits/jboss-as7/standalone/configuration/standalone-teiid.xml
trunk/connectors/pom.xml
Log:
TEIID-2011: Adding initial code for supporting the JPA based translator
Modified: trunk/api/src/main/java/org/teiid/metadata/ColumnSet.java
===================================================================
--- trunk/api/src/main/java/org/teiid/metadata/ColumnSet.java 2012-05-07 18:28:19 UTC (rev
4068)
+++ trunk/api/src/main/java/org/teiid/metadata/ColumnSet.java 2012-05-07 18:40:54 UTC (rev
4069)
@@ -56,4 +56,12 @@
this.parent = parent;
}
+ public Column getColumn(String name) {
+ for (Column c:columns) {
+ if (c.getCanonicalName().equals(name.toUpperCase())) {
+ return c;
+ }
+ }
+ return null;
+ }
}
\ No newline at end of file
Modified: trunk/api/src/main/java/org/teiid/metadata/Table.java
===================================================================
--- trunk/api/src/main/java/org/teiid/metadata/Table.java 2012-05-07 18:28:19 UTC (rev
4068)
+++ trunk/api/src/main/java/org/teiid/metadata/Table.java 2012-05-07 18:40:54 UTC (rev
4069)
@@ -209,6 +209,15 @@
this.foriegnKeys = foriegnKeys;
}
+ public ForeignKey getForeignKey(String name) {
+ for (ForeignKey fk:this.foriegnKeys) {
+ if (fk.getName().equals(name)) {
+ return fk;
+ }
+ }
+ return null;
+ }
+
public List<KeyRecord> getIndexes() {
return this.indexes;
}
Modified: trunk/build/assembly/jboss-as7/dist.xml
===================================================================
--- trunk/build/assembly/jboss-as7/dist.xml 2012-05-07 18:28:19 UTC (rev 4068)
+++ trunk/build/assembly/jboss-as7/dist.xml 2012-05-07 18:40:54 UTC (rev 4069)
@@ -388,6 +388,28 @@
<outputDirectory>modules/org/jboss/teiid/translator/hive/main</outputDirectory>
<fileMode>0644</fileMode>
</binaries>
+ </moduleSet>
+
+ <moduleSet>
+ <includeSubModules>true</includeSubModules>
+ <useAllReactorProjects>true</useAllReactorProjects>
+ <includes>
+ <include>org.jboss.teiid.connectors:translator-jpa</include>
+ </includes>
+ <binaries>
+ <includeDependencies>true</includeDependencies>
+ <unpack>false</unpack>
+ <dependencySets>
+ <dependencySet>
+ <useProjectArtifact>true</useProjectArtifact>
+ <unpack>false</unpack>
+
<useTransitiveDependencies>false</useTransitiveDependencies>
+ <useDefaultExcludes>true</useDefaultExcludes>
+ </dependencySet>
+ </dependencySets>
+
<outputDirectory>modules/org/jboss/teiid/translator/jpa/main</outputDirectory>
+ <fileMode>0644</fileMode>
+ </binaries>
</moduleSet>
<!-- Include the JOPR plugin
Modified: trunk/build/kits/jboss-as7/standalone/configuration/standalone-teiid.xml
===================================================================
--- trunk/build/kits/jboss-as7/standalone/configuration/standalone-teiid.xml 2012-05-07
18:28:19 UTC (rev 4068)
+++ trunk/build/kits/jboss-as7/standalone/configuration/standalone-teiid.xml 2012-05-07
18:40:54 UTC (rev 4069)
@@ -308,6 +308,7 @@
<translator name="ws"
module="org.jboss.teiid.translator.ws"/>
<translator name="salesforce"
module="org.jboss.teiid.translator.salesforce"/>
<translator name="hive"
module="org.jboss.teiid.translator.hive"/>
+ <translator name="jpa2"
module="org.jboss.teiid.translator.jpa"/>
</subsystem>
<subsystem xmlns="urn:jboss:domain:threads:1.1">
Modified: trunk/connectors/pom.xml
===================================================================
--- trunk/connectors/pom.xml 2012-05-07 18:28:19 UTC (rev 4068)
+++ trunk/connectors/pom.xml 2012-05-07 18:40:54 UTC (rev 4069)
@@ -105,5 +105,6 @@
<module>translator-ws</module>
<module>translator-olap</module>
<module>translator-hive</module>
+ <module>translator-jpa</module>
</modules>
</project>
Added: trunk/connectors/translator-jpa/pom.xml
===================================================================
--- trunk/connectors/translator-jpa/pom.xml (rev 0)
+++ trunk/connectors/translator-jpa/pom.xml 2012-05-07 18:40:54 UTC (rev 4069)
@@ -0,0 +1,87 @@
+<?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>connectors</artifactId>
+ <groupId>org.jboss.teiid</groupId>
+ <version>8.1.0.Alpha1-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>translator-jpa</artifactId>
+ <groupId>org.jboss.teiid.connectors</groupId>
+ <name>JPA2 Translator</name>
+ <description>This translator provides access to any JPA based
entities</description>
+ <properties>
+
<version.org.hibernate.javax.persistence.hibernate-jpa-2.0-api>1.0.1.Final</version.org.hibernate.javax.persistence.hibernate-jpa-2.0-api>
+ </properties>
+
+ <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>
+ <dependency>
+ <groupId>org.hibernate.javax.persistence</groupId>
+ <artifactId>hibernate-jpa-2.0-api</artifactId>
+
<version>${version.org.hibernate.javax.persistence.hibernate-jpa-2.0-api}</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <configuration>
+ <archive>
+
<manifestFile>src/main/resources/META-INF/MANIFEST.MF</manifestFile>
+ </archive>
+ </configuration>
+ </plugin>
+ </plugins>
+
+ <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:
trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPA2ExecutionFactory.java
===================================================================
---
trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPA2ExecutionFactory.java
(rev 0)
+++
trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPA2ExecutionFactory.java 2012-05-07
18:40:54 UTC (rev 4069)
@@ -0,0 +1,278 @@
+/*
+ * 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.jpa;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+
+import org.teiid.core.util.PropertiesUtils;
+import org.teiid.language.Call;
+import org.teiid.language.Command;
+import org.teiid.language.QueryExpression;
+import org.teiid.metadata.MetadataFactory;
+import org.teiid.metadata.RuntimeMetadata;
+import org.teiid.translator.ExecutionContext;
+import org.teiid.translator.ExecutionFactory;
+import org.teiid.translator.ProcedureExecution;
+import org.teiid.translator.ResultSetExecution;
+import org.teiid.translator.SourceSystemFunctions;
+import org.teiid.translator.Translator;
+import org.teiid.translator.TranslatorException;
+import org.teiid.translator.UpdateExecution;
+import org.teiid.translator.jdbc.AliasModifier;
+import org.teiid.translator.jdbc.FunctionModifier;
+
+@Translator(name="jpa2", description="A translator for JPA2 based
entities")
+public class JPA2ExecutionFactory extends ExecutionFactory<EntityManagerFactory,
EntityManager> {
+ private Map<String, FunctionModifier> functionModifiers = new TreeMap<String,
FunctionModifier>(String.CASE_INSENSITIVE_ORDER);
+
+ @Override
+ public void start() throws TranslatorException {
+ super.start();
+ setSupportsInnerJoins(true);
+ setSupportsOrderBy(true);
+ setSupportsSelectDistinct(true);
+ setSupportedJoinCriteria(SupportedJoinCriteria.KEY);
+ setSupportsOuterJoins(true);
+
+ registerFunctionModifier(SourceSystemFunctions.LCASE, new
AliasModifier("lower")); //$NON-NLS-1$
+ registerFunctionModifier(SourceSystemFunctions.UCASE, new
AliasModifier("upper")); //$NON-NLS-1$
+ registerFunctionModifier(SourceSystemFunctions.CURDATE, new
AliasModifier("current_date")); //$NON-NLS-1$
+ registerFunctionModifier(SourceSystemFunctions.CURTIME, new
AliasModifier("current_time")); //$NON-NLS-1$
+ }
+
+ @Override
+ public EntityManager getConnection(EntityManagerFactory factory, ExecutionContext
executionContext) throws TranslatorException {
+ if (factory == null) {
+ return null;
+ }
+ return factory.createEntityManager();
+ }
+
+ @Override
+ public void closeConnection(EntityManager connection, EntityManagerFactory factory) {
+ connection.close();
+ }
+
+ @Override
+ public ResultSetExecution createResultSetExecution(QueryExpression command,
ExecutionContext executionContext, RuntimeMetadata metadata, EntityManager connection)
throws TranslatorException {
+ return new JPQLQueryExecution(this, command, executionContext, metadata, connection);
+ }
+
+ @Override
+ public ProcedureExecution createProcedureExecution(Call command, ExecutionContext
executionContext, RuntimeMetadata metadata, EntityManager connection) throws
TranslatorException {
+ return super.createProcedureExecution(command, executionContext, metadata,
connection);
+ }
+
+ @Override
+ public UpdateExecution createUpdateExecution(Command command, ExecutionContext
executionContext, RuntimeMetadata metadata, EntityManager connection) throws
TranslatorException {
+ return new JPQLUpdateExecution(command, executionContext, metadata, connection);
+ }
+
+ @Override
+ public void getMetadata(MetadataFactory mf, EntityManager em) throws TranslatorException
{
+ JPAMetadataProcessor metadataProcessor = new JPAMetadataProcessor();
+ PropertiesUtils.setBeanProperties(metadataProcessor, mf.getImportProperties(),
"importer"); //$NON-NLS-1$
+ metadataProcessor.getMetadata(mf, em);
+ }
+
+
+ @Override
+ public boolean supportsSelectExpression() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsAliasedTable() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsInlineViews() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsCompareCriteriaEquals() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsCompareCriteriaOrdered() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsLikeCriteria() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsInCriteria() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsInCriteriaSubquery() {
+ return false;
+ }
+
+ @Override
+ public boolean supportsIsNullCriteria() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsOrCriteria() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsNotCriteria() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsExistsCriteria() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsGroupBy() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsHaving() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsAggregatesSum() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsAggregatesAvg() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsAggregatesMin() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsAggregatesMax() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsAggregatesCount() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsAggregatesCountStar() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsAggregatesDistinct() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsScalarSubqueries() {
+ return true;
+ }
+
+ @Override
+ public boolean useAnsiJoin() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsDependentJoins() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsSelfJoins() {
+ return true;
+ }
+
+ @Override
+ public List<String> getSupportedFunctions() {
+ List<String> supportedFunctions = new ArrayList<String>();
+ supportedFunctions.addAll(getDefaultSupportedFunctions());
+
+ // String functions
+ supportedFunctions.add(SourceSystemFunctions.CONCAT);
+ supportedFunctions.add(SourceSystemFunctions.SUBSTRING);
+ supportedFunctions.add(SourceSystemFunctions.TRIM);
+ supportedFunctions.add(SourceSystemFunctions.LCASE);
+ supportedFunctions.add(SourceSystemFunctions.UCASE);
+ supportedFunctions.add(SourceSystemFunctions.LENGTH);
+ supportedFunctions.add(SourceSystemFunctions.LOCATE);
+
+ // airthamatic functions
+ supportedFunctions.add(SourceSystemFunctions.ABS);
+ supportedFunctions.add(SourceSystemFunctions.SQRT);
+ supportedFunctions.add(SourceSystemFunctions.MOD);
+ supportedFunctions.add(SourceSystemFunctions.CURDATE);
+ supportedFunctions.add(SourceSystemFunctions.CURTIME);
+
+ supportedFunctions.add(SourceSystemFunctions.COALESCE);
+ supportedFunctions.add(SourceSystemFunctions.NULLIF);
+
+ return supportedFunctions;
+ }
+
+ /**
+ * Return a map of function name to FunctionModifier.
+ * @return Map of function name to FunctionModifier.
+ */
+ public Map<String, FunctionModifier> getFunctionModifiers() {
+ return functionModifiers;
+ }
+
+ /**
+ * Add the {@link FunctionModifier} to the set of known modifiers.
+ * @param name
+ * @param modifier
+ */
+ public void registerFunctionModifier(String name, FunctionModifier modifier) {
+ this.functionModifiers.put(name, modifier);
+ }
+
+
+ public List<String> getDefaultSupportedFunctions(){
+ return Arrays.asList(new String[] { "+", "-", "*",
"/" }); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ }
+}
Added:
trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPAMetadataProcessor.java
===================================================================
---
trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPAMetadataProcessor.java
(rev 0)
+++
trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPAMetadataProcessor.java 2012-05-07
18:40:54 UTC (rev 4069)
@@ -0,0 +1,323 @@
+/*
+ * 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.jpa;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.persistence.EntityManager;
+import javax.persistence.metamodel.Attribute;
+import javax.persistence.metamodel.EmbeddableType;
+import javax.persistence.metamodel.EntityType;
+import javax.persistence.metamodel.ManagedType;
+import javax.persistence.metamodel.Metamodel;
+import javax.persistence.metamodel.PluralAttribute;
+import javax.persistence.metamodel.SingularAttribute;
+import javax.persistence.metamodel.Type.PersistenceType;
+
+import org.teiid.core.types.BlobType;
+import org.teiid.core.types.ClobType;
+import org.teiid.language.SQLConstants.Tokens;
+import org.teiid.metadata.Column;
+import org.teiid.metadata.ForeignKey;
+import org.teiid.metadata.KeyRecord;
+import org.teiid.metadata.MetadataFactory;
+import org.teiid.metadata.Table;
+import org.teiid.translator.TranslatorException;
+import org.teiid.translator.TypeFacility;
+
+/**
+ * TODO:
+ * - support of abstract entities is an issue, should we represent base and extended
types, just extended types?
+ *
+ */
+@SuppressWarnings("nls")
+public class JPAMetadataProcessor {
+ public static final String KEY_ASSOSIATED_WITH_FOREIGN_TABLE =
"assosiated_with_table";
+ public static final String ENTITYCLASS= "entity_class";
+
+ final static Map<Class<?>, Class<?>> map = new
HashMap<Class<?>, Class<?>>();
+ static {
+ map.put(boolean.class, Boolean.class);
+ map.put(byte.class, Byte.class);
+ map.put(short.class, Short.class);
+ map.put(char.class, Character.class);
+ map.put(int.class, Integer.class);
+ map.put(long.class, Long.class);
+ map.put(float.class, Float.class);
+ map.put(double.class, Double.class);
+ map.put(byte[].class, BlobType.class);
+ map.put(char[].class, ClobType.class);
+ map.put(Byte[].class, BlobType.class);
+ map.put(Character[].class, ClobType.class);
+
+ map.put(Boolean.class, Boolean.class);
+ map.put(Byte.class, Byte.class);
+ map.put(Short.class, Short.class);
+ map.put(Character.class, Character.class);
+ map.put(Integer.class, Integer.class);
+ map.put(Long.class, Long.class);
+ map.put(Float.class, Float.class);
+ map.put(Double.class, Double.class);
+ map.put(Calendar.class, java.sql.Timestamp.class);
+ }
+
+ public void getMetadata(MetadataFactory mf, EntityManager entityManager) throws
TranslatorException {
+ Metamodel model = entityManager.getMetamodel();
+
+ Set<EntityType<?>> entities = model.getEntities();
+ for (EntityType<?> entity:entities) {
+ addEntity(mf, model, entity);
+ }
+
+ // take a second swipe and add Foreign Keys
+ for (EntityType<?> entity:entities) {
+ Table t = mf.getTable(entity.getName());
+ addForeignKeys(mf, model, entity, t);
+ }
+ }
+
+ private Table addEntity(MetadataFactory mf, Metamodel model, EntityType<?> entity)
throws TranslatorException {
+ Table table = mf.getTable(entity.getName());
+ if (table == null) {
+ table = mf.addTable(entity.getName());
+ table.setSupportsUpdate(true);
+ table.setProperty(ENTITYCLASS, entity.getJavaType().getCanonicalName());
+ addPrimaryKey(mf, model, entity, table);
+ addSingularAttributes(mf, model, entity, table);
+ }
+ return table;
+ }
+
+ private boolean columnExists(String name, Table table) {
+ if (table.getColumns() == null) {
+ return false;
+ }
+ for (Column existingColumn: table.getColumns()) {
+ if (existingColumn.getName().equals(name)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private Column addColumn(MetadataFactory mf, String name, String type, Table
entityTable) throws TranslatorException {
+ if (!columnExists(name, entityTable)) {
+ Column c = mf.addColumn(name, type, entityTable);
+ c.setUpdatable(true);
+ return c;
+ }
+ return entityTable.getColumn(name);
+ }
+
+ private void addForiegnKey(MetadataFactory mf, String name, List<String>
columnNames, String referenceTable, Table table) throws TranslatorException {
+ ForeignKey fk = mf.addForiegnKey("FK_"+name, columnNames, referenceTable,
table);
+ for (String column:columnNames) {
+ Column c = table.getColumn(column);
+ c.setProperty(KEY_ASSOSIATED_WITH_FOREIGN_TABLE,
mf.getName()+Tokens.DOT+referenceTable);
+ }
+ fk.setNameInSource(name);
+ }
+
+ private void addSingularAttributes(MetadataFactory mf, Metamodel model,
ManagedType<?> entity, Table entityTable) throws TranslatorException {
+ for (Attribute<?, ?> attr:entity.getAttributes()) {
+ if (!attr.isCollection()) {
+ boolean simpleType = isSimpleType(attr.getJavaType());
+ if (simpleType) {
+ Column column = addColumn(mf, attr.getName(),
TypeFacility.getDataTypeName(getJavaDataType(attr.getJavaType())), entityTable);
+ if (((SingularAttribute)attr).isOptional()) {
+ column.setDefaultValue(null);
+ }
+ }
+ else {
+ boolean classFound = false;
+ // If this attribute is a @Embeddable then add its columns as
+ // this tables columns
+ for (EmbeddableType<?> embeddable:model.getEmbeddables()) {
+ if (embeddable.getJavaType().equals(attr.getJavaType())) {
+ addSingularAttributes(mf, model, embeddable, entityTable);
+ classFound = true;
+ break;
+ }
+ }
+
+ if (!classFound) {
+ // if the attribute is @Entity then add entity's PK as column on this
+ // table, then add that column as FK
+ for (EntityType et:model.getEntities()) {
+ if (et.getJavaType().equals(attr.getJavaType())) {
+ Table attributeTable = addEntity(mf, model, et);
+ KeyRecord pk = attributeTable.getPrimaryKey();
+ if (pk != null) { // TODO: entities must have PK, so this check is not needed.
+ ArrayList<String> keys = new ArrayList<String>();
+ for (Column column:pk.getColumns()) {
+ addColumn(mf, column.getName(), column.getDatatype().getRuntimeTypeName(),
entityTable);
+ keys.add(column.getName());
+ }
+ if (!foreignKeyExists(keys, entityTable)) {
+ addForiegnKey(mf, attr.getName(), keys, attributeTable.getName(),
entityTable);
+ }
+ }
+ else {
+ throw new TranslatorException(JPAPlugin.Util.gs(JPAPlugin.Event.TEIID14001,
attributeTable.getName()));
+ }
+ classFound = true;
+ break;
+ }
+ }
+ }
+
+ if (!classFound) {
+ throw new TranslatorException(JPAPlugin.Util.gs(JPAPlugin.Event.TEIID14002,
attr.getName()));
+ }
+ }
+ }
+ }
+ }
+
+ private boolean isSimpleType(Class type) {
+ return type.isPrimitive() || type.equals(String.class)
+ || type.equals(BigDecimal.class) || type.equals(Date.class)
+ || type.equals(BigInteger.class)
+ || map.containsKey(type);
+ }
+
+ private void addForeignKeys(MetadataFactory mf, Metamodel model, ManagedType<?>
entity, Table entityTable) throws TranslatorException {
+ for (Attribute<?, ?> attr:entity.getAttributes()) {
+ if (attr.isCollection()) {
+
+ PluralAttribute pa = (PluralAttribute)attr;
+ Table forignTable = null;
+
+ for (EntityType et:model.getEntities()) {
+ if (et.getJavaType().equals(pa.getElementType().getJavaType())) {
+ forignTable = mf.getTable(et.getName());
+ break;
+ }
+ }
+
+ if (forignTable == null) {
+ continue;
+ }
+
+ // add foreign keys as columns in table first; check if they exist first
+ ArrayList<String> keys = new ArrayList<String>();
+ KeyRecord pk = entityTable.getPrimaryKey();
+ for (Column entityColumn:pk.getColumns()) {
+ addColumn(mf, entityColumn.getName(),
entityColumn.getDatatype().getRuntimeTypeName(), forignTable);
+ keys.add(entityColumn.getName());
+ }
+
+ if (!foreignKeyExists(keys, forignTable)) {
+ addForiegnKey(mf, attr.getName(), keys, entityTable.getName(), forignTable);
+ }
+ }
+ }
+ }
+
+ private boolean foreignKeyExists(List<String> keys, Table forignTable) {
+ boolean fkExists = false;
+ for (ForeignKey fk:forignTable.getForeignKeys()) {
+ boolean allKeysFound = true;
+ for (String key:keys) {
+ boolean keyfound = false;
+ for (Column col:fk.getColumns()) {
+ if (col.getName().equals(key)) {
+ keyfound = true;
+ break;
+ }
+ }
+ if (!keyfound) {
+ allKeysFound = false;
+ break;
+ }
+ }
+
+ if (allKeysFound) {
+ fkExists = true;
+ break;
+ }
+ }
+ return fkExists;
+ }
+
+ private void addPrimaryKey(MetadataFactory mf, Metamodel model, EntityType<?>
entity, Table entityTable) throws TranslatorException {
+ // figure out the PK
+ if (entity.hasSingleIdAttribute()) {
+ if (entity.getIdType().getPersistenceType().equals(PersistenceType.BASIC)) {
+ SingularAttribute<?, ?> pkattr =
entity.getId(entity.getIdType().getJavaType());
+ addColumn(mf, pkattr.getName(),
TypeFacility.getDataTypeName(getJavaDataType(pkattr.getJavaType())), entityTable);
+ mf.addPrimaryKey("PK_"+entity.getName(), Arrays.asList(pkattr.getName()),
entityTable); //$NON-NLS-1$
+ }
+ else if (entity.getIdType().getPersistenceType().equals(PersistenceType.EMBEDDABLE))
{
+ SingularAttribute<?, ?> pkattr =
entity.getId(entity.getIdType().getJavaType());
+ for (EmbeddableType<?> embeddable:model.getEmbeddables()) {
+ if (embeddable.getJavaType().equals(pkattr.getJavaType())) {
+ addSingularAttributes(mf, model, embeddable, entityTable);
+ ArrayList<String> keys = new ArrayList<String>();
+ for (Attribute<?, ?> attr:embeddable.getAttributes()) {
+ if (isSimpleType(attr.getJavaType())) {
+ keys.add(attr.getName());
+ }
+ else {
+ throw new TranslatorException(JPAPlugin.Util.gs(JPAPlugin.Event.TEIID14003,
entityTable.getName()));
+ }
+ }
+ mf.addPrimaryKey("PK_"+pkattr.getName(), keys, entityTable);
+ break;
+ }
+ }
+ }
+ }
+ else {
+ // Composite PK. If the PK is specified with @IdClass then read its attributes,
+ // if those attributes are not found, add them as columns then as composite PK
+ ArrayList<String> keys = new ArrayList<String>();
+ for (Object obj:entity.getIdClassAttributes()) {
+ SingularAttribute<?, ?> attr = (SingularAttribute)obj;
+ addColumn(mf, attr.getName(),
TypeFacility.getDataTypeName(getJavaDataType(attr.getJavaType())), entityTable);
+ keys.add(attr.getName());
+ }
+ mf.addPrimaryKey("PK_"+entity.getName(), keys, entityTable);
+ }
+ }
+
+ private Class getJavaDataType(Class type) {
+ if (type.equals(Date.class)) {
+ return java.sql.Timestamp.class;
+ }
+
+ if (type.isPrimitive()) {
+ return map.get(type); // usage
+ }
+ return type;
+ }
+
+}
Added:
trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPAPlugin.java
===================================================================
--- trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPAPlugin.java
(rev 0)
+++
trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPAPlugin.java 2012-05-07
18:40:54 UTC (rev 4069)
@@ -0,0 +1,45 @@
+/*
+ * 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.jpa;
+
+import java.util.ResourceBundle;
+
+import org.teiid.core.BundleUtil;
+
+
+public class JPAPlugin {
+
+ public static final String PLUGIN_ID = "org.teiid.translator.jpa" ;
//$NON-NLS-1$
+
+ private static final String BUNDLE_NAME = PLUGIN_ID + ".i18n";
//$NON-NLS-1$
+ public static final BundleUtil Util = new
BundleUtil(PLUGIN_ID,BUNDLE_NAME,ResourceBundle.getBundle(BUNDLE_NAME));
+
+ public static enum Event implements BundleUtil.Event{
+ TEIID14001,
+ TEIID14002,
+ TEIID14003,
+ TEIID14004,
+ TEIID14005,
+ TEIID14006,
+ TEIID14007
+ }
+}
Added:
trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPQLBaseExecution.java
===================================================================
---
trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPQLBaseExecution.java
(rev 0)
+++
trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPQLBaseExecution.java 2012-05-07
18:40:54 UTC (rev 4069)
@@ -0,0 +1,41 @@
+/*
+ * 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.jpa;
+
+import javax.persistence.EntityManager;
+
+import org.teiid.metadata.RuntimeMetadata;
+import org.teiid.translator.ExecutionContext;
+
+public class JPQLBaseExecution {
+
+ protected ExecutionContext executionContext;
+ protected RuntimeMetadata metadata;
+ protected EntityManager enityManager;
+
+ protected JPQLBaseExecution(ExecutionContext executionContext, RuntimeMetadata metadata,
EntityManager em) {
+ this.executionContext = executionContext;
+ this.metadata = metadata;
+ this.enityManager = em;
+ }
+
+}
Added:
trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPQLQueryExecution.java
===================================================================
---
trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPQLQueryExecution.java
(rev 0)
+++
trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPQLQueryExecution.java 2012-05-07
18:40:54 UTC (rev 4069)
@@ -0,0 +1,86 @@
+/*
+ * 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.jpa;
+
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+
+import org.teiid.language.QueryExpression;
+import org.teiid.language.Select;
+import org.teiid.logging.LogConstants;
+import org.teiid.logging.LogManager;
+import org.teiid.metadata.RuntimeMetadata;
+import org.teiid.translator.DataNotAvailableException;
+import org.teiid.translator.ExecutionContext;
+import org.teiid.translator.ResultSetExecution;
+import org.teiid.translator.TranslatorException;
+
+public class JPQLQueryExecution extends JPQLBaseExecution implements ResultSetExecution
{
+ private QueryExpression command;
+ private Iterator resultsIterator;
+ private JPA2ExecutionFactory executionFactory;
+
+ public JPQLQueryExecution(JPA2ExecutionFactory executionFactory, QueryExpression
command, ExecutionContext executionContext, RuntimeMetadata metadata, EntityManager em) {
+ super(executionContext, metadata, em);
+ this.command = command;
+ this.executionFactory = executionFactory;
+ }
+
+ @Override
+ public void execute() throws TranslatorException {
+ String jpql = JPQLSelectVisitor.getJPQLString((Select)this.command,
this.executionFactory, this.metadata);
+
+ LogManager.logTrace(LogConstants.CTX_CONNECTOR, "JPA Source-Query:", jpql);
//$NON-NLS-1$
+
+ Query query = this.enityManager.createQuery(jpql);
+ List results = query.getResultList();
+ this.resultsIterator = results.iterator();
+ }
+
+ @Override
+ public List<?> next() throws TranslatorException, DataNotAvailableException {
+ if (this.resultsIterator != null && this.resultsIterator.hasNext()) {
+ Object obj = this.resultsIterator.next();
+ if (obj instanceof Object[]) {
+ return Arrays.asList((Object[])obj);
+ }
+ return Arrays.asList(obj);
+ }
+ return null;
+ }
+
+ @Override
+ public void close() {
+ // no close
+ this.resultsIterator = null;
+
+ }
+
+ @Override
+ public void cancel() throws TranslatorException {
+ // no cancel
+ }
+}
Added:
trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPQLSelectVisitor.java
===================================================================
---
trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPQLSelectVisitor.java
(rev 0)
+++
trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPQLSelectVisitor.java 2012-05-07
18:40:54 UTC (rev 4069)
@@ -0,0 +1,448 @@
+/*
+ * 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.jpa;
+
+import static org.teiid.language.SQLConstants.Reserved.*;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.teiid.language.*;
+import org.teiid.language.Join.JoinType;
+import org.teiid.language.SQLConstants.Tokens;
+import org.teiid.language.visitor.HierarchyVisitor;
+import org.teiid.language.visitor.SQLStringVisitor;
+import org.teiid.metadata.AbstractMetadataRecord;
+import org.teiid.metadata.ForeignKey;
+import org.teiid.metadata.RuntimeMetadata;
+import org.teiid.metadata.Table;
+import org.teiid.translator.TranslatorException;
+/**
+ * This visitor converts the Teiid command into JPQL string
+ */
+public class JPQLSelectVisitor extends HierarchyVisitor {
+ protected JPA2ExecutionFactory executionFactory;
+ protected static final String UNDEFINED = "<undefined>"; //$NON-NLS-1$
+ private LinkedList<JoinTable> joins = new LinkedList<JoinTable>();
+ protected ArrayList<TranslatorException> exceptions = new
ArrayList<TranslatorException>();
+ protected LinkedHashMap<String, NamedTable> implicitGroups = new
LinkedHashMap<String, NamedTable>();
+ protected AtomicInteger aliasCounter = new AtomicInteger(0);
+ protected RuntimeMetadata metadata;
+
+ public JPQLSelectVisitor(JPA2ExecutionFactory executionFactory, RuntimeMetadata
metadata) {
+ super(false);
+ this.executionFactory = executionFactory;
+ this.metadata = metadata;
+ }
+
+ public static String getJPQLString(Select obj, JPA2ExecutionFactory executionFactory,
RuntimeMetadata metadata) throws TranslatorException {
+ JPQLSelectVisitor visitor = new JPQLSelectVisitor(executionFactory, metadata);
+
+ visitor.visitNode(obj);
+
+ if (!visitor.exceptions.isEmpty()) {
+ throw visitor.exceptions.get(0);
+ }
+
+ return visitor.convertToQuery(obj);
+ }
+
+ private String convertToQuery(Select obj) {
+ JPQLSelectStringVisitor visitor = new JPQLSelectStringVisitor(this);
+ visitor.visitNode(obj);
+ return visitor.toString();
+ }
+
+ @Override
+ public void visit(Select obj) {
+ visitNodes(obj.getDerivedColumns());
+ visitNodes(obj.getFrom());
+ visitNode(obj.getWhere());
+ visitNode(obj.getGroupBy());
+ visitNode(obj.getHaving());
+ visitNode(obj.getOrderBy());
+ }
+
+ @Override
+ public void visit(ColumnReference obj) {
+ AbstractMetadataRecord record = obj.getMetadataObject();
+ if (record != null) {
+ String name =
record.getProperty(JPAMetadataProcessor.KEY_ASSOSIATED_WITH_FOREIGN_TABLE, false);
+ if (name != null) {
+ try {
+ Table t = this.metadata.getTable(name);
+ if (this.implicitGroups.get(name) == null) {
+ this.implicitGroups.put(name, new NamedTable(t.getName(),
"J_"+this.aliasCounter.getAndIncrement(), t)); //$NON-NLS-1$
+ }
+ } catch (TranslatorException e) {
+ exceptions.add(e);
+ }
+ }
+ }
+ }
+
+ private boolean alreadyInJoin(String tableName) {
+ for(JoinTable joinTable:this.joins) {
+ if ((joinTable.left != null &&
joinTable.left.getMetadataObject().getFullName().equals(tableName))
+ || (joinTable.right != null &&
joinTable.right.getMetadataObject().getFullName().equals(tableName))) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public void visit(NamedTable obj) {
+ if (implicitGroups.isEmpty()) {
+ this.joins.add(new JoinTable(obj, null, JoinType.INNER_JOIN));
+ }
+ else {
+ for (NamedTable table:this.implicitGroups.values()) {
+ this.joins.add(new JoinTable(obj, table, JoinType.INNER_JOIN));
+ }
+ }
+ }
+
+ @Override
+ public void visit(Join obj) {
+ try {
+ handleJoin(obj);
+ for (NamedTable table:this.implicitGroups.values()) {
+ NamedTable parent = findParent(table);
+ if (parent != null) {
+ if (!alreadyInJoin(table.getMetadataObject().getFullName())) {
+ this.joins.add(new JoinTable(parent, table, JoinType.INNER_JOIN));
+ }
+ }
+ else {
+ exceptions.add(new
TranslatorException(JPAPlugin.Util.gs(JPAPlugin.Event.TEIID14004, table.getName())));
+ }
+ }
+ } catch (TranslatorException e) {
+ exceptions.add(e);
+ }
+ }
+
+ private NamedTable findParent(NamedTable child) {
+ for (JoinTable jt:this.joins) {
+ if (jt.getParent() != null) {
+ if (isParentOf(jt.getParent(), child)) {
+ return jt.getParent();
+ }
+ }
+
+ if (jt.getChild() != null) {
+ if (isParentOf(jt.getChild(), child)) {
+ return jt.getChild();
+ }
+ }
+ }
+ return null;
+ }
+
+ private JoinTable handleJoin(Join obj) throws TranslatorException {
+ TableReference left = obj.getLeftItem();
+ TableReference right = obj.getRightItem();
+
+ if ((left instanceof NamedTable) && (right instanceof NamedTable)) {
+ JoinTable join = handleJoin(obj.getJoinType(), left, right, true);
+ this.joins.add(join);
+ return join;
+ }
+
+ JoinTable leftJoin = null;
+ if (left instanceof Join) {
+ leftJoin = handleJoin((Join)left);
+ if (right instanceof NamedTable) {
+ JoinTable join = handleJoin(obj.getJoinType(), leftJoin, (NamedTable)right);
+ this.joins.add(join);
+ return join;
+ }
+ }
+
+ JoinTable rightJoin = null;
+ if (right instanceof Join) {
+ rightJoin = handleJoin((Join)right);
+ if (left instanceof NamedTable) {
+ JoinTable join = handleJoin(obj.getJoinType(), (NamedTable)left, rightJoin);
+ this.joins.add(join);
+ return join;
+ }
+ }
+ throw new TranslatorException(JPAPlugin.Util.gs(JPAPlugin.Event.TEIID14005));
+ }
+
+ private JoinTable handleJoin(Join.JoinType joinType, JoinTable left, NamedTable right)
throws TranslatorException {
+ // first we need to find correct parent for the right
+ JoinTable withParent = handleJoin(joinType, left.getParent(), right, false);
+ JoinTable withChild = handleJoin(joinType, left.getChild(), right, false);
+
+ NamedTable parent = (withParent.getParent() !=
null)?withParent.getParent():withChild.getParent();
+ if (parent != null) {
+ return handleJoin(joinType, parent, right, true);
+ }
+ throw new TranslatorException(JPAPlugin.Util.gs(JPAPlugin.Event.TEIID14006));
+ }
+
+ private JoinTable handleJoin(Join.JoinType joinType, NamedTable left, JoinTable right)
throws TranslatorException {
+ // first we need to find correct parent for the left
+ JoinTable withParent = handleJoin(joinType, left, right.getParent(), false);
+ JoinTable withChild = handleJoin(joinType, left, right.getChild(), false);
+
+ NamedTable parent = (withParent.getParent() !=
null)?withParent.getParent():withChild.getParent();
+ if (parent != null) {
+ return handleJoin(joinType, left, parent, true);
+ }
+ throw new TranslatorException(JPAPlugin.Util.gs(JPAPlugin.Event.TEIID14006));
+ }
+
+ private JoinTable handleJoin(Join.JoinType joinType, TableReference left, TableReference
right, boolean fixCorrelatedNames) {
+ // both sides are named tables
+ NamedTable leftTable = (NamedTable)left;
+ NamedTable rightTable = (NamedTable)right;
+ JoinTable joinTable = new JoinTable(leftTable, rightTable, joinType);
+
+ if (fixCorrelatedNames) {
+ // fix left table's correleated name
+ NamedTable table =
this.implicitGroups.get(leftTable.getMetadataObject().getFullName());
+ if (table != null) {
+ table.setCorrelationName(leftTable.getCorrelationName());
+ }
+
+ // fix right table's correleated name
+ table = this.implicitGroups.get(rightTable.getMetadataObject().getFullName());
+ if (table != null) {
+ table.setCorrelationName(rightTable.getCorrelationName());
+ }
+ }
+ return joinTable;
+ }
+
+ private boolean isParentOf(NamedTable parent, NamedTable child) {
+ for (ForeignKey fk:parent.getMetadataObject().getForeignKeys()){
+ if (fk.getReferenceTableName().equals(child.getMetadataObject().getName())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ static class JoinTable {
+ NamedTable parent;
+ NamedTable child;
+ NamedTable left;
+ NamedTable right;
+ String childAttributeName;
+ String parentAttributeName;
+ JoinType joinType;
+
+ JoinTable(NamedTable customer, NamedTable address, JoinType type) {
+ this.left = customer;
+ this.right = address;
+ this.joinType = type;
+ if (address == null) {
+ this.parent = customer;
+ this.parentAttributeName = customer.getName();
+ }
+ else {
+ for (ForeignKey fk:customer.getMetadataObject().getForeignKeys()){
+ if (fk.getReferenceTableName().equals(address.getMetadataObject().getName())) {
+ this.parent = customer;
+ this.child = address;
+ this.childAttributeName = fk.getNameInSource();
+ this.parentAttributeName = customer.getName();
+ }
+ }
+ if (this.parent == null) {
+ for (ForeignKey fk:address.getMetadataObject().getForeignKeys()){
+ if
(fk.getReferenceTableName().equals(customer.getMetadataObject().getName())) {
+ this.parent = address;
+ this.child = customer;
+ this.childAttributeName = fk.getNameInSource();
+ this.parentAttributeName = customer.getName();
+ }
+ }
+ }
+ }
+ }
+
+ NamedTable getParent() {
+ return this.parent;
+ }
+
+ NamedTable getChild() {
+ return this.child;
+ }
+
+ NamedTable getLeft() {
+ return this.left;
+ }
+
+ NamedTable getRight() {
+ return this.right;
+ }
+
+ String childAttributeName() {
+ return this.childAttributeName;
+ }
+
+ String parentAttributeName() {
+ return this.parentAttributeName;
+ }
+
+ public boolean isLeftParent() {
+ return this.left == this.parent;
+ }
+ }
+
+
+ static class JPQLSelectStringVisitor extends SQLStringVisitor {
+ private JPQLSelectVisitor visitor;
+
+ public JPQLSelectStringVisitor(JPQLSelectVisitor visitor) {
+ this.visitor = visitor;
+ }
+
+ @Override
+ public void visit(Select obj) {
+
+ buffer.append(SELECT).append(Tokens.SPACE);
+
+ if (obj.isDistinct()) {
+ buffer.append(DISTINCT).append(Tokens.SPACE);
+ }
+
+ append(obj.getDerivedColumns());
+
+ if (obj.getFrom() != null && !obj.getFrom().isEmpty()) {
+ buffer.append(Tokens.SPACE).append(FROM).append(Tokens.SPACE);
+ append(obj.getFrom());
+ }
+
+ if (obj.getWhere() != null) {
+ buffer.append(Tokens.SPACE)
+ .append(WHERE)
+ .append(Tokens.SPACE);
+ append(obj.getWhere());
+ }
+ if (obj.getGroupBy() != null) {
+ buffer.append(Tokens.SPACE);
+ append(obj.getGroupBy());
+ }
+ if (obj.getHaving() != null) {
+ buffer.append(Tokens.SPACE)
+ .append(HAVING)
+ .append(Tokens.SPACE);
+ append(obj.getHaving());
+ }
+ if (obj.getOrderBy() != null) {
+ buffer.append(Tokens.SPACE);
+ append(obj.getOrderBy());
+ }
+ }
+
+ @Override
+ public void visit(ColumnReference column) {
+ AbstractMetadataRecord record = column.getMetadataObject();
+ if (record != null) {
+ String name =
record.getProperty(JPAMetadataProcessor.KEY_ASSOSIATED_WITH_FOREIGN_TABLE, false);
+ if (name == null) {
+ buffer.append(column.getTable().getCorrelationName()).append(Tokens.DOT).append(column.getMetadataObject().getName());
+ }
+ else {
+
buffer.append(this.visitor.implicitGroups.get(name).getCorrelationName()).append(Tokens.DOT).append(column.getMetadataObject().getName());
+ }
+ }
+ else {
+ buffer.append(column.getName());
+ }
+ }
+
+ @Override
+ public void visit(Join obj) {
+ addFromClause();
+ }
+
+ @Override
+ public void visit(Function func) {
+ if (visitor.executionFactory.getFunctionModifiers().containsKey(func.getName()))
{
+
visitor.executionFactory.getFunctionModifiers().get(func.getName()).translate(func);
+ }
+ super.visit(func);
+ }
+
+ @Override
+ public void visit(NamedTable obj) {
+ addFromClause();
+ }
+
+ private void addFromClause() {
+ boolean first = true;
+ for (JoinTable joinTable:this.visitor.joins) {
+ if (!joinTable.isLeftParent() && joinTable.joinType ==
JoinType.LEFT_OUTER_JOIN) {
+ joinTable.joinType = JoinType.RIGHT_OUTER_JOIN;
+ }
+ if (first) {
+ buffer.append(joinTable.getParent().getName());
+ buffer.append(Tokens.SPACE);
+ buffer.append(AS).append(Tokens.SPACE);
+ buffer.append(joinTable.getParent().getCorrelationName());
+ first = false;
+ }
+ if (joinTable.getChild() != null) {
+ buffer.append(Tokens.SPACE);
+ switch(joinTable.joinType) {
+ case CROSS_JOIN:
+ buffer.append(CROSS);
+ break;
+ case FULL_OUTER_JOIN:
+ buffer.append(FULL)
+ .append(Tokens.SPACE)
+ .append(OUTER);
+ break;
+ case INNER_JOIN:
+ buffer.append(INNER);
+ break;
+ case LEFT_OUTER_JOIN:
+ buffer.append(LEFT)
+ .append(Tokens.SPACE)
+ .append(OUTER);
+ break;
+ case RIGHT_OUTER_JOIN:
+ buffer.append(RIGHT)
+ .append(Tokens.SPACE)
+ .append(OUTER);
+ break;
+ default: buffer.append(UNDEFINED);
+ }
+ buffer.append(Tokens.SPACE).append(JOIN).append(Tokens.SPACE);
+
buffer.append(joinTable.getParent().getCorrelationName()).append(Tokens.DOT).append(joinTable.childAttributeName());
+ buffer.append(Tokens.SPACE);
+ buffer.append(AS).append(Tokens.SPACE);
+ buffer.append(joinTable.getChild().getCorrelationName());
+ }
+ }
+ }
+ }
+}
Added:
trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPQLUpdateExecution.java
===================================================================
---
trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPQLUpdateExecution.java
(rev 0)
+++
trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPQLUpdateExecution.java 2012-05-07
18:40:54 UTC (rev 4069)
@@ -0,0 +1,124 @@
+/*
+ * 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.jpa;
+
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+
+import org.teiid.core.TeiidException;
+import org.teiid.core.util.PropertiesUtils;
+import org.teiid.core.util.ReflectionHelper;
+import org.teiid.language.*;
+import org.teiid.logging.LogConstants;
+import org.teiid.logging.LogManager;
+import org.teiid.metadata.Column;
+import org.teiid.metadata.RuntimeMetadata;
+import org.teiid.translator.DataNotAvailableException;
+import org.teiid.translator.ExecutionContext;
+import org.teiid.translator.TranslatorException;
+import org.teiid.translator.UpdateExecution;
+
+public class JPQLUpdateExecution extends JPQLBaseExecution implements UpdateExecution {
+ private Command command;
+ private int[] results;
+
+ public JPQLUpdateExecution(Command command, ExecutionContext executionContext,
RuntimeMetadata metadata, EntityManager em) {
+ super(executionContext, metadata, em);
+ this.command = command;
+ }
+
+ @Override
+ public void execute() throws TranslatorException {
+ if (command instanceof BatchedUpdates) {
+ BatchedUpdates updates = (BatchedUpdates)this.command;
+ this.results = new int[updates.getUpdateCommands().size()];
+ int index = 0;
+ for (Command cmd:updates.getUpdateCommands()) {
+ this.results[index++] = executeUpdate(cmd);
+ }
+ }
+ else if (this.command instanceof Insert) {
+ this.results = new int[1];
+ Object entity = handleInsert((Insert)this.command);
+ this.enityManager.merge(entity);
+ this.results[0] = 1;
+ }
+ else {
+ // update or delete
+ this.results = new int[1];
+ this.results[0] = executeUpdate(this.command);
+ }
+ }
+
+ private int executeUpdate(Command cmd) throws TranslatorException {
+ String jpql = JPQLUpdateQueryVisitor.getJPQLString(cmd);
+ LogManager.logTrace(LogConstants.CTX_CONNECTOR, "JPA Source-Query:", jpql);
//$NON-NLS-1$
+ Query query = this.enityManager.createQuery(jpql);
+ return query.executeUpdate();
+ }
+
+ @Override
+ public int[] getUpdateCounts() throws DataNotAvailableException, TranslatorException {
+ return this.results;
+ }
+
+ @Override
+ public void close() {
+ }
+
+ @Override
+ public void cancel() throws TranslatorException {
+ }
+
+ private Object handleInsert(Insert insert) throws TranslatorException {
+ try {
+ String entityClassName =
insert.getTable().getMetadataObject().getProperty(JPAMetadataProcessor.ENTITYCLASS,
false);
+ Object entity = ReflectionHelper.create(entityClassName, null,
this.executionContext.getCommandContext().getVDBClassLoader());
+
+ List<ColumnReference> columns = insert.getColumns();
+ List<Expression> values =
((ExpressionValueSource)insert.getValueSource()).getValues();
+ if(columns.size() != values.size()) {
+ throw new TranslatorException(JPAPlugin.Util.gs(JPAPlugin.Event.TEIID14007));
+ }
+ for(int i = 0; i < columns.size(); i++) {
+ Column column = columns.get(i).getMetadataObject();
+ Object value = values.get(i);
+
+ // do not add the derived columns
+ String name =
column.getProperty(JPAMetadataProcessor.KEY_ASSOSIATED_WITH_FOREIGN_TABLE, false);
+ if (name == null) {
+ if(value instanceof Literal) {
+ Literal literalValue = (Literal)value;
+ PropertiesUtils.setBeanProperty(entity, column.getName(),
literalValue.getValue());
+ } else {
+ PropertiesUtils.setBeanProperty(entity, column.getName(), value);
+ }
+ }
+ }
+ return entity;
+ } catch (TeiidException e) {
+ throw new TranslatorException(e);
+ }
+ }
+}
Added:
trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPQLUpdateQueryVisitor.java
===================================================================
---
trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPQLUpdateQueryVisitor.java
(rev 0)
+++
trunk/connectors/translator-jpa/src/main/java/org/teiid/translator/jpa/JPQLUpdateQueryVisitor.java 2012-05-07
18:40:54 UTC (rev 4069)
@@ -0,0 +1,100 @@
+/*
+ * 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.jpa;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.teiid.language.ColumnReference;
+import org.teiid.language.Command;
+import org.teiid.language.NamedTable;
+import org.teiid.language.SQLConstants.Tokens;
+import org.teiid.language.visitor.HierarchyVisitor;
+import org.teiid.language.visitor.SQLStringVisitor;
+import org.teiid.metadata.AbstractMetadataRecord;
+import org.teiid.translator.TranslatorException;
+
+public class JPQLUpdateQueryVisitor extends HierarchyVisitor {
+ protected ArrayList<TranslatorException> exceptions = new
ArrayList<TranslatorException>();
+ protected AtomicInteger aliasCounter = new AtomicInteger(0);
+ protected HashMap<String, String> correlatedName = new HashMap<String,
String>();
+
+ public JPQLUpdateQueryVisitor() {
+ super(false);
+ }
+
+ public static String getJPQLString(Command obj) throws TranslatorException {
+ JPQLUpdateQueryVisitor visitor = new JPQLUpdateQueryVisitor();
+
+ visitor.visitNode(obj);
+
+ if (!visitor.exceptions.isEmpty()) {
+ throw visitor.exceptions.get(0);
+ }
+
+ return visitor.convertToQuery(obj);
+ }
+
+ private String convertToQuery(Command obj) {
+ JPQLUpdateStringVisitor visitor = new JPQLUpdateStringVisitor(this);
+ visitor.visitNode(obj);
+ return visitor.toString();
+ }
+
+ @Override
+ public void visit(NamedTable obj) {
+ if (obj.getCorrelationName() == null) {
+ String aliasName = "ql_"+this.aliasCounter.getAndIncrement();
//$NON-NLS-1$
+ this.correlatedName.put(obj.getMetadataObject().getName(), aliasName);
+ obj.setCorrelationName(aliasName);
+ }
+ else {
+ this.correlatedName.put(obj.getMetadataObject().getName(),
obj.getCorrelationName());
+ }
+ }
+
+ static class JPQLUpdateStringVisitor extends SQLStringVisitor {
+ private JPQLUpdateQueryVisitor visitor;
+
+ public JPQLUpdateStringVisitor(JPQLUpdateQueryVisitor visitor) {
+ this.visitor = visitor;
+ }
+
+ @Override
+ public void visit(ColumnReference column) {
+ AbstractMetadataRecord record = column.getMetadataObject();
+ if (record != null) {
+ String name =
record.getProperty(JPAMetadataProcessor.KEY_ASSOSIATED_WITH_FOREIGN_TABLE, false);
+ if (name == null) {
+ buffer.append(this.visitor.correlatedName.get(column.getTable().getMetadataObject().getName())).append(Tokens.DOT).append(column.getMetadataObject().getName());
+ }
+ else {
+
buffer.append(this.visitor.correlatedName.get(name)).append(Tokens.DOT).append(column.getMetadataObject().getName());
+ }
+ }
+ else {
+ buffer.append(column.getName());
+ }
+ }
+ }
+}
Added: trunk/connectors/translator-jpa/src/main/resources/META-INF/MANIFEST.MF
===================================================================
--- trunk/connectors/translator-jpa/src/main/resources/META-INF/MANIFEST.MF
(rev 0)
+++ trunk/connectors/translator-jpa/src/main/resources/META-INF/MANIFEST.MF 2012-05-07
18:40:54 UTC (rev 4069)
@@ -0,0 +1 @@
+Dependencies: org.hibernate,org.jboss.teiid.translator.jdbc
Added:
trunk/connectors/translator-jpa/src/main/resources/META-INF/services/org.teiid.translator.ExecutionFactory
===================================================================
---
trunk/connectors/translator-jpa/src/main/resources/META-INF/services/org.teiid.translator.ExecutionFactory
(rev 0)
+++
trunk/connectors/translator-jpa/src/main/resources/META-INF/services/org.teiid.translator.ExecutionFactory 2012-05-07
18:40:54 UTC (rev 4069)
@@ -0,0 +1 @@
+org.teiid.translator.jpa.JPA2ExecutionFactory
\ No newline at end of file
Added:
trunk/connectors/translator-jpa/src/main/resources/org/teiid/translator/jpa/i18n.properties
===================================================================
---
trunk/connectors/translator-jpa/src/main/resources/org/teiid/translator/jpa/i18n.properties
(rev 0)
+++
trunk/connectors/translator-jpa/src/main/resources/org/teiid/translator/jpa/i18n.properties 2012-05-07
18:40:54 UTC (rev 4069)
@@ -0,0 +1,7 @@
+TEIID14001=PK on table {0} not found
+TEIID14002=Attribute can not be resolved:{0}
+TEIID14003=Embedded class has entity type based pk, not allowed on {0}
+TEIID14004=No parent table found for {0}
+TEIID14005=Bushy joins are not supported.
+TEIID14006=Unsupported join semantics, join can only be done where relationship exists
+TEIID14007=Columns.size and values.size are not the same
\ No newline at end of file
Added:
trunk/connectors/translator-jpa/src/test/java/org/teiid/translator/jpa/TestJSelectJPQLVisitor.java
===================================================================
---
trunk/connectors/translator-jpa/src/test/java/org/teiid/translator/jpa/TestJSelectJPQLVisitor.java
(rev 0)
+++
trunk/connectors/translator-jpa/src/test/java/org/teiid/translator/jpa/TestJSelectJPQLVisitor.java 2012-05-07
18:40:54 UTC (rev 4069)
@@ -0,0 +1,91 @@
+/*
+ * 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.jpa;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.teiid.cdk.api.TranslationUtility;
+import org.teiid.core.util.UnitTestUtil;
+import org.teiid.language.Select;
+import org.teiid.query.metadata.TransformationMetadata;
+import org.teiid.query.unittest.RealMetadataFactory;
+
+@SuppressWarnings("nls")
+public class TestJSelectJPQLVisitor {
+ private JPA2ExecutionFactory jpaTranslator;
+ private TranslationUtility utility;
+
+ @Before
+ public void setUp() throws Exception {
+ jpaTranslator = new JPA2ExecutionFactory();
+ jpaTranslator.start();
+
+ TransformationMetadata metadata =
RealMetadataFactory.fromDDL(UnitTestUtil.getTestDataFile("sakila.ddl"),
"sakila", "sakila");
+ utility = new TranslationUtility(metadata);
+
+ }
+
+ private void helpExecute(String query, String expected) throws Exception {
+ Select cmd = (Select)this.utility.parseCommand(query);
+ String jpaCommand = JPQLSelectVisitor.getJPQLString(cmd, jpaTranslator,
utility.createRuntimeMetadata());
+ assertEquals(expected, jpaCommand);
+ }
+
+ @Test
+ public void testProjectionBasedJoin() throws Exception {
+ helpExecute("select * from customer as c", "SELECT c.customer_id,
J_0.store_id, c.first_name, c.last_name, c.email, J_1.address_id, c.active, c.create_date,
c.last_update FROM customer AS c INNER JOIN c.store AS J_0 INNER JOIN c.address AS
J_1");
+ }
+
+ @Test
+ public void testExplicitJoinJoin() throws Exception {
+ helpExecute("select c.first_name, c.last_name, a.address_id FROM customer c
join address a on c.address_id=a.address_id",
+ "SELECT c.first_name, c.last_name, a.address_id FROM customer AS c INNER JOIN
c.address AS a");
+ }
+
+ @Test
+ public void testSimpleSelect() throws Exception {
+ helpExecute("select c.first_name, c.last_name FROM customer c order by
last_name",
+ "SELECT c.first_name, c.last_name FROM customer AS c ORDER BY
c.last_name");
+ }
+
+ @Test
+ public void testFunctionsSelect() throws Exception {
+ helpExecute("select concat(lcase(first_name), last_Name) from customer as
c",
+ "SELECT concat(lower(c.first_name), c.last_name) FROM customer AS c");
+ }
+
+ @Test
+ public void testRightJoinRewriteSelect() throws Exception {
+ helpExecute("select c.first_name, c.last_name, c.address_id, a.phone from
customer c right join address a on c.address_Id=a.address_Id",
+ "SELECT c.first_name, c.last_name, a.address_id, a.phone FROM customer AS c
RIGHT OUTER JOIN c.address AS a");
+ }
+
+ @Test
+ public void testRightandinnerJoinRewriteSelect() throws Exception {
+ helpExecute("select c.first_name, c.last_name, a.address_id, a.phone, ci.city
from customer c join address a on c.address_Id=a.address_Id right join city ci on
ci.city_id = a.city_id where c.last_Name='MYERS' OR c.last_Name='TALBERT'
order by c.first_Name",
+ "SELECT c.first_name, c.last_name, a.address_id, a.phone, ci.city FROM
customer AS c INNER JOIN c.address AS a RIGHT OUTER JOIN a.city AS ci WHERE c.last_name IN
('TALBERT', 'MYERS') ORDER BY c.first_name");
+ }
+
+ // needs one with composite PK
+}
Added: trunk/connectors/translator-jpa/src/test/resources/sakila.ddl
===================================================================
--- trunk/connectors/translator-jpa/src/test/resources/sakila.ddl
(rev 0)
+++ trunk/connectors/translator-jpa/src/test/resources/sakila.ddl 2012-05-07 18:40:54 UTC
(rev 4069)
@@ -0,0 +1,69 @@
+CREATE FOREIGN TABLE country (
+ country_id integer NOT NULL AUTO_INCREMENT,
+ country varchar(50) NOT NULL,
+ last_update timestamp NOT NULL
+ CONSTRAINT PRIMARY KEY (country_id)
+);
+
+CREATE FOREIGN TABLE city (
+ city_id integer NOT NULL AUTO_INCREMENT,
+ city varchar(50) NOT NULL,
+ country_id integer NOT NULL OPTIONS (assosiated_with_table 'sakila.country'),
+ last_update timestamp NOT NULL
+ CONSTRAINT PRIMARY KEY (city_id),
+ FOREIGN KEY (country_id) REFERENCES country (country_id) OPTIONS(NAMEINSOURCE
'country')
+);
+
+CREATE FOREIGN TABLE address (
+ address_id integer NOT NULL AUTO_INCREMENT,
+ address varchar(50) NOT NULL,
+ address2 varchar(50),
+ district varchar(20) NOT NULL,
+ city_id integer NOT NULL OPTIONS (assosiated_with_table 'sakila.city'),
+ postal_code varchar(10),
+ phone varchar(20) NOT NULL,
+ last_update timestamp NOT NULL
+ CONSTRAINT PRIMARY KEY (address_id),
+ FOREIGN KEY (city_id) REFERENCES city (city_id) OPTIONS(NAMEINSOURCE 'city')
+);
+
+CREATE FOREIGN TABLE staff (
+ staff_id byte NOT NULL AUTO_INCREMENT,
+ first_name varchar(45) NOT NULL,
+ last_name varchar(45) NOT NULL,
+ address_id integer NOT NULL OPTIONS (assosiated_with_table 'sakila.address'),
+ email varchar(50),
+ store_id byte NOT NULL OPTIONS (assosiated_with_table 'sakila.store'),
+ active boolean NOT NULL,
+ username varchar(16) NOT NULL,
+ password varchar(40),
+ last_update timestamp
+ CONSTRAINT PRIMARY KEY (staff_id),
+ FOREIGN KEY (store_id) REFERENCES store (store_id) OPTIONS(NAMEINSOURCE
'store'),
+ FOREIGN KEY (address_id) REFERENCES address (address_id) OPTIONS(NAMEINSOURCE
'address')
+);
+
+CREATE FOREIGN TABLE store (
+ store_id byte NOT NULL AUTO_INCREMENT,
+ manager_staff_id byte NOT NULL OPTIONS (assosiated_with_table 'sakila.staff'),
+ address_id integer NOT NULL OPTIONS (assosiated_with_table 'sakila.store'),
+ last_update timestamp NOT NULL
+ CONSTRAINT PRIMARY KEY (store_id),
+ FOREIGN KEY (manager_staff_id) REFERENCES staff (staff_id) OPTIONS(NAMEINSOURCE
'staff'),
+ FOREIGN KEY (address_id) REFERENCES address (address_id) OPTIONS(NAMEINSOURCE
'address')
+);
+
+CREATE FOREIGN TABLE customer (
+ customer_id integer NOT NULL AUTO_INCREMENT,
+ store_id byte NOT NULL OPTIONS (assosiated_with_table 'sakila.store'),
+ first_name varchar(45) NOT NULL,
+ last_name varchar(45) NOT NULL,
+ email varchar(50),
+ address_id integer NOT NULL OPTIONS (assosiated_with_table 'sakila.address'),
+ active boolean NOT NULL,
+ create_date timestamp NOT NULL,
+ last_update timestamp
+ constraint PRIMARY KEY (customer_id),
+ FOREIGN KEY (address_id) REFERENCES address (address_id) OPTIONS(NAMEINSOURCE
'address'),
+ FOREIGN KEY (store_id) REFERENCES store (store_id) OPTIONS(NAMEINSOURCE
'store')
+);
\ No newline at end of file
Added: trunk/connectors/translator-jpa/target/classes/META-INF/MANIFEST.MF
===================================================================
--- trunk/connectors/translator-jpa/target/classes/META-INF/MANIFEST.MF
(rev 0)
+++ trunk/connectors/translator-jpa/target/classes/META-INF/MANIFEST.MF 2012-05-07
18:40:54 UTC (rev 4069)
@@ -0,0 +1 @@
+Dependencies: org.hibernate,org.jboss.teiid.translator.jdbc
Property changes on: trunk/connectors/translator-jpa/target/classes/META-INF/MANIFEST.MF
___________________________________________________________________
Added: svn:mime-type
+ text/plain