/** * INTERNAL Used by SQLCall.appendModify(..) If the field should be passed to * customModifyInDatabaseCall, return true, otherwise false. Methods * shouldCustomModifyInDatabaseCall and customModifyInDatabaseCall should be kept in sync: * shouldCustomModifyInDatabaseCall should return true if and only if the field is handled by * customModifyInDatabaseCall. */ public boolean shouldUseCustomModifyForCall(DatabaseField field) { Class type = field.getType(); if ((type != null) && isOracle9Specific(type)) { return true; } return super.shouldUseCustomModifyForCall(field); }
/** * INTERNAL: Used by SQLCall.translate(..) The binding *must* be performed (NCHAR, NSTRING, * NCLOB). In these special cases the method returns a wrapper object which knows whether it * should be bound or appended and knows how to do that. */ public Object getCustomModifyValueForCall( Call call, Object value, DatabaseField field, boolean shouldBind) { Class type = field.getType(); if ((type != null) && isOracle9Specific(type)) { if (value == null) { return null; } if (NCHAR.equals(type) || NSTRING.equals(type)) { return new NTypeBindCallCustomParameter(value); } else if (NCLOB.equals(type)) { value = convertToDatabaseType(value); if (shouldUseLocatorForLOBWrite()) { if (lobValueExceedsLimit(value)) { ((DatabaseCall) call).addContext(field, value); value = new String(" "); } } return new NTypeBindCallCustomParameter(value); } else if (XMLTYPE.equals(type)) { return getXMLTypeFactory().createXMLTypeBindCallCustomParameter(value); } } return super.getCustomModifyValueForCall(call, value, field, shouldBind); }
/** * INTERNAL: Build and return the nested rows from the specified field value. This method allows * the field value to be an ARRAY containing other structures such as arrays or Struct, or direct * values. */ public static Object buildContainerFromArray( Array fieldValue, ObjectRelationalDatabaseField arrayField, AbstractSession session) throws DatabaseException { if (arrayField.getType() == null) { return fieldValue; } Object[] objects = null; try { objects = (Object[]) fieldValue.getArray(); } catch (java.sql.SQLException ex) { throw DatabaseException.sqlException(ex, session, false); } if (objects == null) { return null; } boolean isNestedStructure = false; ObjectRelationalDataTypeDescriptor ord = null; DatabaseField nestedType = null; if (arrayField != null) { nestedType = arrayField.getNestedTypeField(); if ((nestedType != null) && nestedType.getSqlType() == Types.STRUCT) { ClassDescriptor descriptor = session.getDescriptor(nestedType.getType()); if ((descriptor != null) && (descriptor.isObjectRelationalDataTypeDescriptor())) { // this is used to convert non-null objects passed through stored procedures and custom // SQL to structs ord = (ObjectRelationalDataTypeDescriptor) descriptor; } } else if ((nestedType != null) && (nestedType instanceof ObjectRelationalDatabaseField)) { isNestedStructure = true; } } // handle ARRAY conversions ReadObjectQuery query = new ReadObjectQuery(); query.setSession(session); ContainerPolicy cp = ContainerPolicy.buildPolicyFor(arrayField.getType()); Object container = cp.containerInstance(objects.length); for (int i = 0; i < objects.length; i++) { Object arrayValue = objects[i]; if (arrayValue == null) { return null; } if (ord != null) { AbstractRecord nestedRow = ord.buildRowFromStructure((Struct) arrayValue); ClassDescriptor descriptor = ord; if (descriptor.hasInheritance()) { Class newElementClass = descriptor.getInheritancePolicy().classFromRow(nestedRow, session); if (!descriptor.getJavaClass().equals(newElementClass)) { descriptor = session.getDescriptor(newElementClass); if (descriptor == null) { descriptor = ord; } } } arrayValue = descriptor.getObjectBuilder().buildNewInstance(); descriptor .getObjectBuilder() .buildAttributesIntoObject(arrayValue, nestedRow, query, null, false); } else if (isNestedStructure && (arrayValue instanceof Array)) { arrayValue = buildContainerFromArray( (Array) arrayValue, (ObjectRelationalDatabaseField) nestedType, session); } cp.addInto(arrayValue, container, session); } return container; }