blob: ac262ed500a2d1153d93f09818574561fb85e8d0 [file] [log] [blame]
/*
* Copyright (c) 2011, 2020 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0,
* or the Eclipse Distribution License v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
// Contributors:
// David McCann - July 2013 - Initial Implementation
package org.eclipse.persistence.tools.metadata.generation.test.typerowtype;
import static org.eclipse.persistence.tools.metadata.generation.test.AllTests.DATABASE_DDL_CREATE_KEY;
import static org.eclipse.persistence.tools.metadata.generation.test.AllTests.DATABASE_DDL_DEBUG_KEY;
import static org.eclipse.persistence.tools.metadata.generation.test.AllTests.DATABASE_DDL_DROP_KEY;
import static org.eclipse.persistence.tools.metadata.generation.test.AllTests.DATABASE_USERNAME_KEY;
import static org.eclipse.persistence.tools.metadata.generation.test.AllTests.DEFAULT_DATABASE_DDL_CREATE;
import static org.eclipse.persistence.tools.metadata.generation.test.AllTests.DEFAULT_DATABASE_DDL_DEBUG;
import static org.eclipse.persistence.tools.metadata.generation.test.AllTests.DEFAULT_DATABASE_DDL_DROP;
import static org.eclipse.persistence.tools.metadata.generation.test.AllTests.DEFAULT_DATABASE_USERNAME;
import static org.eclipse.persistence.tools.metadata.generation.test.AllTests.DEFAULT_PACKAGE_NAME;
import static org.eclipse.persistence.tools.metadata.generation.test.AllTests.comparer;
import static org.eclipse.persistence.tools.metadata.generation.test.AllTests.conn;
import static org.eclipse.persistence.tools.metadata.generation.test.AllTests.databasePlatform;
import static org.eclipse.persistence.tools.metadata.generation.test.AllTests.documentToString;
import static org.eclipse.persistence.tools.metadata.generation.test.AllTests.removeEmptyTextNodes;
import static org.eclipse.persistence.tools.metadata.generation.test.AllTests.runDdl;
import static org.eclipse.persistence.tools.metadata.generation.test.AllTests.xmlParser;
//javase imports
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.ByteArrayOutputStream;
import java.io.StringReader;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.persistence.internal.jpa.metadata.xml.XMLEntityMappings;
import org.eclipse.persistence.internal.jpa.metadata.xml.XMLEntityMappingsWriter;
import org.eclipse.persistence.tools.metadata.generation.JPAMetadataGenerator;
import org.eclipse.persistence.tools.metadata.generation.test.AllTests;
import org.eclipse.persistence.tools.oracleddl.metadata.CompositeDatabaseType;
import org.eclipse.persistence.tools.oracleddl.metadata.PLSQLPackageType;
import org.eclipse.persistence.tools.oracleddl.metadata.ProcedureType;
import org.eclipse.persistence.tools.oracleddl.metadata.TableType;
import org.eclipse.persistence.tools.oracleddl.parser.ParseException;
import org.eclipse.persistence.tools.oracleddl.util.DatabaseTypeBuilder;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.w3c.dom.Document;
/**
* Tests metadata generation involving %TYPE and %ROWTYPE.
*/
public class TypeRowTypeTestSuite {
static final String CREATE_EMPTYPE_TABLE =
"CREATE TABLE EMPTYPEX (" +
"\nEMPNO NUMERIC(4) NOT NULL," +
"\nENAME VARCHAR(25)," +
"\nPRIMARY KEY (EMPNO)" +
"\n)";
static final String CREATE_EMP_RECORD_PACKAGE =
"create or replace PACKAGE EMP_RECORD_PACKAGE AS\n" +
"type EmpRec is record (" +
"emp_id EMPTYPEX.EMPNO%TYPE,\n" +
"emp_name EMPTYPEX.ENAME%TYPE\n" +
");\n" +
"function get_emp_record (pId in number) return EmpRec;\n" +
"END EMP_RECORD_PACKAGE;";
static final String CREATE_ROWTYPE_TEST_PACKAGE =
"CREATE OR REPLACE PACKAGE RTYPE_PKG AS" +
"\nPROCEDURE testProc(PARAM1 IN INTEGER, PARAM2 OUT EMPTYPEX%ROWTYPE);" +
"\nFUNCTION testFunc(PARAM1 IN INTEGER) RETURN EMPTYPEX%ROWTYPE;" +
"\nEND RTYPE_PKG;";
// shadow JDBC type for PL/SQL record
static final String CREATE_EMPREC_TYPE =
"CREATE OR REPLACE TYPE EMP_RECORD_PACKAGE_EmpRec AS OBJECT(EMP_ID NUMERIC(4), EMP_NAME VARCHAR2(25));";
static final String DROP_EMPTYPE_TABLE = "DROP TABLE EMPTYPEX";
static final String DROP_EMP_RECORD_PACKAGE = "DROP PACKAGE EMP_RECORD_PACKAGE";
static final String DROP_EMPREC_TYPE = "DROP TYPE EMP_RECORD_PACKAGE_EMPREC FORCE";
static final String DROP_RTYPE_PKG = "DROP PACKAGE RTYPE_PKG";
static boolean ddlCreate = false;
static boolean ddlDrop = false;
static boolean ddlDebug = false;
static List<CompositeDatabaseType> dbTypes;
static DatabaseTypeBuilder dbTypeBuilder;
@SuppressWarnings({ "unchecked", "rawtypes" })
@BeforeClass
public static void setUp() throws ClassNotFoundException, SQLException {
AllTests.setUp();
String ddlCreateProp = System.getProperty(DATABASE_DDL_CREATE_KEY, DEFAULT_DATABASE_DDL_CREATE);
if ("true".equalsIgnoreCase(ddlCreateProp)) {
ddlCreate = true;
}
String ddlDropProp = System.getProperty(DATABASE_DDL_DROP_KEY, DEFAULT_DATABASE_DDL_DROP);
if ("true".equalsIgnoreCase(ddlDropProp)) {
ddlDrop = true;
}
String ddlDebugProp = System.getProperty(DATABASE_DDL_DEBUG_KEY, DEFAULT_DATABASE_DDL_DEBUG);
if ("true".equalsIgnoreCase(ddlDebugProp)) {
ddlDebug = true;
}
if (ddlCreate) {
runDdl(conn, CREATE_EMPTYPE_TABLE, ddlDebug);
runDdl(conn, CREATE_EMPREC_TYPE, ddlDebug);
runDdl(conn, CREATE_EMP_RECORD_PACKAGE, ddlDebug);
runDdl(conn, CREATE_ROWTYPE_TEST_PACKAGE, ddlDebug);
}
String schema = System.getProperty(DATABASE_USERNAME_KEY, DEFAULT_DATABASE_USERNAME);
List<String> procedurePatterns = new ArrayList<String>();
procedurePatterns.add("get_emp_record");
procedurePatterns.add("testProc");
procedurePatterns.add("testFunc");
// use DatabaseTypeBuilder to generate a lists of TableTypes and PackageTypes
dbTypeBuilder = new DatabaseTypeBuilder();
try {
// process the table
List<TableType> dbTables = dbTypeBuilder.buildTables(conn, schema, "EMPTYPEX");
// process the "EMP_RECORD_PACKAGE" package
List<ProcedureType> empRecPkgProcedures = new ArrayList<ProcedureType>();
List<PLSQLPackageType> packages = dbTypeBuilder.buildPackages(conn, schema, "EMP_RECORD_PACKAGE");
for (PLSQLPackageType pkgType : packages) {
// now get the desired procedures/functions from the processed package
for (ProcedureType procType : pkgType.getProcedures()) {
if (procedurePatterns.contains(procType.getProcedureName())) {
empRecPkgProcedures.add(procType);
}
}
}
// process the "RTYPE_PKG" package
List<ProcedureType> rtypePkgProcedures = new ArrayList<ProcedureType>();
packages = dbTypeBuilder.buildPackages(conn, schema, "RTYPE_PKG");
for (PLSQLPackageType pkgType : packages) {
// now get the desired procedures/functions from the processed package
for (ProcedureType procType : pkgType.getProcedures()) {
if (procedurePatterns.contains(procType.getProcedureName())) {
rtypePkgProcedures.add(procType);
}
}
}
// combine tables and procedures to pass to the metadata generator
dbTypes = new ArrayList();
dbTypes.addAll(dbTables);
dbTypes.addAll(empRecPkgProcedures);
dbTypes.addAll(rtypePkgProcedures);
} catch (ParseException e) {
e.printStackTrace();
fail("An unexpected exception occurred: " + e.getMessage());
}
}
@AfterClass
public static void tearDown() {
if (ddlDrop) {
runDdl(conn, DROP_EMP_RECORD_PACKAGE, ddlDebug);
runDdl(conn, DROP_EMPREC_TYPE, ddlDebug);
runDdl(conn, DROP_EMPTYPE_TABLE, ddlDebug);
runDdl(conn, DROP_RTYPE_PKG, ddlDebug);
}
}
@Test
public void testJPARowTypeMetadata() {
if (dbTypes == null || dbTypes.isEmpty()) {
fail("No types were generated.");
}
XMLEntityMappings mappings = null;
try {
JPAMetadataGenerator gen = new JPAMetadataGenerator(DEFAULT_PACKAGE_NAME, databasePlatform);
mappings = gen.generateXmlEntityMappings(dbTypes);
} catch (Exception x) {
x.printStackTrace();
fail("An unexpected exception occurred: " + x.getMessage());
}
if (mappings == null) {
fail("No JPA metadata was generated");
}
ByteArrayOutputStream metadata = new ByteArrayOutputStream();
XMLEntityMappingsWriter.write(mappings, metadata);
Document testDoc = xmlParser.parse(new StringReader(metadata.toString()));
removeEmptyTextNodes(testDoc);
Document controlDoc = xmlParser.parse(new StringReader(mappingMetadata));
removeEmptyTextNodes(controlDoc);
assertTrue("Metadata comparison failed. Expected:\n" + documentToString(controlDoc) + "\nActual\n" + documentToString(testDoc), comparer.isNodeEqual(controlDoc, testDoc));
}
static final String mappingMetadata =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<orm:entity-mappings xsi:schemaLocation=\"http://www.eclipse.org/eclipselink/xsds/persistence/orm org/eclipse/persistence/jpa/eclipselink_orm_2_5.xsd\"" +
" xmlns:orm=\"http://www.eclipse.org/eclipselink/xsds/persistence/orm\" " +
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n" +
" <orm:named-plsql-stored-procedure-query name=\"testProc\" procedure-name=\"RTYPE_PKG.testProc\">\n" +
" <orm:parameter direction=\"IN\" name=\"PARAM1\" database-type=\"INTEGER_TYPE\"/>\n" +
" <orm:parameter direction=\"OUT\" name=\"PARAM2\" database-type=\"EMPTYPEX%ROWTYPE\"/>\n" +
" </orm:named-plsql-stored-procedure-query>\n" +
" <orm:named-plsql-stored-function-query name=\"get_emp_record\" function-name=\"EMP_RECORD_PACKAGE.get_emp_record\">\n" +
" <orm:parameter direction=\"IN\" name=\"pId\" database-type=\"NUMERIC_TYPE\"/>\n" +
" <orm:return-parameter name=\"RESULT\" database-type=\"EMP_RECORD_PACKAGE.EmpRec\"/>\n" +
" </orm:named-plsql-stored-function-query>\n" +
" <orm:named-plsql-stored-function-query name=\"testFunc\" function-name=\"RTYPE_PKG.testFunc\">\n" +
" <orm:parameter direction=\"IN\" name=\"PARAM1\" database-type=\"INTEGER_TYPE\"/>\n" +
" <orm:return-parameter name=\"RESULT\" database-type=\"EMPTYPEX%ROWTYPE\"/>\n" +
" </orm:named-plsql-stored-function-query>\n" +
" <orm:plsql-record name=\"EMP_RECORD_PACKAGE.EmpRec\" compatible-type=\"EMP_RECORD_PACKAGE_EmpRec\" java-type=\"emp_record_package.Emprec\">\n" +
" <orm:field name=\"emp_id\" database-type=\"NUMERIC_TYPE\"/>\n" +
" <orm:field name=\"emp_name\" database-type=\"VARCHAR_TYPE\"/>\n" +
" </orm:plsql-record>\n" +
" <orm:plsql-record name=\"EMPTYPEX%ROWTYPE\" compatible-type=\"EMPTYPEX_ROWTYPE\" java-type=\"Emptypex_rowtype\">\n" +
" <orm:field name=\"EMPNO\" database-type=\"NUMERIC_TYPE\"/>\n" +
" <orm:field name=\"ENAME\" database-type=\"VARCHAR_TYPE\"/>\n" +
" </orm:plsql-record>\n" +
" <orm:entity class=\"metadatagen.Emptypex\" access=\"VIRTUAL\">\n" +
" <orm:table name=\"EMPTYPEX\"/>\n" +
" <orm:attributes>\n" +
" <orm:id name=\"empno\" attribute-type=\"java.math.BigInteger\">\n" +
" <orm:column name=\"EMPNO\"/>\n" +
" </orm:id>\n" +
" <orm:basic name=\"ename\" attribute-type=\"java.lang.String\">\n" +
" <orm:column name=\"ENAME\"/>\n" +
" </orm:basic>\n" +
" </orm:attributes>\n" +
" </orm:entity>\n" +
" <orm:embeddable class=\"emp_record_package.Emprec\" access=\"VIRTUAL\">\n" +
" <orm:struct name=\"EMP_RECORD_PACKAGE_EmpRec\">\n" +
" <orm:field>emp_id</orm:field>\n" +
" <orm:field>emp_name</orm:field>\n" +
" </orm:struct>\n" +
" <orm:attributes>\n" +
" <orm:basic name=\"emp_id\" attribute-type=\"java.math.BigInteger\">\n" +
" <orm:column name=\"emp_id\"/>\n" +
" </orm:basic>\n" +
" <orm:basic name=\"emp_name\" attribute-type=\"java.lang.String\">\n" +
" <orm:column name=\"emp_name\"/>\n" +
" </orm:basic>\n" +
" </orm:attributes>\n" +
" </orm:embeddable>\n" +
" <orm:embeddable class=\"Emptypex_rowtype\" access=\"VIRTUAL\">\n" +
" <orm:struct name=\"EMPTYPEX_ROWTYPE\">\n" +
" <orm:field>EMPNO</orm:field>\n" +
" <orm:field>ENAME</orm:field>\n" +
" </orm:struct>\n" +
" <orm:attributes>\n" +
" <orm:basic name=\"empno\" attribute-type=\"java.math.BigInteger\">\n" +
" <orm:column name=\"EMPNO\"/>\n" +
" </orm:basic>\n" +
" <orm:basic name=\"ename\" attribute-type=\"java.lang.String\">\n" +
" <orm:column name=\"ENAME\"/>\n" +
" </orm:basic>\n" +
" </orm:attributes>\n" +
" </orm:embeddable>\n" +
"</orm:entity-mappings>";
}