| /* |
| * 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>"; |
| } |