Search in sources :

Example 6 with ColumnMapping

use of org.datanucleus.store.rdbms.mapping.column.ColumnMapping in project datanucleus-rdbms by datanucleus.

the class EmbeddedMapping method addMappingForMember.

/**
 * Method to add a mapping for the specified member to this mapping.
 * @param embCmd Class that the member belongs to
 * @param embMmd Member to be added
 * @param embmdMmds Metadata for embedded members in the "embedded" specification (if any)
 */
private void addMappingForMember(AbstractClassMetaData embCmd, AbstractMemberMetaData embMmd, List<AbstractMemberMetaData> embmdMmds) {
    if (emd != null && emd.getOwnerMember() != null && emd.getOwnerMember().equals(embMmd.getName())) {
    // Do nothing since we don't map owner fields (since the owner is the containing object)
    } else {
        // Find the (embedded) member metadata for this member
        AbstractMemberMetaData embeddedMmd = null;
        for (AbstractMemberMetaData embmdMmd : embmdMmds) {
            AbstractMemberMetaData embMmdForMmds = embCmd.getMetaDataForMember(embmdMmd.getName());
            if (embMmdForMmds != null) {
                if (embMmdForMmds.getAbsoluteFieldNumber() == embMmd.getAbsoluteFieldNumber()) {
                    // Same as the member we are processing, so use it
                    embeddedMmd = embmdMmd;
                    break;
                }
            }
        }
        // Add mapping
        JavaTypeMapping embMmdMapping;
        MappingManager mapMgr = table.getStoreManager().getMappingManager();
        if (embeddedMmd != null) {
            // User has provided a field definition so map with that
            embMmdMapping = mapMgr.getMapping(table, embeddedMmd, clr, FieldRole.ROLE_FIELD);
        } else {
            // User hasn't provided a field definition so map with the classes own definition
            embMmdMapping = mapMgr.getMapping(table, embMmd, clr, FieldRole.ROLE_FIELD);
        }
        if (embMmd.getRelationType(clr) != RelationType.NONE && embMmdMapping instanceof AbstractContainerMapping) {
            // TODO Support 1-N (unidirectional) relationships and use owner object as the key in the join table See #core-171
            // Removing this block would be the first step, but then we need to update scostore classes to allow for this case, and update
            // table of element to link back to the owner of this embedded PC
            NucleusLogger.PERSISTENCE.warn("Embedded object at " + getMemberMetaData().getFullFieldName() + " has a member " + embMmd.getFullFieldName() + " that is a container. Not fully supported as part of an embedded object!");
        }
        // Use field number from embMmd, since the embedded mmd info doesn't have reliable field numbers
        embMmdMapping.setAbsFieldNumber(embMmd.getAbsoluteFieldNumber());
        this.addJavaTypeMapping(embMmdMapping);
        int numCols = embMmdMapping.getNumberOfColumnMappings();
        for (int j = 0; j < numCols; j++) {
            // Register column with mapping
            ColumnMapping colMapping = embMmdMapping.getColumnMapping(j);
            this.addColumnMapping(colMapping);
            if (this.mmd.isPrimaryKey()) {
                // Overall embedded field should be part of PK, so make all columns part of it
                Column col = colMapping.getColumn();
                if (col != null) {
                    col.setPrimaryKey();
                }
            }
        }
    }
}
Also used : Column(org.datanucleus.store.rdbms.table.Column) MappingManager(org.datanucleus.store.rdbms.mapping.MappingManager) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData) ColumnMapping(org.datanucleus.store.rdbms.mapping.column.ColumnMapping)

Example 7 with ColumnMapping

use of org.datanucleus.store.rdbms.mapping.column.ColumnMapping in project datanucleus-rdbms by datanucleus.

the class SQLFunctionMapping method getObject.

public Object getObject(ExecutionContext ec, ResultSet resultSet, int[] exprIndex) {
    if (exprIndex == null) {
        return null;
    }
    if (columnMappings == null || columnMappings.length == 0) {
        // Set the columnMappings and javaType the first time this is used. Get the type from the ResultSetMetaData.
        try {
            ResultSetMetaData rsmd = resultSet.getMetaData();
            int colType = rsmd.getColumnType(exprIndex[0]);
            if (colType == Types.DOUBLE || colType == Types.DECIMAL) {
                javaType = Double.class;
            } else if (colType == Types.FLOAT) {
                javaType = Float.class;
            } else if (colType == Types.BOOLEAN) {
                javaType = Boolean.class;
            } else if (colType == Types.INTEGER || colType == Types.NUMERIC) {
                javaType = Integer.class;
            } else if (colType == Types.SMALLINT || colType == Types.TINYINT) {
                javaType = Short.class;
            } else if (colType == Types.BIGINT) {
                javaType = BigInteger.class;
            } else if (colType == Types.LONGVARCHAR || colType == Types.VARCHAR || colType == Types.NVARCHAR || colType == Types.CHAR || colType == Types.NCHAR) {
                javaType = String.class;
            } else {
                javaType = Object.class;
            }
        // TODO Provide more comprehensive support for all types
        } catch (SQLException e) {
            e.printStackTrace();
        }
        Class columnMappingClass = storeMgr.getDatastoreAdapter().getColumnMappingClass(javaType.getName(), null, null, ec.getClassLoaderResolver(), null);
        ColumnMapping columnMapping = ColumnMappingFactory.createMapping(columnMappingClass, this, storeMgr, null);
        columnMappings = new ColumnMapping[1];
        columnMappings[0] = columnMapping;
    }
    if (javaType == Double.class) {
        return getColumnMapping(0).getDouble(resultSet, exprIndex[0]);
    } else if (javaType == Float.class) {
        return getColumnMapping(0).getFloat(resultSet, exprIndex[0]);
    } else if (javaType == Integer.class) {
        return getColumnMapping(0).getInt(resultSet, exprIndex[0]);
    } else if (javaType == Long.class) {
        return getColumnMapping(0).getLong(resultSet, exprIndex[0]);
    } else if (javaType == Short.class) {
        return getColumnMapping(0).getShort(resultSet, exprIndex[0]);
    } else if (javaType == BigInteger.class) {
        return getColumnMapping(0).getLong(resultSet, exprIndex[0]);
    } else if (javaType == Boolean.class) {
        return getColumnMapping(0).getBoolean(resultSet, exprIndex[0]);
    } else if (javaType == String.class) {
        return getColumnMapping(0).getString(resultSet, exprIndex[0]);
    }
    return getColumnMapping(0).getObject(resultSet, exprIndex[0]);
}
Also used : ResultSetMetaData(java.sql.ResultSetMetaData) BigInteger(java.math.BigInteger) SQLException(java.sql.SQLException) BigInteger(java.math.BigInteger) ColumnMapping(org.datanucleus.store.rdbms.mapping.column.ColumnMapping)

Example 8 with ColumnMapping

use of org.datanucleus.store.rdbms.mapping.column.ColumnMapping in project datanucleus-rdbms by datanucleus.

the class ClassTable method runCallBacks.

/**
 * Execute the callbacks for the classes that this table maps to.
 * @param clr ClassLoader resolver
 */
private void runCallBacks(ClassLoaderResolver clr) {
    // Run callbacks for all classes managed by this table
    Iterator<AbstractClassMetaData> cmdIter = managedClassMetaData.iterator();
    while (cmdIter.hasNext()) {
        AbstractClassMetaData managedCmd = cmdIter.next();
        if (managingClassCurrent != null && managingClassCurrent.equals(managedCmd.getFullClassName())) {
            // We can't run callbacks for this class since it is still being initialised. Mark callbacks to run after it completes
            runCallbacksAfterManageClass = true;
            break;
        }
        Collection processedCallbacks = callbacksAppliedForManagedClass.get(managedCmd.getFullClassName());
        Collection c = (Collection) storeMgr.getSchemaCallbacks().get(managedCmd.getFullClassName());
        if (c != null) {
            if (processedCallbacks == null) {
                processedCallbacks = new HashSet();
                callbacksAppliedForManagedClass.put(managedCmd.getFullClassName(), processedCallbacks);
            }
            for (Iterator it = c.iterator(); it.hasNext(); ) {
                AbstractMemberMetaData callbackMmd = (AbstractMemberMetaData) it.next();
                if (processedCallbacks.contains(callbackMmd)) {
                    continue;
                }
                processedCallbacks.add(callbackMmd);
                if (callbackMmd.getJoinMetaData() == null) {
                    // 1-N FK relationship
                    AbstractMemberMetaData ownerFmd = callbackMmd;
                    if (ownerFmd.getMappedBy() != null) {
                        // Bidirectional (element has a PC mapping to the owner)
                        // Check that the "mapped-by" field in the other class actually exists
                        AbstractMemberMetaData fmd = null;
                        if (ownerFmd.getMappedBy().indexOf('.') > 0) {
                            // TODO Can we just use getRelatedMemberMetaData always?
                            AbstractMemberMetaData[] relMmds = ownerFmd.getRelatedMemberMetaData(clr);
                            fmd = (relMmds != null && relMmds.length > 0) ? relMmds[0] : null;
                        } else {
                            fmd = managedCmd.getMetaDataForMember(ownerFmd.getMappedBy());
                        }
                        if (fmd == null) {
                            throw new NucleusUserException(Localiser.msg("057036", ownerFmd.getMappedBy(), managedCmd.getFullClassName(), ownerFmd.getFullFieldName()));
                        }
                        if (ownerFmd.getMap() != null && storeMgr.getBooleanProperty(RDBMSPropertyNames.PROPERTY_RDBMS_UNIQUE_CONSTRAINTS_MAP_INVERSE)) {
                            initializeFKMapUniqueConstraints(ownerFmd);
                        }
                        boolean duplicate = false;
                        JavaTypeMapping fkDiscrimMapping = null;
                        JavaTypeMapping orderMapping = null;
                        if (ownerFmd.hasExtension(MetaData.EXTENSION_MEMBER_RELATION_DISCRIM_COLUMN)) {
                            // Collection has a relation discriminator so we need to share the FK. Check for the required discriminator
                            String colName = ownerFmd.getValueForExtension(MetaData.EXTENSION_MEMBER_RELATION_DISCRIM_COLUMN);
                            if (colName == null) {
                                // No column defined so use a fallback name
                                colName = "RELATION_DISCRIM";
                            }
                            Set fkDiscrimEntries = getExternalFkDiscriminatorMappings().entrySet();
                            Iterator discrimMappingIter = fkDiscrimEntries.iterator();
                            while (discrimMappingIter.hasNext()) {
                                Map.Entry entry = (Map.Entry) discrimMappingIter.next();
                                JavaTypeMapping discrimMapping = (JavaTypeMapping) entry.getValue();
                                String discrimColName = (discrimMapping.getColumnMapping(0).getColumn().getColumnMetaData()).getName();
                                if (discrimColName.equalsIgnoreCase(colName)) {
                                    duplicate = true;
                                    fkDiscrimMapping = discrimMapping;
                                    orderMapping = getExternalOrderMappings().get(entry.getKey());
                                    break;
                                }
                            }
                            if (!duplicate) {
                                // Create the relation discriminator column since we dont have this discriminator
                                ColumnMetaData colmd = new ColumnMetaData();
                                colmd.setName(colName);
                                // Allow for elements not in any discriminated collection
                                colmd.setAllowsNull(Boolean.TRUE);
                                // Only support String discriminators currently
                                fkDiscrimMapping = storeMgr.getMappingManager().getMapping(String.class);
                                fkDiscrimMapping.setTable(this);
                                ColumnCreator.createIndexColumn(fkDiscrimMapping, storeMgr, clr, this, colmd, false);
                            }
                            if (fkDiscrimMapping != null) {
                                getExternalFkDiscriminatorMappings().put(ownerFmd, fkDiscrimMapping);
                            }
                        }
                        // Add the order mapping as necessary
                        addOrderMapping(ownerFmd, orderMapping, clr);
                    } else {
                        // Unidirectional (element knows nothing about the owner)
                        String ownerClassName = ownerFmd.getAbstractClassMetaData().getFullClassName();
                        JavaTypeMapping fkMapping = new PersistableMapping();
                        fkMapping.setTable(this);
                        fkMapping.initialize(storeMgr, ownerClassName);
                        JavaTypeMapping fkDiscrimMapping = null;
                        JavaTypeMapping orderMapping = null;
                        boolean duplicate = false;
                        try {
                            // Get the owner id mapping of the "1" end
                            DatastoreClass ownerTbl = storeMgr.getDatastoreClass(ownerClassName, clr);
                            if (ownerTbl == null) {
                                // Class doesn't have its own table (subclass-table) so find where it persists
                                AbstractClassMetaData[] ownerParentCmds = storeMgr.getClassesManagingTableForClass(ownerFmd.getAbstractClassMetaData(), clr);
                                if (ownerParentCmds.length > 1) {
                                    throw new NucleusUserException("Relation (" + ownerFmd.getFullFieldName() + ") with multiple related tables (using subclass-table). Not supported");
                                }
                                ownerClassName = ownerParentCmds[0].getFullClassName();
                                ownerTbl = storeMgr.getDatastoreClass(ownerClassName, clr);
                                if (ownerTbl == null) {
                                    throw new NucleusException("Failed to get owner table at other end of relation for field=" + ownerFmd.getFullFieldName());
                                }
                            }
                            JavaTypeMapping ownerIdMapping = ownerTbl.getIdMapping();
                            ColumnMetaDataContainer colmdContainer = null;
                            if (ownerFmd.hasCollection() || ownerFmd.hasArray()) {
                                // 1-N Collection/array
                                colmdContainer = ownerFmd.getElementMetaData();
                            } else if (ownerFmd.hasMap() && ownerFmd.getKeyMetaData() != null && ownerFmd.getKeyMetaData().getMappedBy() != null) {
                                // 1-N Map with key stored in the value
                                colmdContainer = ownerFmd.getValueMetaData();
                            } else if (ownerFmd.hasMap() && ownerFmd.getValueMetaData() != null && ownerFmd.getValueMetaData().getMappedBy() != null) {
                                // 1-N Map with value stored in the key
                                colmdContainer = ownerFmd.getKeyMetaData();
                            }
                            CorrespondentColumnsMapper correspondentColumnsMapping = new CorrespondentColumnsMapper(colmdContainer, this, ownerIdMapping, true);
                            int countIdFields = ownerIdMapping.getNumberOfColumnMappings();
                            for (int i = 0; i < countIdFields; i++) {
                                ColumnMapping refColumnMapping = ownerIdMapping.getColumnMapping(i);
                                JavaTypeMapping mapping = storeMgr.getMappingManager().getMapping(refColumnMapping.getJavaTypeMapping().getJavaType());
                                ColumnMetaData colmd = correspondentColumnsMapping.getColumnMetaDataByIdentifier(refColumnMapping.getColumn().getIdentifier());
                                if (colmd == null) {
                                    throw new NucleusUserException(Localiser.msg("057035", refColumnMapping.getColumn().getIdentifier(), toString())).setFatal();
                                }
                                DatastoreIdentifier identifier = null;
                                IdentifierFactory idFactory = storeMgr.getIdentifierFactory();
                                if (colmd.getName() == null || colmd.getName().length() < 1) {
                                    // No user provided name so generate one
                                    identifier = idFactory.newForeignKeyFieldIdentifier(ownerFmd, null, refColumnMapping.getColumn().getIdentifier(), storeMgr.getNucleusContext().getTypeManager().isDefaultEmbeddedType(mapping.getJavaType()), FieldRole.ROLE_OWNER);
                                } else {
                                    // User-defined name
                                    identifier = idFactory.newColumnIdentifier(colmd.getName());
                                }
                                Column refColumn = addColumn(mapping.getJavaType().getName(), identifier, mapping, colmd);
                                refColumnMapping.getColumn().copyConfigurationTo(refColumn);
                                if ((colmd.getAllowsNull() == null) || (colmd.getAllowsNull() != null && colmd.isAllowsNull())) {
                                    // User either wants it nullable, or haven't specified anything, so make it nullable
                                    refColumn.setNullable(true);
                                }
                                fkMapping.addColumnMapping(getStoreManager().getMappingManager().createColumnMapping(mapping, refColumn, refColumnMapping.getJavaTypeMapping().getJavaType().getName()));
                                ((PersistableMapping) fkMapping).addJavaTypeMapping(mapping);
                            }
                        } catch (DuplicateColumnException dce) {
                            // If the user hasnt specified "relation-discriminator-column" here we dont allow the sharing of columns
                            if (!ownerFmd.hasExtension(MetaData.EXTENSION_MEMBER_RELATION_DISCRIM_COLUMN)) {
                                throw dce;
                            }
                            // Find the FK using this column and use it instead of creating a new one since we're sharing
                            Iterator fkIter = getExternalFkMappings().entrySet().iterator();
                            fkMapping = null;
                            while (fkIter.hasNext()) {
                                Map.Entry entry = (Map.Entry) fkIter.next();
                                JavaTypeMapping existingFkMapping = (JavaTypeMapping) entry.getValue();
                                for (int j = 0; j < existingFkMapping.getNumberOfColumnMappings(); j++) {
                                    if (existingFkMapping.getColumnMapping(j).getColumn().getIdentifier().toString().equals(dce.getConflictingColumn().getIdentifier().toString())) {
                                        // The FK is shared (and so if it is a List we also share the index)
                                        fkMapping = existingFkMapping;
                                        fkDiscrimMapping = externalFkDiscriminatorMappings.get(entry.getKey());
                                        orderMapping = getExternalOrderMappings().get(entry.getKey());
                                        break;
                                    }
                                }
                            }
                            if (fkMapping == null) {
                                // Should never happen since we know there is a col duplicating ours
                                throw dce;
                            }
                            duplicate = true;
                        }
                        if (!duplicate && ownerFmd.hasExtension(MetaData.EXTENSION_MEMBER_RELATION_DISCRIM_COLUMN)) {
                            // Create the relation discriminator column
                            String colName = ownerFmd.getValueForExtension(MetaData.EXTENSION_MEMBER_RELATION_DISCRIM_COLUMN);
                            if (colName == null) {
                                // No column defined so use a fallback name
                                colName = "RELATION_DISCRIM";
                            }
                            ColumnMetaData colmd = new ColumnMetaData();
                            colmd.setName(colName);
                            // Allow for elements not in any discriminated collection
                            colmd.setAllowsNull(Boolean.TRUE);
                            // Only support String discriminators currently
                            fkDiscrimMapping = storeMgr.getMappingManager().getMapping(String.class);
                            fkDiscrimMapping.setTable(this);
                            ColumnCreator.createIndexColumn(fkDiscrimMapping, storeMgr, clr, this, colmd, false);
                        }
                        // Save the external FK
                        getExternalFkMappings().put(ownerFmd, fkMapping);
                        if (fkDiscrimMapping != null) {
                            getExternalFkDiscriminatorMappings().put(ownerFmd, fkDiscrimMapping);
                        }
                        // Add the order mapping as necessary
                        addOrderMapping(ownerFmd, orderMapping, clr);
                    }
                }
            }
        }
    }
}
Also used : Set(java.util.Set) HashSet(java.util.HashSet) DuplicateColumnException(org.datanucleus.store.rdbms.exceptions.DuplicateColumnException) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) MacroString(org.datanucleus.util.MacroString) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData) ColumnMetaDataContainer(org.datanucleus.metadata.ColumnMetaDataContainer) Iterator(java.util.Iterator) ColumnMetaData(org.datanucleus.metadata.ColumnMetaData) ColumnMapping(org.datanucleus.store.rdbms.mapping.column.ColumnMapping) HashSet(java.util.HashSet) NucleusUserException(org.datanucleus.exceptions.NucleusUserException) IdentifierFactory(org.datanucleus.store.rdbms.identifier.IdentifierFactory) PersistableMapping(org.datanucleus.store.rdbms.mapping.java.PersistableMapping) DatastoreIdentifier(org.datanucleus.store.rdbms.identifier.DatastoreIdentifier) Collection(java.util.Collection) NucleusException(org.datanucleus.exceptions.NucleusException) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData) Map(java.util.Map) HashMap(java.util.HashMap) CorrespondentColumnsMapper(org.datanucleus.store.rdbms.mapping.CorrespondentColumnsMapper)

Example 9 with ColumnMapping

use of org.datanucleus.store.rdbms.mapping.column.ColumnMapping in project datanucleus-rdbms by datanucleus.

the class SelectStatement method select.

/**
 * Add a select clause for the specified field (via its mapping).
 * If an alias is supplied and there are more than 1 column for this mapping then they will have
 * names like "{alias}_n" where n is the column number (starting at 0).
 * @param table The SQLTable to select from (null implies the primary table)
 * @param mapping The mapping for the field
 * @param alias optional alias
 * @param applyToUnions Whether to apply to unions
 * @return The column index(es) in the statement for the specified field (1 is first).
 */
public int[] select(SQLTable table, JavaTypeMapping mapping, String alias, boolean applyToUnions) {
    if (mapping == null) {
        throw new NucleusException("Mapping to select is null");
    } else if (table == null) {
        // Default to the primary table if not specified
        table = primaryTable;
    }
    if (mapping.getTable() != table.getTable()) {
        throw new NucleusException("Table being selected from (\"" + table.getTable() + "\") is inconsistent with the column selected (\"" + mapping.getTable() + "\")");
    }
    invalidateStatement();
    ColumnMapping[] mappings = mapping.getColumnMappings();
    int[] selected = new int[mappings.length];
    for (int i = 0; i < selected.length; i++) {
        DatastoreIdentifier colAlias = null;
        if (alias != null) {
            String name = (selected.length > 1) ? (alias + "_" + i) : alias;
            colAlias = rdbmsMgr.getIdentifierFactory().newColumnIdentifier(name);
        }
        SQLColumn col = new SQLColumn(table, mappings[i].getColumn(), colAlias);
        selected[i] = selectItem(new SQLText(col.getColumnSelectString()), alias != null ? colAlias.toString() : null, true);
    }
    if (applyToUnions && unions != null && allowUnions) {
        // Apply the select to all unions
        Iterator<SelectStatement> unionIter = unions.iterator();
        while (unionIter.hasNext()) {
            SelectStatement stmt = unionIter.next();
            stmt.select(table, mapping, alias);
        }
    }
    return selected;
}
Also used : DatastoreIdentifier(org.datanucleus.store.rdbms.identifier.DatastoreIdentifier) NucleusException(org.datanucleus.exceptions.NucleusException) ColumnMapping(org.datanucleus.store.rdbms.mapping.column.ColumnMapping)

Example 10 with ColumnMapping

use of org.datanucleus.store.rdbms.mapping.column.ColumnMapping in project datanucleus-rdbms by datanucleus.

the class CharacterLiteral method setStatement.

protected void setStatement() {
    st.clearStatement();
    ColumnMapping colMapping = mapping.getColumnMapping(0);
    if (colMapping.isIntegerBased()) {
        st.append("" + (int) this.value.charAt(0));
    } else {
        st.append('\'').append(this.value).append('\'');
    }
}
Also used : ColumnMapping(org.datanucleus.store.rdbms.mapping.column.ColumnMapping)

Aggregations

ColumnMapping (org.datanucleus.store.rdbms.mapping.column.ColumnMapping)12 ColumnMetaData (org.datanucleus.metadata.ColumnMetaData)4 DatastoreIdentifier (org.datanucleus.store.rdbms.identifier.DatastoreIdentifier)4 JavaTypeMapping (org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping)4 Column (org.datanucleus.store.rdbms.table.Column)4 DatastoreClass (org.datanucleus.store.rdbms.table.DatastoreClass)4 NucleusException (org.datanucleus.exceptions.NucleusException)3 AbstractClassMetaData (org.datanucleus.metadata.AbstractClassMetaData)3 AbstractMemberMetaData (org.datanucleus.metadata.AbstractMemberMetaData)3 PersistableMapping (org.datanucleus.store.rdbms.mapping.java.PersistableMapping)3 SQLException (java.sql.SQLException)2 HashMap (java.util.HashMap)2 Iterator (java.util.Iterator)2 Map (java.util.Map)2 NucleusUserException (org.datanucleus.exceptions.NucleusUserException)2 RelationType (org.datanucleus.metadata.RelationType)2 DatastoreAdapter (org.datanucleus.store.rdbms.adapter.DatastoreAdapter)2 ResultAliasExpression (org.datanucleus.store.rdbms.sql.expression.ResultAliasExpression)2 BigDecimal (java.math.BigDecimal)1 BigInteger (java.math.BigInteger)1