use of org.datanucleus.metadata.AbstractMemberMetaData in project datanucleus-rdbms by datanucleus.
the class ClassTable method getExpectedIndices.
/**
* Accessor for the indices for this table. This includes both the
* user-defined indices (via MetaData), and the ones required by foreign
* keys (required by relationships).
* @param clr The ClassLoaderResolver
* @return The indices
*/
protected Set<Index> getExpectedIndices(ClassLoaderResolver clr) {
// Auto mode allows us to decide which indices are needed as well as using what is in the users MetaData
boolean autoMode = false;
if (storeMgr.getStringProperty(RDBMSPropertyNames.PROPERTY_RDBMS_CONSTRAINT_CREATE_MODE).equals("DataNucleus")) {
autoMode = true;
}
Set<Index> indices = new HashSet();
// Add on any user-required indices for the fields/properties
Set memberNumbersSet = memberMappingsMap.keySet();
Iterator iter = memberNumbersSet.iterator();
while (iter.hasNext()) {
AbstractMemberMetaData fmd = (AbstractMemberMetaData) iter.next();
JavaTypeMapping fieldMapping = memberMappingsMap.get(fmd);
if (fieldMapping instanceof EmbeddedPCMapping) {
// Add indexes for fields of this embedded PC object
EmbeddedPCMapping embMapping = (EmbeddedPCMapping) fieldMapping;
for (int i = 0; i < embMapping.getNumberOfJavaTypeMappings(); i++) {
JavaTypeMapping embFieldMapping = embMapping.getJavaTypeMapping(i);
IndexMetaData imd = embFieldMapping.getMemberMetaData().getIndexMetaData();
if (imd != null) {
Index index = TableUtils.getIndexForField(this, imd, embFieldMapping);
if (index != null) {
indices.add(index);
}
}
}
} else if (fieldMapping instanceof SerialisedMapping) {
// Don't index these
} else {
// Add any required index for this field
IndexMetaData imd = fmd.getIndexMetaData();
if (imd != null) {
// Index defined so add it
Index index = TableUtils.getIndexForField(this, imd, fieldMapping);
if (index != null) {
indices.add(index);
}
} else if (autoMode) {
if (fmd.getIndexed() == null) {
// Indexing not set, so add where we think it is appropriate
if (// Ignore PKs since they will be indexed anyway
!fmd.isPrimaryKey()) {
// TODO Some RDBMS create index automatically for all FK cols so we don't need to really
RelationType relationType = fmd.getRelationType(clr);
if (relationType == RelationType.ONE_TO_ONE_UNI) {
// 1-1 with FK at this side so index the FK
if (fieldMapping instanceof ReferenceMapping) {
ReferenceMapping refMapping = (ReferenceMapping) fieldMapping;
if (refMapping.getMappingStrategy() == ReferenceMapping.PER_IMPLEMENTATION_MAPPING) {
// Cols per implementation : index each of implementations
if (refMapping.getJavaTypeMapping() != null) {
int colNum = 0;
JavaTypeMapping[] implMappings = refMapping.getJavaTypeMapping();
for (int i = 0; i < implMappings.length; i++) {
int numColsInImpl = implMappings[i].getNumberOfDatastoreMappings();
Index index = new Index(this, false, null);
for (int j = 0; j < numColsInImpl; j++) {
index.setColumn(j, fieldMapping.getDatastoreMapping(colNum++).getColumn());
}
indices.add(index);
}
}
}
} else {
Index index = new Index(this, false, null);
for (int i = 0; i < fieldMapping.getNumberOfDatastoreMappings(); i++) {
index.setColumn(i, fieldMapping.getDatastoreMapping(i).getColumn());
}
indices.add(index);
}
} else if (relationType == RelationType.ONE_TO_ONE_BI && fmd.getMappedBy() == null) {
// 1-1 with FK at this side so index the FK
Index index = new Index(this, false, null);
for (int i = 0; i < fieldMapping.getNumberOfDatastoreMappings(); i++) {
index.setColumn(i, fieldMapping.getDatastoreMapping(i).getColumn());
}
indices.add(index);
} else if (relationType == RelationType.MANY_TO_ONE_BI) {
// N-1 with FK at this side so index the FK
AbstractMemberMetaData relMmd = fmd.getRelatedMemberMetaData(clr)[0];
if (relMmd.getJoinMetaData() == null && fmd.getJoinMetaData() == null) {
if (fieldMapping.getNumberOfDatastoreMappings() > 0) {
Index index = new Index(this, false, null);
for (int i = 0; i < fieldMapping.getNumberOfDatastoreMappings(); i++) {
index.setColumn(i, fieldMapping.getDatastoreMapping(i).getColumn());
}
indices.add(index);
} else {
// TODO How do we get this?
NucleusLogger.DATASTORE_SCHEMA.warn("Table " + this + " manages member " + fmd.getFullFieldName() + " which is a N-1 but there is no column for this mapping so not adding index!");
}
}
}
}
}
}
}
}
// Check if any version column needs indexing
if (versionMapping != null) {
IndexMetaData idxmd = getVersionMetaData().getIndexMetaData();
if (idxmd != null) {
Index index = new Index(this, idxmd.isUnique(), idxmd.getExtensions());
if (idxmd.getName() != null) {
index.setName(idxmd.getName());
}
int countVersionFields = versionMapping.getNumberOfDatastoreMappings();
for (int i = 0; i < countVersionFields; i++) {
index.addColumn(versionMapping.getDatastoreMapping(i).getColumn());
}
indices.add(index);
}
}
// Check if any discriminator column needs indexing
if (discriminatorMapping != null) {
DiscriminatorMetaData dismd = getDiscriminatorMetaData();
IndexMetaData idxmd = dismd.getIndexMetaData();
if (idxmd != null) {
Index index = new Index(this, idxmd.isUnique(), idxmd.getExtensions());
if (idxmd.getName() != null) {
index.setName(idxmd.getName());
}
int countDiscrimFields = discriminatorMapping.getNumberOfDatastoreMappings();
for (int i = 0; i < countDiscrimFields; i++) {
index.addColumn(discriminatorMapping.getDatastoreMapping(i).getColumn());
}
indices.add(index);
}
}
// Add on any order fields (for lists, arrays, collections) that need indexing
Set orderMappingsEntries = getExternalOrderMappings().entrySet();
Iterator orderMappingsEntriesIter = orderMappingsEntries.iterator();
while (orderMappingsEntriesIter.hasNext()) {
Map.Entry entry = (Map.Entry) orderMappingsEntriesIter.next();
AbstractMemberMetaData fmd = (AbstractMemberMetaData) entry.getKey();
JavaTypeMapping mapping = (JavaTypeMapping) entry.getValue();
OrderMetaData omd = fmd.getOrderMetaData();
if (omd != null && omd.getIndexMetaData() != null) {
Index index = getIndexForIndexMetaDataAndMapping(omd.getIndexMetaData(), mapping);
if (index != null) {
indices.add(index);
}
}
}
// Add on any user-required indices for the class(es) as a whole (subelement of <class>)
Iterator<AbstractClassMetaData> cmdIter = managedClassMetaData.iterator();
while (cmdIter.hasNext()) {
AbstractClassMetaData thisCmd = cmdIter.next();
List<IndexMetaData> classIndices = thisCmd.getIndexMetaData();
if (classIndices != null) {
for (IndexMetaData idxmd : classIndices) {
Index index = getIndexForIndexMetaData(idxmd);
if (index != null) {
indices.add(index);
}
}
}
}
if (cmd.getIdentityType() == IdentityType.APPLICATION) {
// Make sure there is no reuse of PK fields that cause a duplicate index for the PK. Remove it if required
PrimaryKey pk = getPrimaryKey();
Iterator<Index> indicesIter = indices.iterator();
while (indicesIter.hasNext()) {
Index idx = indicesIter.next();
if (idx.getColumnList().equals(pk.getColumnList())) {
NucleusLogger.DATASTORE_SCHEMA.debug("Index " + idx + " is for the same columns as the PrimaryKey so being removed from expected set of indices. PK is always indexed");
indicesIter.remove();
}
}
}
return indices;
}
use of org.datanucleus.metadata.AbstractMemberMetaData in project datanucleus-rdbms by datanucleus.
the class RDBMSStoreManager method isObjectInserted.
/**
* Accessor for whether the specified field of the object is inserted in the datastore yet.
* @param op ObjectProvider for the object
* @param fieldNumber (Absolute) field number for the object
* @return Whether it is persistent
*/
public boolean isObjectInserted(ObjectProvider op, int fieldNumber) {
if (op == null) {
return false;
}
if (!op.isInserting()) {
// StateManager isn't inserting so must be persistent
return true;
}
DatastoreClass latestTable = insertedDatastoreClassByObjectProvider.get(op);
if (latestTable == null) {
// Not yet inserted anything
return false;
}
AbstractMemberMetaData mmd = op.getClassMetaData().getMetaDataForManagedMemberAtAbsolutePosition(fieldNumber);
if (mmd == null) {
// Specified field doesn't exist for this object type!
return false;
}
String className = mmd.getClassName();
if (mmd.isPrimaryKey()) {
// PK field so need to check if the latestTable manages the actual class here
className = op.getObject().getClass().getName();
}
DatastoreClass datastoreCls = latestTable;
while (datastoreCls != null) {
if (datastoreCls.managesClass(className)) {
// This datastore class manages the specified class so it is inserted
return true;
}
datastoreCls = datastoreCls.getSuperDatastoreClass();
}
return false;
}
use of org.datanucleus.metadata.AbstractMemberMetaData in project datanucleus-rdbms by datanucleus.
the class RDBMSStoreManager method getTableForStrategy.
private DatastoreClass getTableForStrategy(AbstractClassMetaData cmd, int fieldNumber, ClassLoaderResolver clr) {
DatastoreClass t = getDatastoreClass(cmd.getFullClassName(), clr);
if (t == null && cmd.getInheritanceMetaData().getStrategy() == InheritanceStrategy.SUBCLASS_TABLE) {
throw new NucleusUserException(Localiser.msg("032013", cmd.getFullClassName()));
}
if (t == null) {
throw new NucleusUserException("Attempt to find table for class=" + cmd.getFullClassName() + " but no table found! Check the metadata");
}
if (fieldNumber >= 0) {
AbstractMemberMetaData mmd = cmd.getMetaDataForManagedMemberAtAbsolutePosition(fieldNumber);
t = t.getBaseDatastoreClassWithMember(mmd);
} else {
// Go up to overall superclass to find id for that class.
boolean hasSuperclass = true;
while (hasSuperclass) {
DatastoreClass supert = t.getSuperDatastoreClass();
if (supert != null) {
t = supert;
} else {
hasSuperclass = false;
}
}
}
return t;
}
use of org.datanucleus.metadata.AbstractMemberMetaData in project datanucleus-rdbms by datanucleus.
the class RDBMSStoreManager method getPropertiesForValueGenerator.
/**
* Method to return the properties to pass to the ValueGenerator for the specified field.
* @param cmd MetaData for the class
* @param absoluteFieldNumber Number of the field (-1 = datastore identity)
* @param clr ClassLoader resolver
* @param seqmd Any sequence metadata
* @param tablegenmd Any table generator metadata
* @return The properties to use for this field
*/
protected Properties getPropertiesForValueGenerator(AbstractClassMetaData cmd, int absoluteFieldNumber, ClassLoaderResolver clr, SequenceMetaData seqmd, TableGeneratorMetaData tablegenmd) {
AbstractMemberMetaData mmd = null;
ValueGenerationStrategy strategy = null;
String sequence = null;
Map<String, String> extensions = null;
if (absoluteFieldNumber >= 0) {
// real field
mmd = cmd.getMetaDataForManagedMemberAtAbsolutePosition(absoluteFieldNumber);
strategy = mmd.getValueStrategy();
sequence = mmd.getSequence();
extensions = mmd.getExtensions();
} else {
// datastore-identity surrogate field
// always use the root IdentityMetaData since the root class defines the identity
IdentityMetaData idmd = cmd.getBaseIdentityMetaData();
strategy = idmd.getValueStrategy();
sequence = idmd.getSequence();
extensions = idmd.getExtensions();
}
// Get base table with the required field
DatastoreClass tbl = getDatastoreClass(cmd.getBaseAbstractClassMetaData().getFullClassName(), clr);
if (tbl == null) {
tbl = getTableForStrategy(cmd, absoluteFieldNumber, clr);
}
JavaTypeMapping m = null;
if (mmd != null) {
m = tbl.getMemberMapping(mmd);
if (m == null) {
// Field not mapped in root table so use passed-in table
tbl = getTableForStrategy(cmd, absoluteFieldNumber, clr);
m = tbl.getMemberMapping(mmd);
}
} else {
m = tbl.getIdMapping();
}
StringBuilder columnsName = new StringBuilder();
for (int i = 0; i < m.getNumberOfDatastoreMappings(); i++) {
if (i > 0) {
columnsName.append(",");
}
columnsName.append(m.getDatastoreMapping(i).getColumn().getIdentifier().toString());
}
Properties properties = new Properties();
properties.setProperty(ValueGenerator.PROPERTY_CLASS_NAME, cmd.getFullClassName());
properties.put(ValueGenerator.PROPERTY_ROOT_CLASS_NAME, cmd.getBaseAbstractClassMetaData().getFullClassName());
if (mmd != null) {
properties.setProperty(ValueGenerator.PROPERTY_FIELD_NAME, mmd.getFullFieldName());
}
if (cmd.getCatalog() != null) {
properties.setProperty(ValueGenerator.PROPERTY_CATALOG_NAME, cmd.getCatalog());
} else if (!StringUtils.isWhitespace(catalogName)) {
properties.setProperty(ValueGenerator.PROPERTY_CATALOG_NAME, catalogName);
}
if (cmd.getSchema() != null) {
properties.setProperty(ValueGenerator.PROPERTY_SCHEMA_NAME, cmd.getSchema());
} else if (!StringUtils.isWhitespace(schemaName)) {
properties.setProperty(ValueGenerator.PROPERTY_SCHEMA_NAME, schemaName);
}
properties.setProperty(ValueGenerator.PROPERTY_TABLE_NAME, tbl.getIdentifier().toString());
properties.setProperty(ValueGenerator.PROPERTY_COLUMN_NAME, columnsName.toString());
if (sequence != null) {
properties.setProperty(ValueGenerator.PROPERTY_SEQUENCE_NAME, sequence);
}
// Add any extension properties
if (extensions != null && extensions.size() > 0) {
properties.putAll(extensions);
}
if (strategy.equals(ValueGenerationStrategy.NATIVE)) {
String realStrategyName = getValueGenerationStrategyForNative(cmd, absoluteFieldNumber);
strategy = ValueGenerationStrategy.getIdentityStrategy(realStrategyName);
}
if (strategy == ValueGenerationStrategy.INCREMENT && tablegenmd != null) {
// User has specified a TableGenerator (JPA)
properties.put(ValueGenerator.PROPERTY_KEY_INITIAL_VALUE, "" + tablegenmd.getInitialValue());
properties.put(ValueGenerator.PROPERTY_KEY_CACHE_SIZE, "" + tablegenmd.getAllocationSize());
if (tablegenmd.getTableName() != null) {
properties.put(ValueGenerator.PROPERTY_SEQUENCETABLE_TABLE, tablegenmd.getTableName());
}
if (tablegenmd.getCatalogName() != null) {
properties.put(ValueGenerator.PROPERTY_SEQUENCETABLE_CATALOG, tablegenmd.getCatalogName());
}
if (tablegenmd.getSchemaName() != null) {
properties.put(ValueGenerator.PROPERTY_SEQUENCETABLE_SCHEMA, tablegenmd.getSchemaName());
}
if (tablegenmd.getPKColumnName() != null) {
properties.put(ValueGenerator.PROPERTY_SEQUENCETABLE_NAME_COLUMN, tablegenmd.getPKColumnName());
}
if (tablegenmd.getPKColumnName() != null) {
properties.put(ValueGenerator.PROPERTY_SEQUENCETABLE_NEXTVAL_COLUMN, tablegenmd.getValueColumnName());
}
if (tablegenmd.getPKColumnValue() != null) {
properties.put(ValueGenerator.PROPERTY_SEQUENCE_NAME, tablegenmd.getPKColumnValue());
}
// Using JPA generator so don't enable initial value detection
properties.remove(ValueGenerator.PROPERTY_TABLE_NAME);
properties.remove(ValueGenerator.PROPERTY_COLUMN_NAME);
} else if (strategy == ValueGenerationStrategy.INCREMENT && tablegenmd == null) {
if (!properties.containsKey(ValueGenerator.PROPERTY_KEY_CACHE_SIZE)) {
// Use default allocation size
int allocSize = getIntProperty(PropertyNames.PROPERTY_VALUEGEN_INCREMENT_ALLOCSIZE);
properties.put(ValueGenerator.PROPERTY_KEY_CACHE_SIZE, "" + allocSize);
}
} else if (strategy == ValueGenerationStrategy.SEQUENCE && seqmd != null) {
// User has specified a SequenceGenerator (JDO/JPA)
if (seqmd.getSchemaName() != null) {
properties.put(ValueGenerator.PROPERTY_SEQUENCETABLE_SCHEMA, seqmd.getSchemaName());
}
if (seqmd.getCatalogName() != null) {
properties.put(ValueGenerator.PROPERTY_SEQUENCETABLE_CATALOG, seqmd.getCatalogName());
}
if (StringUtils.isWhitespace(sequence)) {
// Apply default to sequence name, as name of sequence metadata
if (seqmd.getName() != null) {
properties.put(ValueGenerator.PROPERTY_SEQUENCE_NAME, seqmd.getName());
}
}
if (seqmd.getDatastoreSequence() != null) {
if (seqmd.getInitialValue() >= 0) {
properties.put(ValueGenerator.PROPERTY_KEY_INITIAL_VALUE, "" + seqmd.getInitialValue());
}
if (seqmd.getAllocationSize() > 0) {
properties.put(ValueGenerator.PROPERTY_KEY_CACHE_SIZE, "" + seqmd.getAllocationSize());
} else {
// Use default allocation size
int allocSize = getIntProperty(PropertyNames.PROPERTY_VALUEGEN_SEQUENCE_ALLOCSIZE);
properties.put(ValueGenerator.PROPERTY_KEY_CACHE_SIZE, "" + allocSize);
}
properties.put(ValueGenerator.PROPERTY_SEQUENCE_NAME, "" + seqmd.getDatastoreSequence());
// Add on any extensions specified on the sequence
Map<String, String> seqExtensions = seqmd.getExtensions();
if (seqExtensions != null && seqExtensions.size() > 0) {
properties.putAll(seqExtensions);
}
} else {
// JDO Factory-based sequence generation
// TODO Support this
}
}
return properties;
}
use of org.datanucleus.metadata.AbstractMemberMetaData in project datanucleus-rdbms by datanucleus.
the class RDBMSPersistenceHandler method updateObject.
// ------------------------------ Update ----------------------------------
/**
* Updates a persistent object in the database.
* The update can take place in several steps, one update per table that it is stored in (depending on
* which fields are updated).
* e.g When updating an object that uses "new-table" inheritance for each level of the inheritance tree
* then will get an UPDATE into each table. When updating an object that uses "complete-table"
* inheritance then will get a single UPDATE into its table.
* @param op The ObjectProvider of the object to be updated.
* @param fieldNumbers The numbers of the fields to be updated.
* @throws NucleusDataStoreException when an error occurs in the datastore communication
*/
public void updateObject(ObjectProvider op, int[] fieldNumbers) {
// Check if read-only so update not permitted
assertReadOnlyForUpdateOfObject(op);
// Check if we need to do any updates to the schema before updating this object
checkForSchemaUpdatesForFieldsOfObject(op, fieldNumbers);
AbstractMemberMetaData[] mmds = null;
if (fieldNumbers != null && fieldNumbers.length > 0) {
// Convert the field numbers for this class into their metadata for the table
ExecutionContext ec = op.getExecutionContext();
mmds = new AbstractMemberMetaData[fieldNumbers.length];
for (int i = 0; i < mmds.length; i++) {
mmds[i] = op.getClassMetaData().getMetaDataForManagedMemberAtAbsolutePosition(fieldNumbers[i]);
}
if (ec.getStatistics() != null) {
ec.getStatistics().incrementUpdateCount();
}
ClassLoaderResolver clr = ec.getClassLoaderResolver();
DatastoreClass dc = getDatastoreClass(op.getObject().getClass().getName(), clr);
updateObjectInTable(dc, op, clr, mmds);
}
}
Aggregations