use of org.datanucleus.metadata.SoftDeleteMetaData 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
*/
@Override
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].getNumberOfColumnMappings();
Index index = new Index(this, false, null);
for (int j = 0; j < numColsInImpl; j++) {
index.setColumn(j, fieldMapping.getColumnMapping(colNum++).getColumn());
}
indices.add(index);
}
}
}
} else {
Index index = new Index(this, false, null);
for (int i = 0; i < fieldMapping.getNumberOfColumnMappings(); i++) {
index.setColumn(i, fieldMapping.getColumnMapping(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.getNumberOfColumnMappings(); i++) {
index.setColumn(i, fieldMapping.getColumnMapping(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.getNumberOfColumnMappings() > 0) {
Index index = new Index(this, false, null);
for (int i = 0; i < fieldMapping.getNumberOfColumnMappings(); i++) {
index.setColumn(i, fieldMapping.getColumnMapping(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.getNumberOfColumnMappings();
for (int i = 0; i < countVersionFields; i++) {
index.addColumn(versionMapping.getColumnMapping(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 numCols = discriminatorMapping.getNumberOfColumnMappings();
for (int i = 0; i < numCols; i++) {
index.addColumn(discriminatorMapping.getColumnMapping(i).getColumn());
}
indices.add(index);
}
}
// Check if multitenancy discriminator present and needs indexing
if (multitenancyMapping != null) {
MultitenancyMetaData mtmd = cmd.getMultitenancyMetaData();
IndexMetaData idxmd = mtmd.getIndexMetaData();
if (idxmd != null) {
Index index = new Index(this, false, null);
if (idxmd.getName() != null) {
index.setName(idxmd.getName());
}
int numCols = multitenancyMapping.getNumberOfColumnMappings();
for (int i = 0; i < numCols; i++) {
index.addColumn(multitenancyMapping.getColumnMapping(i).getColumn());
}
indices.add(index);
}
}
// Check if soft delete column present and needs indexing
if (softDeleteMapping != null) {
SoftDeleteMetaData sdmd = cmd.getSoftDeleteMetaData();
IndexMetaData idxmd = sdmd.getIndexMetaData();
if (idxmd != null) {
Index index = new Index(this, false, null);
if (idxmd.getName() != null) {
index.setName(idxmd.getName());
}
int numCols = softDeleteMapping.getNumberOfColumnMappings();
for (int i = 0; i < numCols; i++) {
index.addColumn(softDeleteMapping.getColumnMapping(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.SoftDeleteMetaData in project datanucleus-rdbms by datanucleus.
the class ClassTable method initialize.
/**
* Method to initialise the table.
* This adds the columns based on the MetaData representation for the class being represented by this table.
* @param clr The ClassLoaderResolver
*/
@Override
public void initialize(ClassLoaderResolver clr) {
// if already initialized, we have nothing further to do here
if (isInitialized()) {
return;
}
// we may inherit from that table are initialized at the point at which we may need them
if (supertable != null) {
supertable.initialize(clr);
}
// Add the fields for this class (and any other superclasses that we need to manage the
// fields for (inheritance-strategy="subclass-table" in the superclass)
initializeForClass(cmd, clr);
// Add Version where specified in MetaData
// TODO If there is a superclass table that has a version we should omit from here even if in MetaData. See "getTableWithDiscriminator()" for the logic
versionMetaData = cmd.getVersionMetaDataForTable();
if (versionMetaData != null && versionMetaData.getMemberName() == null) {
if (versionMetaData.getStrategy() == VersionStrategy.NONE) {
// Equate NONE to an integral column (TODO Allow for using timestamp when not checking the version?)
// See also LockManagerImpl
versionMapping = new VersionMapping.VersionLongMapping(this, storeMgr.getMappingManager().getMapping(Long.class));
} else if (versionMetaData.getStrategy() == VersionStrategy.VERSION_NUMBER) {
versionMapping = new VersionMapping.VersionLongMapping(this, storeMgr.getMappingManager().getMapping(Long.class));
} else if (versionMetaData.getStrategy() == VersionStrategy.DATE_TIME) {
if (!dba.supportsOption(DatastoreAdapter.DATETIME_STORES_MILLISECS)) {
// TODO Localise this
throw new NucleusException("Class " + cmd.getFullClassName() + " is defined " + "to use date-time versioning, yet this datastore doesnt support storing " + "milliseconds in DATETIME/TIMESTAMP columns. Use version-number");
}
versionMapping = new VersionMapping.VersionTimestampMapping(this, storeMgr.getMappingManager().getMapping(Timestamp.class));
} else if (versionMetaData.getStrategy() == VersionStrategy.STATE_IMAGE) {
// TODO Support state-image strategy
throw new NucleusUserException("DataNucleus doesnt currently support version strategy \"state-image\"");
}
if (versionMapping != null) {
logMapping("VERSION", versionMapping);
}
}
DiscriminatorMetaData dismd = cmd.getDiscriminatorMetaDataForTable();
if (dismd != null) {
// Surrogate discriminator
discriminatorMetaData = dismd;
if (storeMgr.getBooleanProperty(RDBMSPropertyNames.PROPERTY_RDBMS_DISCRIM_PER_SUBCLASS_TABLE)) {
// Backwards compatibility only. Creates discriminator in all subclass tables even though not needed
// TODO Remove this in the future
discriminatorMapping = DiscriminatorMapping.createDiscriminatorMapping(this, dismd);
} else {
// Create discriminator column only in top most table that needs it
ClassTable tableWithDiscrim = getTableWithDiscriminator();
if (tableWithDiscrim == this) {
// No superclass with a discriminator so add it in this table
discriminatorMapping = DiscriminatorMapping.createDiscriminatorMapping(this, dismd);
}
}
if (discriminatorMapping != null) {
logMapping("DISCRIMINATOR", discriminatorMapping);
}
}
// TODO Only put on root table (i.e "if (supertable != null)" then omit)
MultitenancyMetaData mtmd = cmd.getMultitenancyMetaData();
if (mtmd != null) {
// Surrogate multi-tenancy discriminator
ColumnMetaData colmd = mtmd.getColumnMetaData();
if (colmd == null) {
colmd = new ColumnMetaData();
if (mtmd.getColumnName() != null) {
colmd.setName(mtmd.getColumnName());
}
}
String colName = (colmd.getName() != null) ? colmd.getName() : "TENANT_ID";
String typeName = (colmd.getJdbcType() == JdbcType.INTEGER) ? Integer.class.getName() : String.class.getName();
multitenancyMapping = (typeName.equals(Integer.class.getName())) ? new IntegerMapping() : new StringMapping();
multitenancyMapping.setTable(this);
multitenancyMapping.initialize(storeMgr, typeName);
Column tenantColumn = addColumn(typeName, storeMgr.getIdentifierFactory().newIdentifier(IdentifierType.COLUMN, colName), multitenancyMapping, colmd);
storeMgr.getMappingManager().createColumnMapping(multitenancyMapping, tenantColumn, typeName);
logMapping("MULTITENANCY", multitenancyMapping);
}
SoftDeleteMetaData sdmd = cmd.getSoftDeleteMetaData();
if (sdmd != null) {
// Surrogate "SoftDelete" flag column
ColumnMetaData colmd = sdmd.getColumnMetaData();
if (colmd == null) {
colmd = new ColumnMetaData();
if (sdmd.getColumnName() != null) {
colmd.setName(sdmd.getColumnName());
}
}
String colName = (colmd.getName() != null) ? colmd.getName() : "DELETED";
// TODO Allow integer using JDBC type
String typeName = Boolean.class.getName();
softDeleteMapping = new BooleanMapping();
softDeleteMapping.setTable(this);
softDeleteMapping.initialize(storeMgr, typeName);
Column tenantColumn = addColumn(typeName, storeMgr.getIdentifierFactory().newIdentifier(IdentifierType.COLUMN, colName), softDeleteMapping, colmd);
storeMgr.getMappingManager().createColumnMapping(softDeleteMapping, tenantColumn, typeName);
logMapping("SOFTDELETE", softDeleteMapping);
}
if (cmd.hasExtension(MetaData.EXTENSION_CLASS_CREATEUSER)) {
// Surrogate "create user" column
ColumnMetaData colmd = new ColumnMetaData();
if (cmd.hasExtension(MetaData.EXTENSION_CLASS_CREATEUSER_COLUMN_NAME)) {
colmd.setName(cmd.getValueForExtension(MetaData.EXTENSION_CLASS_CREATEUSER_COLUMN_NAME));
}
if (cmd.hasExtension(MetaData.EXTENSION_CLASS_CREATEUSER_COLUMN_LENGTH)) {
colmd.setLength(cmd.getValueForExtension(MetaData.EXTENSION_CLASS_CREATEUSER_COLUMN_LENGTH));
}
String colName = (colmd.getName() != null) ? colmd.getName() : "CREATE_USER";
String typeName = String.class.getName();
createUserMapping = new StringMapping();
createUserMapping.setTable(this);
createUserMapping.initialize(storeMgr, typeName);
Column auditColumn = addColumn(typeName, storeMgr.getIdentifierFactory().newIdentifier(IdentifierType.COLUMN, colName), createUserMapping, colmd);
storeMgr.getMappingManager().createColumnMapping(createUserMapping, auditColumn, typeName);
logMapping("CREATEUSER", createUserMapping);
}
if (cmd.hasExtension(MetaData.EXTENSION_CLASS_CREATETIMESTAMP)) {
// Surrogate "create timestamp" column
ColumnMetaData colmd = new ColumnMetaData();
if (cmd.hasExtension(MetaData.EXTENSION_CLASS_CREATETIMESTAMP_COLUMN_NAME)) {
colmd.setName(cmd.getValueForExtension(MetaData.EXTENSION_CLASS_CREATETIMESTAMP_COLUMN_NAME));
}
String colName = (colmd.getName() != null) ? colmd.getName() : "CREATE_TIMESTAMP";
String typeName = Timestamp.class.getName();
createTimestampMapping = new SqlTimestampMapping();
createTimestampMapping.setTable(this);
createTimestampMapping.initialize(storeMgr, typeName);
Column auditColumn = addColumn(typeName, storeMgr.getIdentifierFactory().newIdentifier(IdentifierType.COLUMN, colName), createTimestampMapping, colmd);
storeMgr.getMappingManager().createColumnMapping(createTimestampMapping, auditColumn, typeName);
logMapping("CREATETIMESTAMP", createTimestampMapping);
}
if (cmd.hasExtension(MetaData.EXTENSION_CLASS_UPDATEUSER)) {
// Surrogate "update user" column
ColumnMetaData colmd = new ColumnMetaData();
if (cmd.hasExtension(MetaData.EXTENSION_CLASS_UPDATEUSER_COLUMN_NAME)) {
colmd.setName(cmd.getValueForExtension(MetaData.EXTENSION_CLASS_UPDATEUSER_COLUMN_NAME));
}
if (cmd.hasExtension(MetaData.EXTENSION_CLASS_UPDATEUSER_COLUMN_LENGTH)) {
colmd.setLength(cmd.getValueForExtension(MetaData.EXTENSION_CLASS_UPDATEUSER_COLUMN_LENGTH));
}
String colName = (colmd.getName() != null) ? colmd.getName() : "UPDATE_USER";
String typeName = String.class.getName();
updateUserMapping = new StringMapping();
updateUserMapping.setTable(this);
updateUserMapping.initialize(storeMgr, typeName);
Column auditColumn = addColumn(typeName, storeMgr.getIdentifierFactory().newIdentifier(IdentifierType.COLUMN, colName), updateUserMapping, colmd);
storeMgr.getMappingManager().createColumnMapping(updateUserMapping, auditColumn, typeName);
logMapping("UPDATEUSER", updateUserMapping);
}
if (cmd.hasExtension(MetaData.EXTENSION_CLASS_UPDATETIMESTAMP)) {
// Surrogate "update timestamp" column
ColumnMetaData colmd = new ColumnMetaData();
if (cmd.hasExtension(MetaData.EXTENSION_CLASS_UPDATETIMESTAMP_COLUMN_NAME)) {
colmd.setName(cmd.getValueForExtension(MetaData.EXTENSION_CLASS_UPDATETIMESTAMP_COLUMN_NAME));
}
String colName = (colmd.getName() != null) ? colmd.getName() : "UPDATE_TIMESTAMP";
String typeName = Timestamp.class.getName();
updateTimestampMapping = new SqlTimestampMapping();
updateTimestampMapping.setTable(this);
updateTimestampMapping.initialize(storeMgr, typeName);
Column auditColumn = addColumn(typeName, storeMgr.getIdentifierFactory().newIdentifier(IdentifierType.COLUMN, colName), updateTimestampMapping, colmd);
storeMgr.getMappingManager().createColumnMapping(updateTimestampMapping, auditColumn, typeName);
logMapping("UPDATETIMESTAMP", updateTimestampMapping);
}
// Initialise any SecondaryTables
if (secondaryTables != null) {
Iterator<Map.Entry<String, SecondaryTable>> secondaryTableEntryIter = secondaryTables.entrySet().iterator();
while (secondaryTableEntryIter.hasNext()) {
Map.Entry<String, SecondaryTable> secondaryTableEntry = secondaryTableEntryIter.next();
SecondaryTable second = secondaryTableEntry.getValue();
if (!second.isInitialized()) {
second.initialize(clr);
}
}
}
if (NucleusLogger.DATASTORE_SCHEMA.isDebugEnabled()) {
NucleusLogger.DATASTORE_SCHEMA.debug(Localiser.msg("057023", this));
}
storeMgr.registerTableInitialized(this);
state = TABLE_STATE_INITIALIZED;
}
Aggregations