protected static Column mergeColumn()

in openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/MappingInfo.java [650:832]


    protected static Column mergeColumn(MetaDataContext context, String prefix,
        Column tmplate, boolean compat, Column given, Table table,
        boolean adapt, boolean fill) {
        assertTable(context, table);

        // if not adapting must provide column name at a minimum
        DBIdentifier colName = (given == null) ? DBIdentifier.NULL : given.getIdentifier();
        if (DBIdentifier.isNull(colName) && !adapt && !fill)
            throw new MetaDataException(_loc.get(prefix + "-no-col-name",
                context));

        MappingRepository repos = (MappingRepository) context.getRepository();
        DBDictionary dict = repos.getDBDictionary();

        // determine the column name based on given info, or template if none;
        // also make sure that if the user gave a column name, he didn't try
        // to put the column in an unexpected table
        if (DBIdentifier.isNull(colName))
            colName = tmplate.getIdentifier();
        QualifiedDBIdentifier path = QualifiedDBIdentifier.getPath(colName);
        if (path.isUnqualifiedColumn()) {
            colName = path.getIdentifier();
        } else if (!DBIdentifier.isNull(path.getObjectTableName())) {
            findTable(context, path.getObjectTableName(), table,
                null, null);
            colName = path.getUnqualifiedName();
        }

        // find existing column
        Column col = table.getColumn(colName);
        if (col == null && !adapt) {
            //
            // See if column name has already been validated in a dynamic table.
            // If so then want to use that validated column name instead. This
            // should seldom if ever occur as long as the database dictionaries
            // are kept up-to-date.
            //
            if ((colName.getName().length() > dict.maxColumnNameLength) ||
               dict.getInvalidColumnWordSet().contains(DBIdentifier.toUpper(colName).getName()) &&
              !(table.getClass().getName().contains("DynamicTable"))) {
                colName=dict.getValidColumnName(colName, new Table());
                col = table.getColumn(colName);
                if (col == null && !adapt) {
                    throw new MetaDataException(_loc.
                        get(prefix + "-bad-col-name", context, colName, table));
                }
            }
            else {
                throw new MetaDataException(_loc.
                    get(prefix + "-bad-col-name", context, colName, table));
            }
        }

        // use information from template column by default, allowing any
        // user-given specifics to override it
        int type = tmplate.getType();
        int size = tmplate.getSize();
        if (type == Types.OTHER) {
            int precis = 0;
            int scale = 0;
            if(given != null) {
                precis = given.getSize();
                scale = given.getDecimalDigits();
            }
            type =
                dict.getJDBCType(tmplate.getJavaType(), size == -1, precis,
                    scale, tmplate.isXML());
        }

        boolean ttype = true;
        int otype = type;
        String typeName = tmplate.getTypeName();
        Boolean notNull = null;
        if (tmplate.isNotNullExplicit())
            notNull = (tmplate.isNotNull()) ? Boolean.TRUE : Boolean.FALSE;
        int decimals = tmplate.getDecimalDigits();
        String defStr = tmplate.getDefaultString();
        boolean autoAssign = tmplate.isAutoAssigned();
        boolean relationId = tmplate.isRelationId();
        boolean implicitRelation = tmplate.isImplicitRelation();
        String targetField = tmplate.getTargetField();
        if (given != null) {
            // use given type if provided, but warn if it isn't compatible with
            // the expected column type
            if (given.getType() != Types.OTHER) {
                ttype = false;
                if (compat && !given.isCompatible(type, typeName, size,
                    decimals)) {
                    Log log = repos.getLog();
                    if (log.isWarnEnabled())
                        log.warn(_loc.get(prefix + "-incompat-col",
                            context, colName, Schemas.getJDBCName(type)));
                }
                otype = given.getType();
                type = dict.getPreferredType(otype);
            }
            typeName = given.getTypeName();
            if (given.getSize() > 0)
                size = given.getSize();
            decimals = given.getDecimalDigits();

            // leave this info as the template defaults unless the user
            // explicitly turns it on in the given column
            if (given.isNotNullExplicit())
                notNull = (given.isNotNull()) ? Boolean.TRUE : Boolean.FALSE;
            if (given.getDefaultString() != null)
                defStr = given.getDefaultString();
            if (given.isAutoAssigned())
                autoAssign = true;
            if (given.isRelationId())
                relationId = true;
            if (given.isImplicitRelation())
                implicitRelation = true;
        }

        // default char column size if original type is char (test original
        // type rather than final type because orig might be clob, translated
        // to an unsized varchar, which is supported by some dbs)
        if (size == 0 && (otype == Types.VARCHAR || otype == Types.CHAR))
            size = dict.characterColumnSize;

        // create column, or make sure existing column matches expected type
        if (col == null) {
            col = table.addColumn(colName);
            col.setType(type);
        } else if ((compat || !ttype) &&
                !col.isCompatible(type, typeName, size, decimals)) {
            // if existing column isn't compatible with desired type, die if
            // can't adapt, else warn and change the existing column type
            Message msg = _loc.get(prefix + "-bad-col", context,
                Schemas.getJDBCName(type), col.getDescription());
            if (!adapt && !dict.disableSchemaFactoryColumnTypeErrors)
                throw new MetaDataException(msg);
            Log log = repos.getLog();
            if (log.isWarnEnabled())
                log.warn(msg);

            col.setType(type);
        } else if (given != null && given.getType() != Types.OTHER) {
            // as long as types are compatible, set column to expected type
            col.setType(type);
        }

        // always set the java type and autoassign to expected values, even on
        // an existing column, since we don't get this from the DB
        if (compat)
            col.setJavaType(tmplate.getJavaType());
        else if (col.getJavaType() == JavaTypes.OBJECT) {
            if (given != null && given.getJavaType() != JavaTypes.OBJECT)
                col.setJavaType(given.getJavaType());
            else
                col.setJavaType(JavaTypes.getTypeCode
                    (Schemas.getJavaType(col.getType(), col.getSize(),
                        col.getDecimalDigits())));
        }
        col.setAutoAssigned(autoAssign);
        col.setRelationId(relationId);
        col.setImplicitRelation(implicitRelation);
        col.setTargetField(targetField);

        // we need this for runtime, and the dynamic schema factory might
        // not know it, so set it even if not adapting
        if (defStr != null)
            col.setDefaultString(defStr);
        if (notNull != null)
            col.setNotNull(notNull);

        // add other details if adapting
        if (adapt) {
            if (typeName != null)
                col.setTypeName(typeName);
            if (size != 0)
                col.setSize(size);
            if (decimals != 0)
                col.setDecimalDigits(decimals);
        }

        if (tmplate.hasComment())
            col.setComment(tmplate.getComment());
        if (tmplate.isXML())
            col.setXML(tmplate.isXML());
        return col;
    }