Second commit for Bug 383011 - DBWS: Should support cross-package type references
diff --git a/oracleddlparser/src/main/java/org/eclipse/persistence/tools/oracleddl/util/DatabaseTypeBuilder.java b/oracleddlparser/src/main/java/org/eclipse/persistence/tools/oracleddl/util/DatabaseTypeBuilder.java
index bdb15f0..d101801 100644
--- a/oracleddlparser/src/main/java/org/eclipse/persistence/tools/oracleddl/util/DatabaseTypeBuilder.java
+++ b/oracleddlparser/src/main/java/org/eclipse/persistence/tools/oracleddl/util/DatabaseTypeBuilder.java
@@ -38,8 +38,10 @@
import org.eclipse.persistence.tools.oracleddl.metadata.FunctionType;
import org.eclipse.persistence.tools.oracleddl.metadata.ObjectTableType;
import org.eclipse.persistence.tools.oracleddl.metadata.ObjectType;
+import org.eclipse.persistence.tools.oracleddl.metadata.PLSQLCursorType;
import org.eclipse.persistence.tools.oracleddl.metadata.PLSQLPackageType;
import org.eclipse.persistence.tools.oracleddl.metadata.PLSQLRecordType;
+import org.eclipse.persistence.tools.oracleddl.metadata.PLSQLType;
import org.eclipse.persistence.tools.oracleddl.metadata.ProcedureType;
import org.eclipse.persistence.tools.oracleddl.metadata.ROWTYPEType;
import org.eclipse.persistence.tools.oracleddl.metadata.TYPEType;
@@ -99,7 +101,7 @@
", '" + OBJECT_TYPE_TABLE + "', " + OBJECT_TYPE_TABLE_CODE +
", '" + OBJECT_TYPE_TYPE + "', " + OBJECT_TYPE_TYPE_CODE +
"," + OBJECT_TYPE_UNKNOWN_CODE + ") AS OBJECT_TYPE FROM ALL_OBJECTS AO WHERE " +
- "(STATUS = 'VALID' AND OWNER LIKE ? AND OBJECT_NAME = ?)";
+ "(STATUS = 'VALID' AND OWNER LIKE ? AND OBJECT_NAME = ?)";
static DBMSMetadataSessionTransforms TRANSFORMS_FACTORY;
static {
@@ -212,8 +214,8 @@
UnresolvedTypesVisitor unresolvedTypesVisitor = new UnresolvedTypesVisitor();
unresolvedTypesVisitor.visit(packageType);
if (!unresolvedTypesVisitor.getUnresolvedTypes().isEmpty()) {
- resolvedTypes(conn, packageType.getSchema(), parser,
- unresolvedTypesVisitor.getUnresolvedTypes(), packageType);
+ resolvedTypes(conn, packageType.getSchema(), parser,
+ unresolvedTypesVisitor.getUnresolvedTypes(), packageType, packageTypes);
}
}
}
@@ -498,23 +500,35 @@
return ddls;
}
+ /**
+ * Attempt to resolve any types that the DDLParser could not resolve.
+ *
+ */
+ protected void resolvedTypes(Connection conn, String schemaPattern, DDLParser parser, List<UnresolvedType> unresolvedTypes, DatabaseType databaseType) throws ParseException {
+ resolvedTypes(conn, schemaPattern, parser, unresolvedTypes, databaseType, null);
+ }
+
+ /**
+ * Attempt to resolve any types that the DDLParser could not resolve.
+ *
+ */
protected void resolvedTypes(Connection conn, String schemaPattern, DDLParser parser,
- List<UnresolvedType> unresolvedTypes, DatabaseType databaseType) throws ParseException {
+ List<UnresolvedType> unresolvedTypes, DatabaseType databaseType, List<PLSQLPackageType> processedPackages) throws ParseException {
// need to process non '%' named items 1st such that we can resolve the '%' ones later
- List<String> percentNameList = new ArrayList<String>();
- List<String> nonPercentNameList = new ArrayList<String>();
+ List<String> percentNameList = new ArrayList<String>();
+ List<String> nonPercentNameList = new ArrayList<String>();
for (UnresolvedType uType : unresolvedTypes) {
CompositeDatabaseType owningType = uType.getOwningType();
- if (owningType != null && (owningType.isTYPEType() || owningType.isROWTYPEType())) {
- if (!percentNameList.contains(uType.getTypeName())) {
- percentNameList.add(uType.getTypeName());
- }
- } else {
- if (!nonPercentNameList.contains(uType.getTypeName())) {
- nonPercentNameList.add(uType.getTypeName());
- }
- }
+ if (owningType != null && (owningType.isTYPEType() || owningType.isROWTYPEType())) {
+ if (!percentNameList.contains(uType.getTypeName())) {
+ percentNameList.add(uType.getTypeName());
+ }
+ } else {
+ if (!nonPercentNameList.contains(uType.getTypeName())) {
+ nonPercentNameList.add(uType.getTypeName());
+ }
+ }
}
// sort so dotted entries are last
Collections.sort(percentNameList);
@@ -523,22 +537,22 @@
Collections.reverse(percentNameList);
Collections.reverse(nonPercentNameList);
// iterate over the collections and add unresolved types based on type name
- List<UnresolvedType> percentList = new ArrayList<UnresolvedType>();
+ List<UnresolvedType> percentList = new ArrayList<UnresolvedType>();
for (String tname : percentNameList) {
for (UnresolvedType uType : unresolvedTypes) {
- if (uType.getTypeName().equals(tname)) {
- percentList.add(uType);
- break;
- }
+ if (uType.getTypeName().equals(tname)) {
+ percentList.add(uType);
+ break;
+ }
}
}
- List<UnresolvedType> nonPercentList = new ArrayList<UnresolvedType>();
+ List<UnresolvedType> nonPercentList = new ArrayList<UnresolvedType>();
for (String tname : nonPercentNameList) {
for (UnresolvedType uType : unresolvedTypes) {
- if (uType.getTypeName().equals(tname)) {
- nonPercentList.add(uType);
- break;
- }
+ if (uType.getTypeName().equals(tname)) {
+ nonPercentList.add(uType);
+ break;
+ }
}
}
Stack<UnresolvedType> stac = new Stack<UnresolvedType>();
@@ -547,12 +561,12 @@
if (!stac.contains(uPercentType)) {
stac.push(uPercentType);
}
- }
- for (UnresolvedType uNonPercentType : nonPercentList) {
+ }
+ for (UnresolvedType uNonPercentType : nonPercentList) {
if (!stac.contains(uNonPercentType)) {
stac.push(uNonPercentType);
}
- }
+ }
boolean done = false;
DatabaseTypesRepository typesRepository = parser.getTypesRepository();
@@ -564,131 +578,147 @@
int dotIdx = typeName.indexOf('.');
String typeName1 = typeName;
String typeName2 = null;
+ // handle dotted scenario, i.e. "PackageName.TypeName" or "SchemaName.TypeName"
if (dotIdx != -1) {
typeName1 = typeName.substring(0, dotIdx);
typeName2 = typeName.substring(dotIdx+1, typeName.length());
}
// check type repository first
- resolvedType = (CompositeDatabaseType)typesRepository.getDatabaseType(typeName);
- if (resolvedType == null) {
- if (owningType.isROWTYPEType()) {
- ROWTYPEType rType = (ROWTYPEType)owningType;
- String tableName = rType.getTypeName();
- if (tableName.contains(ROWTYPE_MACRO)) {
- int idx = tableName.indexOf(ROWTYPE_MACRO);
- tableName = tableName.substring(0,idx);
- }
- resolvedType = (CompositeDatabaseType)typesRepository.getDatabaseType(tableName);
- if (resolvedType == null) {
- TableType tableType = null;
- List<TableType> tables = buildTables(conn, schemaPattern, tableName, false);
- if (tables != null && tables.size() > 0) {
- tableType = tables.get(0);
- typesRepository.setDatabaseType(tableType.getTableName(), tableType);
- rType.setEnclosedType(tableType);
- typesRepository.setDatabaseType(rType.getTypeName(), rType);
- }
+ resolvedType = (CompositeDatabaseType)typesRepository.getDatabaseType(typeName);
+ if (resolvedType == null) {
+ if (owningType.isROWTYPEType()) {
+ ROWTYPEType rType = (ROWTYPEType)owningType;
+ String tableName = rType.getTypeName();
+ if (tableName.contains(ROWTYPE_MACRO)) {
+ int idx = tableName.indexOf(ROWTYPE_MACRO);
+ tableName = tableName.substring(0,idx);
+ }
+ resolvedType = (CompositeDatabaseType)typesRepository.getDatabaseType(tableName);
+ if (resolvedType == null) {
+ TableType tableType = null;
+ List<TableType> tables = buildTables(conn, schemaPattern, tableName, false);
+ if (tables != null && tables.size() > 0) {
+ tableType = tables.get(0);
+ typesRepository.setDatabaseType(tableType.getTableName(), tableType);
+ rType.setEnclosedType(tableType);
+ typesRepository.setDatabaseType(rType.getTypeName(), rType);
+ }
resolvedType = tableType;
- // always a chance that tableType has some unresolved column type
- if (tableType != null && !tableType.isResolved()) {
- UnresolvedTypesVisitor unresolvedTypesVisitor = new UnresolvedTypesVisitor();
- unresolvedTypesVisitor.visit(tableType);
- for (UnresolvedType u2Type : unresolvedTypesVisitor.getUnresolvedTypes()) {
- if (!stac.contains(u2Type)) {
- stac.push(u2Type);
- }
- }
- }
- else {
- //TODO - table is in a different schema?
- }
- }
- else {
- uType.getOwningType().setEnclosedType(resolvedType);
- }
- }
- else if (owningType.isTYPEType()) {
- TYPEType tType = (TYPEType)owningType;
- DatabaseType foundType = findField(typeName1, databaseType);
- if (foundType != null) {
- if (typeName2 != null) {
- foundType = findField(typeName2, foundType);
- }
- if (foundType != null) {
- tType.setEnclosedType(foundType);
- //TODO - figure out TYPEType's that go 'into' a local variable
- resolvedType = (CompositeDatabaseType)foundType;
- }
- }
- }
- if (resolvedType == null) {
- int objectTypeCode = getObjectType(conn, schemaPattern, typeName1);
- switch (objectTypeCode) {
- case OBJECT_TYPE_FUNCTION_CODE :
- List<FunctionType> functions = buildFunctions(conn, schemaPattern,
- typeName1, false);
- if (functions != null && functions.size() > 0) {
- resolvedType = functions.get(0); // only care about first one
- }
- break;
- case OBJECT_TYPE_PACKAGE_CODE :
- List<PLSQLPackageType> packages = buildPackages(conn, schemaPattern,
- typeName1, false);
- if (packages != null && packages.size() > 0) {
- resolvedType = packages.get(0); // only care about first one
- }
- break;
- case OBJECT_TYPE_PROCEDURE_CODE :
- List<ProcedureType> procedures = buildProcedures(conn, schemaPattern,
- typeName1, false);
- if (procedures != null && procedures.size() > 0) {
- resolvedType = procedures.get(0); // only care about first one
- }
- break;
- case OBJECT_TYPE_TABLE_CODE :
- List<TableType> tables = buildTables(conn, schemaPattern,
- typeName1, false);
- if (tables != null && tables.size() > 0) {
- TableType tableType = tables.get(0); // only care about first one
- resolvedType = tableType;
- if (typeName2 != null) {
- DatabaseType foundType = findField(typeName2, resolvedType);
- if (foundType != null) {
- resolvedType = (CompositeDatabaseType)foundType;
- }
- }
- // always a chance that tableType has some unresolved column type
- if (!tableType.isResolved()) {
- UnresolvedTypesVisitor unresolvedTypesVisitor = new UnresolvedTypesVisitor();
- unresolvedTypesVisitor.visit(tableType);
- for (UnresolvedType u2Type : unresolvedTypesVisitor.getUnresolvedTypes()) {
- if (!stac.contains(u2Type)) {
- stac.push(u2Type);
- }
- }
- }
- }
- break;
- case OBJECT_TYPE_TYPE_CODE :
- List<CompositeDatabaseType> types = buildTypes(conn, schemaPattern,
- typeName1, false);
- if (types != null && types.size() > 0) {
- resolvedType = types.get(0); // only care about first one
- if (typeName2 != null) {
- DatabaseType foundType = findField(typeName2, resolvedType);
- if (foundType != null) {
- resolvedType = (CompositeDatabaseType)foundType;
- }
- }
- }
- break;
- case OBJECT_TYPE_UNKNOWN_CODE :
- default :
- break;
- }
- }
- }
+ // always a chance that tableType has some unresolved column type
+ if (tableType != null && !tableType.isResolved()) {
+ UnresolvedTypesVisitor unresolvedTypesVisitor = new UnresolvedTypesVisitor();
+ unresolvedTypesVisitor.visit(tableType);
+ for (UnresolvedType u2Type : unresolvedTypesVisitor.getUnresolvedTypes()) {
+ if (!stac.contains(u2Type)) {
+ stac.push(u2Type);
+ }
+ }
+ } else {
+ // may be dealing with a table from a different schema
+ }
+ } else {
+ uType.getOwningType().setEnclosedType(resolvedType);
+ }
+ } else if (owningType.isTYPEType()) {
+ TYPEType tType = (TYPEType)owningType;
+ DatabaseType foundType = findField(typeName1, databaseType);
+ if (foundType != null) {
+ if (typeName2 != null) {
+ foundType = findField(typeName2, foundType);
+ }
+ if (foundType != null) {
+ tType.setEnclosedType(foundType);
+ // may need to handle TYPEType's that go 'into' a local variable
+ resolvedType = (CompositeDatabaseType)foundType;
+ }
+ }
+ }
+ if (resolvedType == null) {
+ int objectTypeCode = getObjectType(conn, schemaPattern, typeName1);
+ switch (objectTypeCode) {
+ case OBJECT_TYPE_FUNCTION_CODE :
+ List<FunctionType> functions = buildFunctions(conn, schemaPattern, typeName1, false);
+ if (functions != null && functions.size() > 0) {
+ resolvedType = functions.get(0); // only care about first one
+ }
+ break;
+ case OBJECT_TYPE_PACKAGE_CODE :
+ PLSQLPackageType plsqlPkg = null;
+ // we may have already processed this package
+ if (processedPackages != null) {
+ for (PLSQLPackageType pkg : processedPackages) {
+ if (pkg.getPackageName().equals(typeName1)) {
+ plsqlPkg = pkg;
+ }
+ }
+ }
+ if (plsqlPkg == null) {
+ List<PLSQLPackageType> packages = buildPackages(conn, schemaPattern, typeName1, false);
+ if (packages != null && packages.size() > 0) {
+ plsqlPkg = packages.get(0); // only care about first one
+ processedPackages.add(plsqlPkg);
+ }
+ }
+ if (plsqlPkg != null) {
+ // we may have a dotted scenario, i.e. 'PackageName.TypeName'
+ if (typeName2 == null) {
+ resolvedType = plsqlPkg;
+ } else {
+ DatabaseType dbType = findField(typeName2, plsqlPkg);
+ if (dbType != null && dbType.isComposite()) {
+ resolvedType = (CompositeDatabaseType) dbType;
+ }
+ }
+ }
+ break;
+ case OBJECT_TYPE_PROCEDURE_CODE :
+ List<ProcedureType> procedures = buildProcedures(conn, schemaPattern, typeName1, false);
+ if (procedures != null && procedures.size() > 0) {
+ resolvedType = procedures.get(0); // only care about first one
+ }
+ break;
+ case OBJECT_TYPE_TABLE_CODE :
+ List<TableType> tables = buildTables(conn, schemaPattern, typeName1, false);
+ if (tables != null && tables.size() > 0) {
+ TableType tableType = tables.get(0); // only care about first one
+ resolvedType = tableType;
+ if (typeName2 != null) {
+ DatabaseType foundType = findField(typeName2, resolvedType);
+ if (foundType != null) {
+ resolvedType = (CompositeDatabaseType)foundType;
+ }
+ }
+ // always a chance that tableType has some unresolved column type
+ if (!tableType.isResolved()) {
+ UnresolvedTypesVisitor unresolvedTypesVisitor = new UnresolvedTypesVisitor();
+ unresolvedTypesVisitor.visit(tableType);
+ for (UnresolvedType u2Type : unresolvedTypesVisitor.getUnresolvedTypes()) {
+ if (!stac.contains(u2Type)) {
+ stac.push(u2Type);
+ }
+ }
+ }
+ }
+ break;
+ case OBJECT_TYPE_TYPE_CODE :
+ List<CompositeDatabaseType> types = buildTypes(conn, schemaPattern, typeName1, false);
+ if (types != null && types.size() > 0) {
+ resolvedType = types.get(0); // only care about first one
+ if (typeName2 != null) {
+ DatabaseType foundType = findField(typeName2, resolvedType);
+ if (foundType != null) {
+ resolvedType = (CompositeDatabaseType)foundType;
+ }
+ }
+ }
+ break;
+ case OBJECT_TYPE_UNKNOWN_CODE :
+ default :
+ break;
+ }
+ }
+ }
if (resolvedType != null) {
if (owningType.isPLSQLRecordType() && !(resolvedType.isFieldType())) {
PLSQLRecordType recordType = (PLSQLRecordType)owningType;
@@ -700,19 +730,18 @@
}
}
}
- }
- else {
+ } else {
owningType.setEnclosedType(resolvedType);
}
typesRepository.setDatabaseType(resolvedType.getTypeName(), resolvedType);
// update any other types in the unresolved list that reference the resolved type
for (UnresolvedType unresolvedType : unresolvedTypes) {
- if (unresolvedType.getTypeName().equals(typeName)) {
- if (unresolvedType.getOwningType().getEnclosedType() instanceof UnresolvedType) {
- unresolvedType.getOwningType().setEnclosedType(resolvedType);
- }
- }
+ if (unresolvedType.getTypeName().equals(typeName)) {
+ if (unresolvedType.getOwningType().getEnclosedType() instanceof UnresolvedType) {
+ unresolvedType.getOwningType().setEnclosedType(resolvedType);
+ }
+ }
}
// always a chance that resolvedType refers to something that is un-resolved
@@ -725,7 +754,7 @@
}
}
}
- }
+ }
if (stac.isEmpty()) {
done = true;
@@ -733,6 +762,19 @@
}
}
+ /**
+ * Attempt to determine the database type (Function, Package, Table, etc.) for a
+ * given a Schema and Type name.
+ *
+ * Types are translated to integer values as follows:
+ * <ul>
+ * <li>FUNCTION = 1</li>
+ * <li>PACKAGE = 2</li>
+ * <li>PROCEDURE = 3</li>
+ * <li>TABLE = 4</li>
+ * <li>TYPE = 5</li>
+ * </ul>
+ */
protected int getObjectType(Connection conn, String schema, String typeName) {
int objectType = -1;
String schemaPattern = schema == null ? PERCENT : schema;
@@ -750,24 +792,21 @@
objectType = rs.getInt(ALL_OBJECTS_OBJECT_TYPE_FIELD);
}
}
- }
- catch (SQLException e) {
- e.printStackTrace();
+ } catch (SQLException e) {
+ // ignore
}
finally {
if (rs != null) {
try {
rs.close();
- }
- catch (SQLException e) {
+ } catch (SQLException e) {
// ignore
}
}
if (pStmt != null) {
try {
pStmt.close();
- }
- catch (SQLException e) {
+ } catch (SQLException e) {
// ignore
}
}
@@ -831,20 +870,22 @@
TOPLEVEL.equals(schemaPattern) || PERCENT.equals(schemaPattern));
}
+ /**
+ * Attempt to find a field matching 'fieldName' in a given DatabaseType.
+ *
+ */
static DatabaseType findField(String fieldName, DatabaseType targetType) {
// remove '%' from field name
int pctIdx = fieldName.indexOf(PERCENT);
if (pctIdx != -1) {
- fieldName = fieldName.substring(0, pctIdx);
+ fieldName = fieldName.substring(0, pctIdx);
}
- DatabaseType foundType = null;
if (targetType.isPLSQLRecordType()) {
PLSQLRecordType plsqlRecordType = (PLSQLRecordType)targetType;
for (FieldType fieldType : plsqlRecordType.getFields()) {
if (fieldType.getFieldName().equals(fieldName)) {
- foundType = fieldType;
- break;
+ return fieldType;
}
}
}
@@ -852,8 +893,7 @@
TableType tableType = (TableType)targetType;
for (FieldType columnType : tableType.getColumns()) {
if (columnType.getFieldName().equals(fieldName)) {
- foundType = columnType;
- break;
+ return columnType;
}
}
}
@@ -861,38 +901,55 @@
ObjectType objectType = (ObjectType)targetType;
for (FieldType fieldType : objectType.getFields()) {
if (fieldType.getFieldName().equals(fieldName)) {
- foundType = fieldType;
- break;
+ return fieldType;
}
}
}
else if (targetType instanceof PLSQLPackageType) {
- PLSQLPackageType packageType = (PLSQLPackageType) targetType;
- // check local variables
- for (FieldType fieldType : packageType.getLocalVariables()) {
- if (fieldType.getFieldName().equals(fieldName)) {
- foundType = fieldType;
- break;
+ PLSQLPackageType packageType = (PLSQLPackageType) targetType;
+ // check cursors
+ for (PLSQLCursorType cursorType : packageType.getCursors()) {
+ if (cursorType.getCursorName().equals(fieldName)) {
+ return cursorType;
}
- }
+
+ }
+ // check types
+ for (PLSQLType plsqlType : packageType.getTypes()) {
+ if (plsqlType.getTypeName().equals(fieldName)) {
+ return plsqlType;
+ }
+ }
+ // check procedures
+ for (ProcedureType procType : packageType.getProcedures()) {
+ if (procType.getProcedureName().equals(fieldName)) {
+ return procType;
+ }
+ }
+ // check local variables
+ for (FieldType fieldType : packageType.getLocalVariables()) {
+ if (fieldType.getFieldName().equals(fieldName)) {
+ return fieldType;
+ }
+ }
}
// we may be dealing with a Field type, and need to navigate to the last enclosed type
else if (targetType.isFieldType()) {
- FieldType fldType = (FieldType) targetType;
- DatabaseType eType = fldType.getEnclosedType();
- if (eType.isComposite()) {
- CompositeDatabaseType cType = (CompositeDatabaseType) eType;
- while (cType.getEnclosedType() != null) {
- eType = cType.getEnclosedType();
- if (eType.isComposite()) {
- cType = (CompositeDatabaseType) eType;
- } else {
- break;
- }
- }
- }
- foundType = findField(fieldName, eType);
+ FieldType fldType = (FieldType) targetType;
+ DatabaseType eType = fldType.getEnclosedType();
+ if (eType.isComposite()) {
+ CompositeDatabaseType cType = (CompositeDatabaseType) eType;
+ while (cType.getEnclosedType() != null) {
+ eType = cType.getEnclosedType();
+ if (eType.isComposite()) {
+ cType = (CompositeDatabaseType) eType;
+ } else {
+ break;
+ }
+ }
+ }
+ return findField(fieldName, eType);
}
- return foundType;
+ return null;
}
}
\ No newline at end of file