/** * Method that will unload all fields that are not in the FetchPlan. This is typically for use * when the instance is being refreshed. */ public void unloadNonFetchPlanFields() { int[] fpFieldNumbers = myFP.getMemberNumbers(); int[] nonfpFieldNumbers = null; if (fpFieldNumbers == null || fpFieldNumbers.length == 0) { nonfpFieldNumbers = cmd.getAllMemberPositions(); } else { int fieldCount = cmd.getMemberCount(); if (fieldCount == fpFieldNumbers.length) { // No fields that arent in FetchPlan return; } nonfpFieldNumbers = new int[fieldCount - fpFieldNumbers.length]; int currentFPFieldIndex = 0; int j = 0; for (int i = 0; i < fieldCount; i++) { if (currentFPFieldIndex >= fpFieldNumbers.length) { // Past end of FetchPlan fields nonfpFieldNumbers[j++] = i; } else { if (fpFieldNumbers[currentFPFieldIndex] == i) { // FetchPlan field so move to next currentFPFieldIndex++; } else { nonfpFieldNumbers[j++] = i; } } } } // Mark all non-FetchPlan fields as unloaded for (int i = 0; i < nonfpFieldNumbers.length; i++) { loadedFields[nonfpFieldNumbers[i]] = false; } }
/** * Method to load all unloaded fields in the FetchPlan. Recurses through the FetchPlan objects and * loads fields of sub-objects where needed. Used as a precursor to detaching objects at commit * since fields can't be loaded during the postCommit phase when the detach actually happens. * * @param state The FetchPlan state */ public void loadFieldsInFetchPlan(FetchPlanState state) { if ((flags & FLAG_LOADINGFPFIELDS) != 0) { // Already in the process of loading fields in this class so skip return; } flags |= FLAG_LOADINGFPFIELDS; try { // Load unloaded FetchPlan fields of this object loadUnloadedFieldsInFetchPlan(); // Recurse through all fields and do the same int[] fieldNumbers = ClassUtils.getFlagsSetTo(loadedFields, cmd.getAllMemberPositions(), true); if (fieldNumbers != null && fieldNumbers.length > 0) { // TODO Fix this to just access the fields of the FieldManager yet this actually does a // replaceField replaceFields( fieldNumbers, new LoadFieldManager(this, cmd.getSCOMutableMemberFlags(), myFP, state)); updateLevel2CacheForFields(fieldNumbers); } } finally { flags &= ~FLAG_LOADINGFPFIELDS; } }
/** * This method should be called only if it has been determined that field schema should be created * (or deleted). Create the {@link CustomField} for the metadata API to use during deploy * * @param cmd the class metadata for the entity * @param storeManager the store manager */ public void createCustomFields(AbstractClassMetaData cmd, ForceStoreManager storeManager) { synchronized (cmd) { try { if (cmd.isEmbeddedOnly() || PersistenceUtils.isReadOnlySchema(cmd, false)) return; ForceManagedConnection mconn = storeManager.createConnection(); try { ForceColumnMetaData cols = new ForceColumnMetaData(cmd, tableImpl, storeManager); cols.createFieldSchema(mconn.getNamespace()); if (customObject == null) { createCustomObjectStub(); } cols.addFieldsToObject(customObject); } catch (NucleusException ce) { throw ce; } catch (Exception e) { throw new NucleusException(e.getMessage(), e); } finally { mconn.close(); } } catch (Exception e) { throw new NucleusUserException( "Exception during initialisation of metadata for " + cmd.getFullClassName(), e); } } }
/** Convenience method to mark PK fields as loaded (if using app id). */ protected void markPKFieldsAsLoaded() { if (cmd.getIdentityType() == IdentityType.APPLICATION) { int[] pkPositions = cmd.getPKMemberPositions(); for (int i = 0; i < pkPositions.length; i++) { loadedFields[pkPositions[i]] = true; } } }
/** * Convenience method to find the element information relating to the element type. Used * specifically for the "element-type" of a collection/array to find the elements which have table * information. * * @return Element information relating to the element type */ protected ElementInfo[] getElementInformationForClass() { ElementInfo[] info = null; DatastoreClass rootTbl; String[] clsNames; if (clr.classForName(elementType).isInterface()) { // Collection<interface>, so find implementations of the interface clsNames = storeMgr .getNucleusContext() .getMetaDataManager() .getClassesImplementingInterface(elementType, clr); rootTbl = null; } else { clsNames = new String[] {elementType}; rootTbl = storeMgr.getDatastoreClass(elementType, clr); } if (rootTbl == null) { if (clr.classForName(elementType).isInterface()) { info = new ElementInfo[clsNames.length]; for (int i = 0; i < clsNames.length; i++) { AbstractClassMetaData implCmd = storeMgr.getMetaDataManager().getMetaDataForClass(clsNames[i], clr); DatastoreClass table = storeMgr.getDatastoreClass(clsNames[i], clr); info[i] = new ElementInfo(implCmd, table); } } else { AbstractClassMetaData[] subclassCmds = storeMgr.getClassesManagingTableForClass(emd, clr); info = new ElementInfo[subclassCmds.length]; for (int i = 0; i < subclassCmds.length; i++) { DatastoreClass table = storeMgr.getDatastoreClass(subclassCmds[i].getFullClassName(), clr); info[i] = new ElementInfo(subclassCmds[i], table); } } } else { info = new ElementInfo[clsNames.length]; for (int i = 0; i < clsNames.length; i++) { AbstractClassMetaData cmd = storeMgr.getNucleusContext().getMetaDataManager().getMetaDataForClass(clsNames[i], clr); DatastoreClass table = storeMgr.getDatastoreClass(cmd.getFullClassName(), clr); info[i] = new ElementInfo(cmd, table); } } return info; }
// TODO Remove this when we support subclasses from a query @Override public Extent getExtent(ExecutionContext ec, Class c, boolean subclasses) { AbstractClassMetaData cmd = getMetaDataManager().getMetaDataForClass(c, ec.getClassLoaderResolver()); validateMetaDataForClass(cmd); if (!cmd.isRequiresExtent()) { throw new NoExtentException(c.getName()); } if (!getBooleanProperty(GET_EXTENT_CAN_RETURN_SUBCLASSES_PROPERTY, false)) { subclasses = false; } // In order to avoid breaking existing apps I'm hard-coding subclasses to // be false. This breaks spec compliance since the no-arg overload of // PersistenceManager.getExtent() is supposed to return subclasses. return new DefaultCandidateExtent(ec, c, subclasses, cmd); }
/** * Perform appengine-specific validation on the provided meta data. Also generates cached * information that is needed by persistence. * * @param cmd The metadata to validate. */ public void validateMetaDataForClass(AbstractClassMetaData cmd) { // Only validate each meta data once if (validatedClasses.add(cmd.getFullClassName())) { if (getBooleanProperty(VALIDATE_METADATA, true)) { // Only do if the persistence property is not set to false metadataValidator.validate(cmd); } AbstractMemberMetaData parentPkMmd = MetaDataUtils.getParentPkMemberMetaDataForClass( cmd, getMetaDataManager(), getNucleusContext().getClassLoaderResolver(cmd.getClass().getClassLoader())); if (parentPkMmd != null) { parentMemberMetaDataByClass.put(cmd.getFullClassName(), parentPkMmd); } } }
/** * Convenience accessor for the names of the fields that are loaded. * * @return Names of the loaded fields */ public String[] getLoadedFieldNames() { int[] loadedFieldNumbers = ClassUtils.getFlagsSetTo(loadedFields, true); if (loadedFieldNumbers != null && loadedFieldNumbers.length > 0) { String[] loadedFieldNames = new String[loadedFieldNumbers.length]; for (int i = 0; i < loadedFieldNumbers.length; i++) { loadedFieldNames[i] = cmd.getMetaDataForManagedMemberAtAbsolutePosition(loadedFieldNumbers[i]).getName(); } return loadedFieldNames; } return null; }
@Override public FieldManager getFieldManagerForResultProcessing( ExecutionContext ec, Object resultSet, StatementClassMapping resultMappings, AbstractClassMetaData cmd) { Class<?> cls = ec.getClassLoaderResolver().classForName(cmd.getFullClassName()); Object internalKey = EntityUtils.idToInternalKey(ec, cls, resultSet, true); // Need to provide this to the field manager in the form of the pk // of the type: Key, Long, encoded String, or unencoded String return new KeyOnlyFieldManager(internalKey); }
/** * Convenience accessor for the names of the fields that are dirty. * * @return Names of the dirty fields */ public String[] getDirtyFieldNames() { int[] dirtyFieldNumbers = ClassUtils.getFlagsSetTo(dirtyFields, true); if (dirtyFieldNumbers != null && dirtyFieldNumbers.length > 0) { String[] dirtyFieldNames = new String[dirtyFieldNumbers.length]; for (int i = 0; i < dirtyFieldNumbers.length; i++) { dirtyFieldNames[i] = cmd.getMetaDataForManagedMemberAtAbsolutePosition(dirtyFieldNumbers[i]).getName(); } return dirtyFieldNames; } return null; }
/* (non-Javadoc) * @see org.datanucleus.store.fieldmanager.AbstractFieldManager#fetchObjectField(int) */ @Override public Object fetchObjectField(int fieldNumber) { ClassLoaderResolver clr = ec.getClassLoaderResolver(); AbstractMemberMetaData mmd = cmd.getMetaDataForManagedMemberAtAbsolutePosition(fieldNumber); RelationType relationType = mmd.getRelationType(clr); EmbeddedMetaData embmd = mmds.get(0).getEmbeddedMetaData(); if (mmds.size() == 1 && embmd != null && embmd.getOwnerMember() != null && embmd.getOwnerMember().equals(mmd.getName())) { // Special case of this being a link back to the owner. TODO Repeat this for nested and their // owners ObjectProvider[] ownerOps = ec.getOwnersForEmbeddedObjectProvider(op); return (ownerOps != null && ownerOps.length > 0 ? ownerOps[0].getObject() : null); } if (relationType != RelationType.NONE && MetaDataUtils.getInstance() .isMemberEmbedded(ec.getMetaDataManager(), clr, mmd, relationType, null)) { // Embedded field if (RelationType.isRelationSingleValued(relationType)) { // TODO Cater for null value detection List<AbstractMemberMetaData> embMmds = new ArrayList<AbstractMemberMetaData>(mmds); embMmds.add(mmd); AbstractClassMetaData embCmd = ec.getMetaDataManager().getMetaDataForClass(mmd.getType(), clr); ObjectProvider embOP = ec.getNucleusContext() .getObjectProviderFactory() .newForEmbedded(ec, embCmd, op, fieldNumber); FieldManager ffm = new FetchEmbeddedFieldManager(embOP, result, embMmds, table); embOP.replaceFields(embCmd.getAllMemberPositions(), ffm); return embOP.getObject(); } } return fetchNonEmbeddedObjectField(mmd, relationType, clr); }
private static void addColumnsToScanForEmbeddedMember( Scan scan, List<AbstractMemberMetaData> embMmds, Table table, ExecutionContext ec) { AbstractMemberMetaData lastMmd = embMmds.get(embMmds.size() - 1); ClassLoaderResolver clr = ec.getClassLoaderResolver(); AbstractClassMetaData embCmd = ec.getMetaDataManager().getMetaDataForClass(lastMmd.getTypeName(), clr); int[] embMmdPosns = embCmd.getAllMemberPositions(); for (int i = 0; i < embMmdPosns.length; i++) { AbstractMemberMetaData embMmd = embCmd.getMetaDataForManagedMemberAtAbsolutePosition(i); List<AbstractMemberMetaData> subEmbMmds = new ArrayList<AbstractMemberMetaData>(embMmds); subEmbMmds.add(embMmd); RelationType relationType = embMmd.getRelationType(clr); MemberColumnMapping mapping = table.getMemberColumnMappingForEmbeddedMember(subEmbMmds); if (RelationType.isRelationSingleValued(relationType)) { addColumnsToScanForEmbeddedMember(scan, subEmbMmds, table, ec); } else { String familyName = HBaseUtils.getFamilyNameForColumn(mapping.getColumn(0)); String qualifName = HBaseUtils.getQualifierNameForColumn(mapping.getColumn(0)); scan.addColumn(familyName.getBytes(), qualifName.getBytes()); } } }
/** Method to (re)connect the provider to the specified ExecutionContext and object type. */ public void connect(ExecutionContext ec, AbstractClassMetaData cmd) { int fieldCount = cmd.getMemberCount(); this.cmd = cmd; this.dirtyFields = new boolean[fieldCount]; this.loadedFields = new boolean[fieldCount]; this.dirty = false; this.myEC = ec; this.myFP = myEC.getFetchPlan().getFetchPlanForClass(cmd); this.lock = new ReentrantLock(); this.lockMode = LockManager.LOCK_MODE_NONE; this.savedFlags = 0; this.savedLoadedFields = null; this.objectType = 0; this.activity = ActivityState.NONE; this.myVersion = null; this.transactionalVersion = null; this.persistenceFlags = 0; }
/** * Convenience accessor to return the field numbers for the input loaded and dirty field arrays. * * @param loadedFields Fields that were detached with the object * @param dirtyFields Fields that have been modified while detached * @return The field numbers of loaded or dirty fields */ protected int[] getFieldNumbersOfLoadedOrDirtyFields( boolean[] loadedFields, boolean[] dirtyFields) { // Find the number of fields that are loaded or dirty int numFields = 0; for (int i = 0; i < loadedFields.length; i++) { if (loadedFields[i] || dirtyFields[i]) { numFields++; } } int[] fieldNumbers = new int[numFields]; int n = 0; int[] allFieldNumbers = cmd.getAllMemberPositions(); for (int i = 0; i < loadedFields.length; i++) { if (loadedFields[i] || dirtyFields[i]) { fieldNumbers[n++] = allFieldNumbers[i]; } } return fieldNumbers; }
/** * Method to return an expression for Map.containsValue using INNER JOIN to the element. This is * only for use when there are no "!containsValue" and no "OR" operations. Creates SQL by adding * INNER JOIN to the join table (where it exists), and also to the value table adding an AND * condition on the value (with value of the valueExpr). Returns a BooleanExpression "TRUE" (since * the INNER JOIN will guarantee if the value is contained of not). * * @param mapExpr Map expression * @param valExpr Expression for the value * @return Contains expression */ protected SQLExpression containsAsInnerJoin(MapExpression mapExpr, SQLExpression valExpr) { boolean valIsUnbound = (valExpr instanceof UnboundExpression); String varName = null; String valAlias = null; if (valIsUnbound) { varName = ((UnboundExpression) valExpr).getVariableName(); NucleusLogger.QUERY.debug( "map.containsValue(" + valExpr + ") binding unbound variable " + varName + " using INNER JOIN"); // TODO What if the variable is declared as a subtype, handle this see // CollectionContainsMethod } else if (!stmt.getQueryGenerator().hasExplicitJoins()) { JoinType joinType = stmt.getJoinTypeForTable(valExpr.getSQLTable()); if (joinType == JoinType.CROSS_JOIN) { // Value is currently joined via CROSS JOIN, so remove it (and use INNER JOIN below) valAlias = stmt.removeCrossJoin(valExpr.getSQLTable()); valIsUnbound = true; NucleusLogger.QUERY.debug( "map.containsValue(" + valExpr + ") was previously bound as CROSS JOIN but changing to INNER JOIN"); } // TODO If owner is joined via CROSS JOIN and value is already present then remove CROSS JOIN // and join via INNER JOIN } RDBMSStoreManager storeMgr = stmt.getRDBMSManager(); MetaDataManager mmgr = storeMgr.getMetaDataManager(); AbstractMemberMetaData mmd = mapExpr.getJavaTypeMapping().getMemberMetaData(); AbstractClassMetaData valCmd = mmd.getMap().getValueClassMetaData(clr, mmgr); if (mmd.getMap().getMapType() == MapType.MAP_TYPE_JOIN) { // Map formed in join table - add join to join table, then to value table (if present) MapTable mapTbl = (MapTable) storeMgr.getTable(mmd); SQLTable joinSqlTbl = stmt.innerJoin( mapExpr.getSQLTable(), mapExpr.getSQLTable().getTable().getIdMapping(), mapTbl, null, mapTbl.getOwnerMapping(), null, null); if (valCmd != null) { if (valIsUnbound) { DatastoreClass valTbl = storeMgr.getDatastoreClass(valCmd.getFullClassName(), clr); SQLTable valSqlTbl = stmt.innerJoin( joinSqlTbl, mapTbl.getValueMapping(), valTbl, valAlias, valTbl.getIdMapping(), null, null); // Bind the variable in the QueryGenerator valExpr = exprFactory.newExpression(stmt, valSqlTbl, valSqlTbl.getTable().getIdMapping()); stmt.getQueryGenerator() .bindVariable(varName, valCmd, valExpr.getSQLTable(), valExpr.getJavaTypeMapping()); } else { // Add restrict to value SQLExpression valIdExpr = exprFactory.newExpression(stmt, joinSqlTbl, mapTbl.getValueMapping()); stmt.whereAnd(valIdExpr.eq(valExpr), true); } } else { if (valIsUnbound) { // Bind the variable in the QueryGenerator valExpr = exprFactory.newExpression(stmt, joinSqlTbl, mapTbl.getValueMapping()); stmt.getQueryGenerator() .bindVariable(varName, null, valExpr.getSQLTable(), valExpr.getJavaTypeMapping()); } else { // Add restrict to value SQLExpression valIdExpr = exprFactory.newExpression(stmt, joinSqlTbl, mapTbl.getValueMapping()); stmt.whereAnd(valIdExpr.eq(valExpr), true); } } } else if (mmd.getMap().getMapType() == MapType.MAP_TYPE_KEY_IN_VALUE) { // Map formed in value table - add join to value table DatastoreClass valTbl = storeMgr.getDatastoreClass(valCmd.getFullClassName(), clr); JavaTypeMapping ownerMapping = null; if (mmd.getMappedBy() != null) { ownerMapping = valTbl.getMemberMapping(valCmd.getMetaDataForMember(mmd.getMappedBy())); } else { ownerMapping = valTbl.getExternalMapping(mmd, MappingConsumer.MAPPING_TYPE_EXTERNAL_FK); } SQLTable valSqlTbl = stmt.innerJoin( mapExpr.getSQLTable(), mapExpr.getSQLTable().getTable().getIdMapping(), valTbl, valAlias, ownerMapping, null, null); if (valIsUnbound) { // Bind the variable in the QueryGenerator valExpr = exprFactory.newExpression(stmt, valSqlTbl, valTbl.getIdMapping()); stmt.getQueryGenerator() .bindVariable(varName, valCmd, valExpr.getSQLTable(), valExpr.getJavaTypeMapping()); } else { // Add restrict to value SQLExpression valIdExpr = exprFactory.newExpression(stmt, valSqlTbl, valTbl.getIdMapping()); stmt.whereAnd(valIdExpr.eq(valExpr), true); } } else if (mmd.getMap().getMapType() == MapType.MAP_TYPE_VALUE_IN_KEY) { // Map formed in key table - add join to key table then to value table AbstractClassMetaData keyCmd = mmd.getMap().getKeyClassMetaData(clr, mmgr); DatastoreClass keyTbl = storeMgr.getDatastoreClass(keyCmd.getFullClassName(), clr); AbstractMemberMetaData keyValMmd = keyCmd.getMetaDataForMember(mmd.getValueMetaData().getMappedBy()); JavaTypeMapping ownerMapping = null; if (mmd.getMappedBy() != null) { ownerMapping = keyTbl.getMemberMapping(keyCmd.getMetaDataForMember(mmd.getMappedBy())); } else { ownerMapping = keyTbl.getExternalMapping(mmd, MappingConsumer.MAPPING_TYPE_EXTERNAL_FK); } SQLTable keySqlTbl = stmt.innerJoin( mapExpr.getSQLTable(), mapExpr.getSQLTable().getTable().getIdMapping(), keyTbl, null, ownerMapping, null, null); if (valCmd != null) { DatastoreClass valTbl = storeMgr.getDatastoreClass(valCmd.getFullClassName(), clr); SQLTable valSqlTbl = stmt.innerJoin( keySqlTbl, keyTbl.getMemberMapping(keyValMmd), valTbl, valAlias, valTbl.getIdMapping(), null, null); if (valIsUnbound) { // Bind the variable in the QueryGenerator valExpr = exprFactory.newExpression(stmt, valSqlTbl, valTbl.getIdMapping()); stmt.getQueryGenerator() .bindVariable(varName, valCmd, valExpr.getSQLTable(), valExpr.getJavaTypeMapping()); } else { // Add restrict to value SQLExpression valIdExpr = exprFactory.newExpression(stmt, valSqlTbl, valTbl.getIdMapping()); stmt.whereAnd(valIdExpr.eq(valExpr), true); } } else { if (valIsUnbound) { // Bind the variable in the QueryGenerator valExpr = exprFactory.newExpression(stmt, keySqlTbl, keyTbl.getMemberMapping(keyValMmd)); stmt.getQueryGenerator() .bindVariable(varName, null, valExpr.getSQLTable(), valExpr.getJavaTypeMapping()); } else { // Add restrict to value SQLExpression valIdExpr = exprFactory.newExpression(stmt, keySqlTbl, keyTbl.getMemberMapping(keyValMmd)); stmt.whereAnd(valIdExpr.eq(valExpr), true); } } } JavaTypeMapping m = exprFactory.getMappingForType(boolean.class, true); return exprFactory.newLiteral(stmt, m, true).eq(exprFactory.newLiteral(stmt, m, true)); }
/** * Accessor for the metadata of the member of this class marked as "gae.parent-pk". * * @param cmd Metadata for the class * @return The member marked as "gae.parent-pk". */ public AbstractMemberMetaData getMetaDataForParentPK(AbstractClassMetaData cmd) { return parentMemberMetaDataByClass.get(cmd.getFullClassName()); }
/** Method called at the end of the class. */ public void visitEnd() { AbstractClassMetaData cmd = enhancer.getClassMetaData(); if (cmd.getPersistenceModifier() == ClassPersistenceModifier.PERSISTENCE_CAPABLE) { // Add any new fields List fields = enhancer.getFieldsList(); Iterator fieldsIter = fields.iterator(); while (fieldsIter.hasNext()) { ClassField field = (ClassField) fieldsIter.next(); if (field.getName().equals(enhancer.getNamer().getDetachedStateFieldName()) && hasDetachedState) { // No need to add this field since exists continue; } if (DataNucleusEnhancer.LOGGER.isDebugEnabled()) { DataNucleusEnhancer.LOGGER.debug( Localiser.msg("005021", ((Class) field.getType()).getName() + " " + field.getName())); } cv.visitField( field.getAccess(), field.getName(), Type.getDescriptor((Class) field.getType()), null, null); } if (!hasStaticInitialisation) { // Add a static initialisation block for the class since nothing added yet InitClass method = InitClass.getInstance(enhancer); method.initialise(cv); method.execute(); method.close(); } if (!hasDefaultConstructor && enhancer.hasOption(ClassEnhancer.OPTION_GENERATE_DEFAULT_CONSTRUCTOR)) { // Add a default constructor DefaultConstructor ctr = DefaultConstructor.getInstance(enhancer); ctr.initialise(cv); ctr.execute(); ctr.close(); } // Add any new methods List methods = enhancer.getMethodsList(); Iterator<ClassMethod> methodsIter = methods.iterator(); while (methodsIter.hasNext()) { ClassMethod method = methodsIter.next(); method.initialise(cv); method.execute(); method.close(); } if (Serializable.class.isAssignableFrom(enhancer.getClassBeingEnhanced())) { // Class is Serializable if (!hasSerialVersionUID) { // Needs "serialVersionUID" field Long uid = null; try { uid = (Long) AccessController.doPrivileged( new PrivilegedAction() { public Object run() { return Long.valueOf( ObjectStreamClass.lookup(enhancer.getClassBeingEnhanced()) .getSerialVersionUID()); } }); } catch (Throwable e) { DataNucleusEnhancer.LOGGER.warn(StringUtils.getStringFromStackTrace(e)); } ClassField cf = new ClassField( enhancer, enhancer.getNamer().getSerialVersionUidFieldName(), Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC | Opcodes.ACC_FINAL, long.class, uid); if (DataNucleusEnhancer.LOGGER.isDebugEnabled()) { DataNucleusEnhancer.LOGGER.debug( Localiser.msg("005021", ((Class) cf.getType()).getName() + " " + cf.getName())); } cv.visitField( cf.getAccess(), cf.getName(), Type.getDescriptor((Class) cf.getType()), null, cf.getInitialValue()); } // The dnPreSerialize method need be called only once for a persistent instance. The // writeObject method in the least-derived // pc class that implements Serializable in the inheritance hierarchy needs to be modified // or generated to call it. if (cmd.getSuperAbstractClassMetaData() == null && !hasWriteObject) { // User hasn't provided their own writeObject, so provide the default but with a call to // dnPreSerialize first ClassMethod method = WriteObject.getInstance(enhancer); method.initialise(cv); method.execute(); method.close(); } } // Add dnGetXXX, dnSetXXX for each of the (managed) fields/properties AbstractMemberMetaData[] fmds = cmd.getManagedMembers(); for (int i = 0; i < fmds.length; i++) { if (fmds[i].getPersistenceModifier() == FieldPersistenceModifier.NONE) { // Field/Property is not persistent so ignore continue; } byte persistenceFlags = fmds[i].getPersistenceFlags(); ClassMethod getMethod = null; ClassMethod setMethod = null; if (fmds[i] instanceof PropertyMetaData) { // dnGetXXX, dnSetXXX for property are generated when processing existing getXXX, setXXX // methods } else { // Generate dnGetXXX, dnSetXXX for field if ((persistenceFlags & Persistable.MEDIATE_READ) == Persistable.MEDIATE_READ) { getMethod = new GetViaMediate(enhancer, fmds[i]); } else if ((persistenceFlags & Persistable.CHECK_READ) == Persistable.CHECK_READ) { getMethod = new GetViaCheck(enhancer, fmds[i]); } else { getMethod = new GetNormal(enhancer, fmds[i]); } if ((persistenceFlags & Persistable.MEDIATE_WRITE) == Persistable.MEDIATE_WRITE) { setMethod = new SetViaMediate(enhancer, fmds[i]); } else if ((persistenceFlags & Persistable.CHECK_WRITE) == Persistable.CHECK_WRITE) { setMethod = new SetViaCheck(enhancer, fmds[i]); } else { setMethod = new SetNormal(enhancer, fmds[i]); } } if (getMethod != null) { getMethod.initialise(cv); getMethod.execute(); getMethod.close(); } if (setMethod != null) { setMethod.initialise(cv); setMethod.execute(); setMethod.close(); } } } cv.visitEnd(); }
/** * Method to return a statement selecting the candidate table(s) required to cover all possible * types for this candidates inheritance strategy. * * @param storeMgr RDBMS StoreManager * @param parentStmt Parent statement (if there is one) * @param cmd Metadata for the class * @param clsMapping Mapping for the results of the statement * @param ec ExecutionContext * @param candidateCls Candidate class * @param subclasses Whether to create a statement for subclasses of the candidate too * @param result The result clause * @param candidateAlias alias for the candidate (if any) * @param candidateTableGroupName TableGroup name for the candidate (if any) * @return The SQLStatement * @throws NucleusException if there are no tables for concrete classes in this query (hence would * return null) */ public static SQLStatement getStatementForCandidates( RDBMSStoreManager storeMgr, SQLStatement parentStmt, AbstractClassMetaData cmd, StatementClassMapping clsMapping, ExecutionContext ec, Class candidateCls, boolean subclasses, String result, String candidateAlias, String candidateTableGroupName) { SQLStatement stmt = null; DatastoreIdentifier candidateAliasId = null; if (candidateAlias != null) { candidateAliasId = storeMgr.getIdentifierFactory().newTableIdentifier(candidateAlias); } ClassLoaderResolver clr = ec.getClassLoaderResolver(); List<DatastoreClass> candidateTables = new ArrayList<DatastoreClass>(); if (cmd.getInheritanceMetaData().getStrategy() == InheritanceStrategy.COMPLETE_TABLE) { DatastoreClass candidateTable = storeMgr.getDatastoreClass(cmd.getFullClassName(), clr); if (candidateTable != null) { candidateTables.add(candidateTable); } if (subclasses) { Collection<String> subclassNames = storeMgr.getSubClassesForClass(cmd.getFullClassName(), subclasses, clr); if (subclassNames != null) { Iterator<String> subclassIter = subclassNames.iterator(); while (subclassIter.hasNext()) { String subclassName = subclassIter.next(); DatastoreClass tbl = storeMgr.getDatastoreClass(subclassName, clr); if (tbl != null) { candidateTables.add(tbl); } } } } Iterator<DatastoreClass> iter = candidateTables.iterator(); int maxClassNameLength = cmd.getFullClassName().length(); while (iter.hasNext()) { DatastoreClass cls = iter.next(); String className = cls.getType(); if (className.length() > maxClassNameLength) { maxClassNameLength = className.length(); } } iter = candidateTables.iterator(); while (iter.hasNext()) { DatastoreClass cls = iter.next(); SQLStatement tblStmt = new SQLStatement(parentStmt, storeMgr, cls, candidateAliasId, candidateTableGroupName); tblStmt.setClassLoaderResolver(clr); tblStmt.setCandidateClassName(cls.getType()); // Add SELECT of dummy column accessible as "NUCLEUS_TYPE" containing the classname JavaTypeMapping m = storeMgr.getMappingManager().getMapping(String.class); String nuctypeName = cls.getType(); if (maxClassNameLength > nuctypeName.length()) { nuctypeName = StringUtils.leftAlignedPaddedString(nuctypeName, maxClassNameLength); } StringLiteral lit = new StringLiteral(tblStmt, m, nuctypeName, null); tblStmt.select(lit, UnionStatementGenerator.NUC_TYPE_COLUMN); if (stmt == null) { stmt = tblStmt; } else { stmt.union(tblStmt); } } if (clsMapping != null) { clsMapping.setNucleusTypeColumnName(UnionStatementGenerator.NUC_TYPE_COLUMN); } } else { // "new-table", "superclass-table", "subclass-table" List<Class> candidateClasses = new ArrayList<Class>(); if (ClassUtils.isReferenceType(candidateCls)) { // Persistent interface, so find all persistent implementations String[] clsNames = storeMgr .getNucleusContext() .getMetaDataManager() .getClassesImplementingInterface(candidateCls.getName(), clr); for (int i = 0; i < clsNames.length; i++) { Class cls = clr.classForName(clsNames[i]); DatastoreClass table = storeMgr.getDatastoreClass(clsNames[i], clr); candidateClasses.add(cls); candidateTables.add(table); AbstractClassMetaData implCmd = storeMgr.getNucleusContext().getMetaDataManager().getMetaDataForClass(cls, clr); if (implCmd.getIdentityType() != cmd.getIdentityType()) { throw new NucleusUserException( "You are querying an interface (" + cmd.getFullClassName() + ") " + "yet one of its implementations (" + implCmd.getFullClassName() + ") " + " uses a different identity type!"); } else if (cmd.getIdentityType() == IdentityType.APPLICATION) { if (cmd.getPKMemberPositions().length != implCmd.getPKMemberPositions().length) { throw new NucleusUserException( "You are querying an interface (" + cmd.getFullClassName() + ") " + "yet one of its implementations (" + implCmd.getFullClassName() + ") " + " has a different number of PK members!"); } } } } else { DatastoreClass candidateTable = storeMgr.getDatastoreClass(cmd.getFullClassName(), clr); if (candidateTable != null) { // Candidate has own table candidateClasses.add(candidateCls); candidateTables.add(candidateTable); } else { // Candidate stored in subclass tables AbstractClassMetaData[] cmds = storeMgr.getClassesManagingTableForClass(cmd, clr); if (cmds != null && cmds.length > 0) { for (int i = 0; i < cmds.length; i++) { DatastoreClass table = storeMgr.getDatastoreClass(cmds[i].getFullClassName(), clr); Class cls = clr.classForName(cmds[i].getFullClassName()); candidateClasses.add(cls); candidateTables.add(table); } } else { throw new UnsupportedOperationException( "No tables for query of " + cmd.getFullClassName()); } } } for (int i = 0; i < candidateTables.size(); i++) { DatastoreClass tbl = candidateTables.get(i); Class cls = candidateClasses.get(i); StatementGenerator stmtGen = null; if (tbl.getDiscriminatorMapping(true) != null || QueryUtils.resultHasOnlyAggregates(result)) { // Either has a discriminator, or only selecting aggregates so need single select stmtGen = new DiscriminatorStatementGenerator( storeMgr, clr, cls, subclasses, candidateAliasId, candidateTableGroupName); stmtGen.setOption(StatementGenerator.OPTION_RESTRICT_DISCRIM); } else { stmtGen = new UnionStatementGenerator( storeMgr, clr, cls, subclasses, candidateAliasId, candidateTableGroupName); if (result == null) { // Returning one row per candidate so include distinguisher column stmtGen.setOption(StatementGenerator.OPTION_SELECT_NUCLEUS_TYPE); clsMapping.setNucleusTypeColumnName(UnionStatementGenerator.NUC_TYPE_COLUMN); } } stmtGen.setParentStatement(parentStmt); SQLStatement tblStmt = stmtGen.getStatement(); if (stmt == null) { stmt = tblStmt; } else { stmt.union(tblStmt); } } } return stmt; }
public DiscriminatorStrategy getDiscriminatorStrategy() { return cmd.getDiscriminatorStrategyForTable(); }
/** * Utility that does a discriminator candidate query for the specified candidate and subclasses * and returns the class name of the instance that has the specified identity (if any). * * @param storeMgr RDBMS StoreManager * @param ec execution context * @param id The id * @param cmd Metadata for the root candidate class * @return Name of the class with this identity (or null if none found) */ public static String getClassNameForIdUsingDiscriminator( RDBMSStoreManager storeMgr, ExecutionContext ec, Object id, AbstractClassMetaData cmd) { // Check for input error if (cmd == null || id == null) { return null; } SQLExpressionFactory exprFactory = storeMgr.getSQLExpressionFactory(); ClassLoaderResolver clr = ec.getClassLoaderResolver(); DatastoreClass primaryTable = storeMgr.getDatastoreClass(cmd.getFullClassName(), clr); // Form the query to find which one of these classes has the instance with this id DiscriminatorStatementGenerator stmtGen = new DiscriminatorStatementGenerator( storeMgr, clr, clr.classForName(cmd.getFullClassName()), true, null, null); stmtGen.setOption(SelectStatementGenerator.OPTION_RESTRICT_DISCRIM); SelectStatement sqlStmt = stmtGen.getStatement(); // Select the discriminator JavaTypeMapping discrimMapping = primaryTable.getDiscriminatorMapping(true); SQLTable discrimSqlTbl = SQLStatementHelper.getSQLTableForMappingOfTable( sqlStmt, sqlStmt.getPrimaryTable(), discrimMapping); sqlStmt.select(discrimSqlTbl, discrimMapping, null); // Restrict to this id JavaTypeMapping idMapping = primaryTable.getIdMapping(); JavaTypeMapping idParamMapping = new PersistableIdMapping((PersistableMapping) idMapping); SQLExpression sqlFldExpr = exprFactory.newExpression(sqlStmt, sqlStmt.getPrimaryTable(), idMapping); SQLExpression sqlFldVal = exprFactory.newLiteralParameter(sqlStmt, idParamMapping, id, "ID"); sqlStmt.whereAnd(sqlFldExpr.eq(sqlFldVal), true); // Perform the query try { ManagedConnection mconn = storeMgr.getConnection(ec); SQLController sqlControl = storeMgr.getSQLController(); if (ec.getSerializeReadForClass(cmd.getFullClassName())) { sqlStmt.addExtension(SQLStatement.EXTENSION_LOCK_FOR_UPDATE, true); } try { PreparedStatement ps = SQLStatementHelper.getPreparedStatementForSQLStatement(sqlStmt, ec, mconn, null, null); String statement = sqlStmt.getSQLText().toSQL(); try { ResultSet rs = sqlControl.executeStatementQuery(ec, mconn, statement, ps); try { if (rs != null) { while (rs.next()) { DiscriminatorMetaData dismd = discrimMapping.getTable().getDiscriminatorMetaData(); return RDBMSQueryUtils.getClassNameFromDiscriminatorResultSetRow( discrimMapping, dismd, rs, ec); } } } finally { rs.close(); } } finally { sqlControl.closeStatement(mconn, ps); } } finally { mconn.release(); } } catch (SQLException sqe) { NucleusLogger.DATASTORE.error("Exception thrown on querying of discriminator for id", sqe); throw new NucleusDataStoreException(sqe.toString(), sqe); } return null; }
/** * Utility that does a union candidate query for the specified candidate(s) and subclasses and * returns the class name of the instance that has the specified identity (if any). * * @param storeMgr RDBMS StoreManager * @param ec execution context * @param id The id * @param rootCmds Metadata for the classes at the root * @return Name of the class with this identity (or null if none found) */ public static String getClassNameForIdUsingUnion( RDBMSStoreManager storeMgr, ExecutionContext ec, Object id, List<AbstractClassMetaData> rootCmds) { // Check for input error if (rootCmds == null || rootCmds.isEmpty() || id == null) { return null; } SQLExpressionFactory exprFactory = storeMgr.getSQLExpressionFactory(); ClassLoaderResolver clr = ec.getClassLoaderResolver(); // Form a query UNIONing all possible root candidates (and their subclasses) Iterator<AbstractClassMetaData> rootCmdIter = rootCmds.iterator(); AbstractClassMetaData sampleCmd = null; // Metadata for sample class in the tree so we can check if needs locking SelectStatement sqlStmtMain = null; while (rootCmdIter.hasNext()) { AbstractClassMetaData rootCmd = rootCmdIter.next(); DatastoreClass rootTbl = storeMgr.getDatastoreClass(rootCmd.getFullClassName(), clr); if (rootTbl == null) { // Class must be using "subclass-table" (no table of its own) so find where it is AbstractClassMetaData[] subcmds = storeMgr.getClassesManagingTableForClass(rootCmd, clr); if (subcmds == null || subcmds.length == 0) { // No table for this class so ignore } else { for (int i = 0; i < subcmds.length; i++) { UnionStatementGenerator stmtGen = new UnionStatementGenerator( storeMgr, clr, clr.classForName(subcmds[i].getFullClassName()), true, null, null); stmtGen.setOption(SelectStatementGenerator.OPTION_SELECT_NUCLEUS_TYPE); if (sqlStmtMain == null) { sampleCmd = subcmds[i]; sqlStmtMain = stmtGen.getStatement(); // WHERE (object id) = ? JavaTypeMapping idMapping = sqlStmtMain.getPrimaryTable().getTable().getIdMapping(); JavaTypeMapping idParamMapping = new PersistableIdMapping((PersistableMapping) idMapping); SQLExpression fieldExpr = exprFactory.newExpression(sqlStmtMain, sqlStmtMain.getPrimaryTable(), idMapping); SQLExpression fieldVal = exprFactory.newLiteralParameter(sqlStmtMain, idParamMapping, id, "ID"); sqlStmtMain.whereAnd(fieldExpr.eq(fieldVal), true); } else { SelectStatement sqlStmt = stmtGen.getStatement(); // WHERE (object id) = ? JavaTypeMapping idMapping = sqlStmt.getPrimaryTable().getTable().getIdMapping(); JavaTypeMapping idParamMapping = new PersistableIdMapping((PersistableMapping) idMapping); SQLExpression fieldExpr = exprFactory.newExpression(sqlStmt, sqlStmt.getPrimaryTable(), idMapping); SQLExpression fieldVal = exprFactory.newLiteralParameter(sqlStmt, idParamMapping, id, "ID"); sqlStmt.whereAnd(fieldExpr.eq(fieldVal), true); sqlStmtMain.union(sqlStmt); } } } } else { UnionStatementGenerator stmtGen = new UnionStatementGenerator( storeMgr, clr, clr.classForName(rootCmd.getFullClassName()), true, null, null); stmtGen.setOption(SelectStatementGenerator.OPTION_SELECT_NUCLEUS_TYPE); if (sqlStmtMain == null) { sampleCmd = rootCmd; sqlStmtMain = stmtGen.getStatement(); // WHERE (object id) = ? JavaTypeMapping idMapping = sqlStmtMain.getPrimaryTable().getTable().getIdMapping(); JavaTypeMapping idParamMapping = new PersistableIdMapping((PersistableMapping) idMapping); SQLExpression fieldExpr = exprFactory.newExpression(sqlStmtMain, sqlStmtMain.getPrimaryTable(), idMapping); SQLExpression fieldVal = exprFactory.newLiteralParameter(sqlStmtMain, idParamMapping, id, "ID"); sqlStmtMain.whereAnd(fieldExpr.eq(fieldVal), true); } else { SelectStatement sqlStmt = stmtGen.getStatement(); // WHERE (object id) = ? JavaTypeMapping idMapping = sqlStmt.getPrimaryTable().getTable().getIdMapping(); JavaTypeMapping idParamMapping = new PersistableIdMapping((PersistableMapping) idMapping); SQLExpression fieldExpr = exprFactory.newExpression(sqlStmt, sqlStmt.getPrimaryTable(), idMapping); SQLExpression fieldVal = exprFactory.newLiteralParameter(sqlStmt, idParamMapping, id, "ID"); sqlStmt.whereAnd(fieldExpr.eq(fieldVal), true); sqlStmtMain.union(sqlStmt); } } } // Perform the query try { ManagedConnection mconn = storeMgr.getConnection(ec); SQLController sqlControl = storeMgr.getSQLController(); if (ec.getSerializeReadForClass(sampleCmd.getFullClassName())) { sqlStmtMain.addExtension(SQLStatement.EXTENSION_LOCK_FOR_UPDATE, true); } try { PreparedStatement ps = SQLStatementHelper.getPreparedStatementForSQLStatement( sqlStmtMain, ec, mconn, null, null); String statement = sqlStmtMain.getSQLText().toSQL(); try { ResultSet rs = sqlControl.executeStatementQuery(ec, mconn, statement, ps); try { if (rs != null) { while (rs.next()) { try { return rs.getString(UnionStatementGenerator.NUC_TYPE_COLUMN).trim(); } catch (SQLException sqle) { } } } } finally { rs.close(); } } finally { sqlControl.closeStatement(mconn, ps); } } finally { mconn.release(); } } catch (SQLException sqe) { NucleusLogger.DATASTORE.error("Exception with UNION statement", sqe); throw new NucleusDataStoreException(sqe.toString()); } return null; }
public String toString() { return "ElementInfo : [class=" + cmd.getFullClassName() + " table=" + table + "]"; }
protected static Object getObjectUsingNondurableIdForResult( final Result result, final AbstractClassMetaData cmd, final ExecutionContext ec, boolean ignoreCache, final int[] fpMembers, String tableName, StoreManager storeMgr, Table table) { if (cmd.hasDiscriminatorStrategy()) { // Check the class for this discriminator value String familyName = HBaseUtils.getFamilyNameForColumn(table.getDiscriminatorColumn()); String columnName = HBaseUtils.getQualifierNameForColumn(table.getDiscriminatorColumn()); Object discValue = new String(result.getValue(familyName.getBytes(), columnName.getBytes())); if (cmd.getDiscriminatorStrategy() == DiscriminatorStrategy.CLASS_NAME && !cmd.getFullClassName().equals(discValue)) { return null; } else if (cmd.getDiscriminatorStrategy() == DiscriminatorStrategy.VALUE_MAP && !cmd.getDiscriminatorValue().equals(discValue)) { return null; } } final FieldManager fm = new FetchFieldManager(ec, cmd, result, table); SCOID id = new SCOID(cmd.getFullClassName()); Object pc = ec.findObject( id, new FieldValues() { // ObjectProvider calls the fetchFields method public void fetchFields(ObjectProvider op) { op.replaceFields(fpMembers, fm); } public void fetchNonLoadedFields(ObjectProvider op) { op.replaceNonLoadedFields(fpMembers, fm); } public FetchPlan getFetchPlanForLoading() { return null; } }, null, ignoreCache, false); if (cmd.isVersioned()) { // Set the version on the object ObjectProvider op = ec.findObjectProvider(pc); Object version = null; VersionMetaData vermd = cmd.getVersionMetaDataForClass(); if (vermd.getFieldName() != null) { // Set the version from the field value AbstractMemberMetaData verMmd = cmd.getMetaDataForMember(vermd.getFieldName()); version = op.provideField(verMmd.getAbsoluteFieldNumber()); } else { // Get the surrogate version from the datastore version = HBaseUtils.getSurrogateVersionForObject(cmd, result, tableName, storeMgr); } op.setVersion(version); } if (result.getRow() != null) { ObjectProvider sm = ec.findObjectProvider(pc); sm.setAssociatedValue("HBASE_ROW_KEY", result.getRow()); } return pc; }
protected static Object getObjectUsingDatastoreIdForResult( final Result result, final AbstractClassMetaData cmd, final ExecutionContext ec, boolean ignoreCache, final int[] fpMembers, String tableName, StoreManager storeMgr, Table table) { if (cmd.hasDiscriminatorStrategy()) { // Check the class for this discriminator value String familyName = HBaseUtils.getFamilyNameForColumn(table.getDiscriminatorColumn()); String columnName = HBaseUtils.getQualifierNameForColumn(table.getDiscriminatorColumn()); Object discValue = new String(result.getValue(familyName.getBytes(), columnName.getBytes())); if (cmd.getDiscriminatorStrategy() == DiscriminatorStrategy.CLASS_NAME && !cmd.getFullClassName().equals(discValue)) { return null; } else if (cmd.getDiscriminatorStrategy() == DiscriminatorStrategy.VALUE_MAP && !cmd.getDiscriminatorValue().equals(discValue)) { return null; } } String dsidFamilyName = HBaseUtils.getFamilyNameForColumn(table.getDatastoreIdColumn()); String dsidColumnName = HBaseUtils.getQualifierNameForColumn(table.getDatastoreIdColumn()); Object id = null; try { byte[] bytes = result.getValue(dsidFamilyName.getBytes(), dsidColumnName.getBytes()); if (bytes != null) { ByteArrayInputStream bis = new ByteArrayInputStream(bytes); ObjectInputStream ois = new ObjectInputStream(bis); Object key = ois.readObject(); id = ec.getNucleusContext().getIdentityManager().getDatastoreId(cmd.getFullClassName(), key); ois.close(); bis.close(); } else { throw new NucleusException( "Retrieved identity for family=" + dsidFamilyName + " column=" + dsidColumnName + " IS NULL"); } } catch (Exception e) { throw new NucleusException(e.getMessage(), e); } final FieldManager fm = new FetchFieldManager(ec, cmd, result, table); Object pc = ec.findObject( id, new FieldValues() { // ObjectProvider calls the fetchFields method public void fetchFields(ObjectProvider op) { op.replaceFields(fpMembers, fm); } public void fetchNonLoadedFields(ObjectProvider op) { op.replaceNonLoadedFields(fpMembers, fm); } public FetchPlan getFetchPlanForLoading() { return null; } }, null, ignoreCache, false); if (cmd.isVersioned()) { // Set the version on the object ObjectProvider op = ec.findObjectProvider(pc); Object version = null; VersionMetaData vermd = cmd.getVersionMetaDataForClass(); if (vermd.getFieldName() != null) { // Set the version from the field value AbstractMemberMetaData verMmd = cmd.getMetaDataForMember(vermd.getFieldName()); version = op.provideField(verMmd.getAbsoluteFieldNumber()); } else { // Get the surrogate version from the datastore version = HBaseUtils.getSurrogateVersionForObject(cmd, result, tableName, storeMgr); } op.setVersion(version); } if (result.getRow() != null) { ObjectProvider sm = ec.findObjectProvider(pc); sm.setAssociatedValue("HBASE_ROW_KEY", result.getRow()); } return pc; }
/** * Convenience method to get all objects of the specified type. * * @param ec Execution Context * @param mconn Managed Connection * @param cmd Metadata for the type to return * @param ignoreCache Whether to ignore the cache * @param fp Fetch Plan * @param filter Optional filter for the candidates * @param storeMgr StoreManager in use * @return List of objects of the candidate type */ private static List getObjectsOfType( final ExecutionContext ec, final HBaseManagedConnection mconn, final AbstractClassMetaData cmd, boolean ignoreCache, FetchPlan fp, final Filter filter, final StoreManager storeMgr) { List results = new ArrayList(); if (!storeMgr.managesClass(cmd.getFullClassName())) { storeMgr.manageClasses(ec.getClassLoaderResolver(), cmd.getFullClassName()); } final Table table = storeMgr.getStoreDataForClass(cmd.getFullClassName()).getTable(); final String tableName = table.getName(); final int[] fpMembers = fp.getFetchPlanForClass(cmd).getMemberNumbers(); try { final ClassLoaderResolver clr = ec.getClassLoaderResolver(); Iterator<Result> it = (Iterator<Result>) AccessController.doPrivileged( new PrivilegedExceptionAction() { public Object run() throws Exception { Scan scan = new Scan(); if (filter != null) { scan.setFilter(filter); } // Retrieve all fetch-plan fields for (int i = 0; i < fpMembers.length; i++) { AbstractMemberMetaData mmd = cmd.getMetaDataForManagedMemberAtAbsolutePosition(fpMembers[i]); RelationType relationType = mmd.getRelationType(clr); if (relationType != RelationType.NONE && MetaDataUtils.getInstance() .isMemberEmbedded( ec.getMetaDataManager(), clr, mmd, relationType, null)) { if (RelationType.isRelationSingleValued(relationType)) { // 1-1 embedded List<AbstractMemberMetaData> embMmds = new ArrayList<AbstractMemberMetaData>(); embMmds.add(mmd); addColumnsToScanForEmbeddedMember(scan, embMmds, table, ec); } } else { Column col = table .getMemberColumnMappingForMember(mmd) .getColumn(0); // TODO Support multicol mapping byte[] familyName = HBaseUtils.getFamilyNameForColumn(col).getBytes(); byte[] qualifName = HBaseUtils.getQualifierNameForColumn(col).getBytes(); scan.addColumn(familyName, qualifName); } } VersionMetaData vermd = cmd.getVersionMetaDataForClass(); if (cmd.isVersioned() && vermd.getFieldName() == null) { // Add version column byte[] familyName = HBaseUtils.getFamilyNameForColumn(table.getVersionColumn()).getBytes(); byte[] qualifName = HBaseUtils.getQualifierNameForColumn(table.getVersionColumn()) .getBytes(); scan.addColumn(familyName, qualifName); } if (cmd.hasDiscriminatorStrategy()) { // Add discriminator column byte[] familyName = HBaseUtils.getFamilyNameForColumn(table.getDiscriminatorColumn()) .getBytes(); byte[] qualifName = HBaseUtils.getQualifierNameForColumn(table.getDiscriminatorColumn()) .getBytes(); scan.addColumn(familyName, qualifName); } if (cmd.getIdentityType() == IdentityType.DATASTORE) { // Add datastore identity column byte[] familyName = HBaseUtils.getFamilyNameForColumn(table.getDatastoreIdColumn()) .getBytes(); byte[] qualifName = HBaseUtils.getQualifierNameForColumn(table.getDatastoreIdColumn()) .getBytes(); scan.addColumn(familyName, qualifName); } HTableInterface htable = mconn.getHTable(tableName); ResultScanner scanner = htable.getScanner(scan); if (ec.getStatistics() != null) { // Add to statistics ec.getStatistics().incrementNumReads(); } Iterator<Result> it = scanner.iterator(); return it; } }); // Instantiate the objects if (cmd.getIdentityType() == IdentityType.APPLICATION) { while (it.hasNext()) { final Result result = it.next(); Object obj = getObjectUsingApplicationIdForResult( result, cmd, ec, ignoreCache, fpMembers, tableName, storeMgr, table); if (obj != null) { results.add(obj); } } } else if (cmd.getIdentityType() == IdentityType.DATASTORE) { while (it.hasNext()) { final Result result = it.next(); Object obj = getObjectUsingDatastoreIdForResult( result, cmd, ec, ignoreCache, fpMembers, tableName, storeMgr, table); if (obj != null) { results.add(obj); } } } else { while (it.hasNext()) { final Result result = it.next(); Object obj = getObjectUsingNondurableIdForResult( result, cmd, ec, ignoreCache, fpMembers, tableName, storeMgr, table); if (obj != null) { results.add(obj); } } } } catch (PrivilegedActionException e) { throw new NucleusDataStoreException(e.getMessage(), e.getCause()); } return results; }
public String getClassName() { return cmd.getFullClassName(); }
/** * Utility to create the application identity columns and mapping. Uses the id mapping of the * specified class table and copies the mappings and columns, whilst retaining the passed * preferences for column namings. This is used to copy the PK mappings of a superclass table so * we have the same PK. * * @param columnContainer The container of column MetaData with any namings * @param refTable The table that we use as reference * @param clr The ClassLoaderResolver * @param cmd The ClassMetaData */ final void addApplicationIdUsingClassTableId( ColumnMetaDataContainer columnContainer, DatastoreClass refTable, ClassLoaderResolver clr, AbstractClassMetaData cmd) { ColumnMetaData[] userdefinedCols = null; int nextUserdefinedCol = 0; if (columnContainer != null) { userdefinedCols = columnContainer.getColumnMetaData(); } pkMappings = new JavaTypeMapping[cmd.getPKMemberPositions().length]; for (int i = 0; i < cmd.getPKMemberPositions().length; i++) { AbstractMemberMetaData mmd = cmd.getMetaDataForManagedMemberAtAbsolutePosition(cmd.getPKMemberPositions()[i]); JavaTypeMapping mapping = refTable.getMemberMapping(mmd); if (mapping == null) { // probably due to invalid metadata defined by the user throw new NucleusUserException( "Cannot find mapping for field " + mmd.getFullFieldName() + " in table " + refTable.toString() + " " + StringUtils.collectionToString(refTable.getColumns())); } JavaTypeMapping masterMapping = storeMgr.getMappingManager().getMapping(clr.classForName(mapping.getType())); masterMapping.setMemberMetaData(mmd); // Update field info in mapping masterMapping.setTable(this); pkMappings[i] = masterMapping; // Loop through each id column in the reference table and add the same here // applying the required names from the columnContainer for (int j = 0; j < mapping.getNumberOfDatastoreMappings(); j++) { JavaTypeMapping m = masterMapping; Column refColumn = mapping.getDatastoreMapping(j).getColumn(); if (mapping instanceof PersistableMapping) { m = storeMgr .getMappingManager() .getMapping(clr.classForName(refColumn.getJavaTypeMapping().getType())); ((PersistableMapping) masterMapping).addJavaTypeMapping(m); } ColumnMetaData userdefinedColumn = null; if (userdefinedCols != null) { for (int k = 0; k < userdefinedCols.length; k++) { if (refColumn.getIdentifier().toString().equals(userdefinedCols[k].getTarget())) { userdefinedColumn = userdefinedCols[k]; break; } } if (userdefinedColumn == null && nextUserdefinedCol < userdefinedCols.length) { userdefinedColumn = userdefinedCols[nextUserdefinedCol++]; } } // Add this application identity column Column idColumn = null; if (userdefinedColumn != null) { // User has provided a name for this column // Currently we only use the column namings from the users definition but we could easily // take more of their details. idColumn = addColumn( refColumn.getStoredJavaType(), storeMgr .getIdentifierFactory() .newIdentifier(IdentifierType.COLUMN, userdefinedColumn.getName()), m, refColumn.getColumnMetaData()); } else { // No name provided so take same as superclass idColumn = addColumn( refColumn.getStoredJavaType(), refColumn.getIdentifier(), m, refColumn.getColumnMetaData()); } if (mapping.getDatastoreMapping(j).getColumn().getColumnMetaData() != null) { refColumn.copyConfigurationTo(idColumn); } idColumn.setPrimaryKey(); // Set the column type based on the field.getType() getStoreManager() .getMappingManager() .createDatastoreMapping(m, idColumn, refColumn.getJavaTypeMapping().getType()); } // Update highest field number if this is higher int absoluteFieldNumber = mmd.getAbsoluteFieldNumber(); if (absoluteFieldNumber > highestMemberNumber) { highestMemberNumber = absoluteFieldNumber; } } }
/** * Utility to create the datastore identity column and mapping. This is used in 2 modes. The first * is where we have a (primary) class table and we aren't creating the OID mapping as a FK to * another class. The second is where we have a (secondary) class table and we are creating the * OID mapping as a FK to the primary class. In the second case the refTable will be specified. * * @param columnMetaData The column MetaData for the datastore id * @param refTable Table used as a reference (if any) * @param cmd The MetaData for the class */ void addDatastoreId( ColumnMetaData columnMetaData, DatastoreClass refTable, AbstractClassMetaData cmd) { // Create the mapping, setting its table datastoreIDMapping = new DatastoreIdMapping(); datastoreIDMapping.setTable(this); datastoreIDMapping.initialize(storeMgr, cmd.getFullClassName()); // Create a ColumnMetaData in the container if none is defined ColumnMetaData colmd = null; if (columnMetaData == null) { colmd = new ColumnMetaData(); } else { colmd = columnMetaData; } if (colmd.getName() == null) { // Provide default column naming if none is defined if (refTable != null) { colmd.setName( storeMgr .getIdentifierFactory() .newColumnIdentifier( refTable.getIdentifier().getName(), this.storeMgr .getNucleusContext() .getTypeManager() .isDefaultEmbeddedType(DatastoreId.class), FieldRole.ROLE_OWNER, false) .getName()); } else { colmd.setName( storeMgr .getIdentifierFactory() .newColumnIdentifier( identifier.getName(), this.storeMgr .getNucleusContext() .getTypeManager() .isDefaultEmbeddedType(DatastoreId.class), FieldRole.ROLE_NONE, false) .getName()); } } // Add the datastore identity column as the PK Column idColumn = addColumn( DatastoreId.class.getName(), storeMgr.getIdentifierFactory().newIdentifier(IdentifierType.COLUMN, colmd.getName()), datastoreIDMapping, colmd); idColumn.setPrimaryKey(); // Set the identity column type based on the IdentityStrategy String strategyName = cmd.getIdentityMetaData().getValueStrategy().toString(); if (cmd.getIdentityMetaData().getValueStrategy().equals(IdentityStrategy.CUSTOM)) { strategyName = cmd.getIdentityMetaData().getValueStrategy().getCustomName(); } if (strategyName != null && IdentityStrategy.NATIVE.toString().equals(strategyName)) { strategyName = storeMgr.getStrategyForNative(cmd, -1); } // Check the value generator type being stored Class valueGeneratedType = Long.class; if (strategyName != null && IdentityStrategy.IDENTITY.toString().equals(strategyName)) { valueGeneratedType = dba.getAutoIncrementJavaTypeForType(valueGeneratedType); if (valueGeneratedType != Long.class) { NucleusLogger.DATASTORE_SCHEMA.debug( "Class " + cmd.getFullClassName() + " uses IDENTITY strategy and rather than using BIGINT " + " for the column type, using " + valueGeneratedType.getName() + " since the datastore requires that"); } } try { // Create generator so we can find the generated type // a). Try as unique generator first AbstractGenerator generator = (AbstractGenerator) storeMgr .getNucleusContext() .getPluginManager() .createExecutableExtension( "org.datanucleus.store_valuegenerator", new String[] {"name", "unique"}, new String[] {strategyName, "true"}, "class-name", new Class[] {String.class, Properties.class}, new Object[] {null, null}); if (generator == null) { // b). Try as datastore-specific generator generator = (AbstractGenerator) storeMgr .getNucleusContext() .getPluginManager() .createExecutableExtension( "org.datanucleus.store_valuegenerator", new String[] {"name", "datastore"}, new String[] {strategyName, storeMgr.getStoreManagerKey()}, "class-name", new Class[] {String.class, Properties.class}, new Object[] {null, null}); } try { if (generator != null) { ParameterizedType parameterizedType = (ParameterizedType) generator.getClass().getGenericSuperclass(); valueGeneratedType = (Class) parameterizedType.getActualTypeArguments()[0]; if (valueGeneratedType == null) { // Use getStorageClass method if available valueGeneratedType = (Class) generator.getClass().getMethod("getStorageClass").invoke(null); } } } catch (Exception e) { } } catch (Exception e) { NucleusLogger.VALUEGENERATION.warn( "Error obtaining generator for strategy=" + strategyName, e); } storeMgr .getMappingManager() .createDatastoreMapping(datastoreIDMapping, idColumn, valueGeneratedType.getName()); logMapping("DATASTORE_ID", datastoreIDMapping); // Handle any auto-increment requirement if (isObjectIdDatastoreAttributed()) { if (this instanceof DatastoreClass && ((DatastoreClass) this).isBaseDatastoreClass()) { // Only the base class can be autoincremented idColumn.setIdentity(true); } } // Check if auto-increment and that it is supported by this RDBMS if (idColumn.isIdentity() && !dba.supportsOption(DatastoreAdapter.IDENTITY_COLUMNS)) { throw new NucleusException( Localiser.msg("057020", cmd.getFullClassName(), "datastore-identity")) .setFatal(); } }
/** * Method to return an expression for Map.containsValue using a subquery "EXISTS". This is for use * when there are "!contains" or "OR" operations in the filter. Creates the following SQL, * * <ul> * <li><b>Map using join table</b> * <pre> * SELECT 1 FROM JOIN_TBL A0_SUB * WHERE A0_SUB.JOIN_OWN_ID = A0.ID AND A0_SUB.JOIN_VAL_ID = {valExpr} * </pre> * <li><b>Map with key stored in value</b> * <pre> * SELECT 1 FROM VAL_TABLE A0_SUB INNER JOIN KEY_TBL B0 ON ... * WHERE B0.JOIN_OWN_ID = A0.ID AND A0_SUB.ID = {valExpr} * </pre> * <li><b>Map of value stored in key</b> * <pre> * SELECT 1 FROM VAL_TABLE A0_SUB * WHERE A0_SUB.OWN_ID = A0.ID AND A0_SUB.ID = {valExpr} * </pre> * </ul> * * and returns a BooleanSubqueryExpression ("EXISTS (subquery)") * * @param mapExpr Map expression * @param valExpr Expression for the value * @return Contains expression */ protected SQLExpression containsAsSubquery(MapExpression mapExpr, SQLExpression valExpr) { boolean valIsUnbound = (valExpr instanceof UnboundExpression); String varName = null; if (valIsUnbound) { varName = ((UnboundExpression) valExpr).getVariableName(); NucleusLogger.QUERY.debug( "map.containsValue binding unbound variable " + varName + " using SUBQUERY"); // TODO What if the variable is declared as a subtype, handle this see // CollectionContainsMethod } RDBMSStoreManager storeMgr = stmt.getRDBMSManager(); MetaDataManager mmgr = storeMgr.getMetaDataManager(); AbstractMemberMetaData mmd = mapExpr.getJavaTypeMapping().getMemberMetaData(); AbstractClassMetaData valCmd = mmd.getMap().getValueClassMetaData(clr, mmgr); MapTable joinTbl = (MapTable) storeMgr.getTable(mmd); SQLStatement subStmt = null; if (mmd.getMap().getMapType() == MapType.MAP_TYPE_JOIN) { // JoinTable Map if (valCmd == null) { // Map<?, Non-PC> subStmt = new SQLStatement(stmt, storeMgr, joinTbl, null, null); subStmt.setClassLoaderResolver(clr); JavaTypeMapping oneMapping = storeMgr.getMappingManager().getMapping(Integer.class); subStmt.select(exprFactory.newLiteral(subStmt, oneMapping, 1), null); // Restrict to map owner JavaTypeMapping ownerMapping = ((JoinTable) joinTbl).getOwnerMapping(); SQLExpression ownerExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), ownerMapping); SQLExpression ownerIdExpr = exprFactory.newExpression( stmt, mapExpr.getSQLTable(), mapExpr.getSQLTable().getTable().getIdMapping()); subStmt.whereAnd(ownerExpr.eq(ownerIdExpr), true); if (valIsUnbound) { // Bind the variable in the QueryGenerator valExpr = exprFactory.newExpression( subStmt, subStmt.getPrimaryTable(), joinTbl.getValueMapping()); stmt.getQueryGenerator() .bindVariable(varName, null, valExpr.getSQLTable(), valExpr.getJavaTypeMapping()); } else { // Add restrict to value SQLExpression valIdExpr = exprFactory.newExpression( subStmt, subStmt.getPrimaryTable(), joinTbl.getValueMapping()); subStmt.whereAnd(valIdExpr.eq(valExpr), true); } } else { // Map<?, PC> DatastoreClass valTbl = storeMgr.getDatastoreClass(mmd.getMap().getValueType(), clr); subStmt = new SQLStatement(stmt, storeMgr, valTbl, null, null); subStmt.setClassLoaderResolver(clr); JavaTypeMapping oneMapping = storeMgr.getMappingManager().getMapping(Integer.class); subStmt.select(exprFactory.newLiteral(subStmt, oneMapping, 1), null); // Join to join table SQLTable joinSqlTbl = subStmt.innerJoin( subStmt.getPrimaryTable(), valTbl.getIdMapping(), joinTbl, null, joinTbl.getValueMapping(), null, null); // Restrict to map owner JavaTypeMapping ownerMapping = joinTbl.getOwnerMapping(); SQLExpression ownerExpr = exprFactory.newExpression(subStmt, joinSqlTbl, ownerMapping); SQLExpression ownerIdExpr = exprFactory.newExpression( stmt, mapExpr.getSQLTable(), mapExpr.getSQLTable().getTable().getIdMapping()); subStmt.whereAnd(ownerExpr.eq(ownerIdExpr), true); if (valIsUnbound) { // Bind the variable in the QueryGenerator valExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), valTbl.getIdMapping()); stmt.getQueryGenerator() .bindVariable(varName, valCmd, valExpr.getSQLTable(), valExpr.getJavaTypeMapping()); } else { // Add restrict to value SQLExpression valIdExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), valTbl.getIdMapping()); subStmt.whereAnd(valIdExpr.eq(valExpr), true); } } } else if (mmd.getMap().getMapType() == MapType.MAP_TYPE_KEY_IN_VALUE) { // Key stored in value table DatastoreClass valTbl = storeMgr.getDatastoreClass(mmd.getMap().getValueType(), clr); JavaTypeMapping ownerMapping = null; if (mmd.getMappedBy() != null) { ownerMapping = valTbl.getMemberMapping(valCmd.getMetaDataForMember(mmd.getMappedBy())); } else { ownerMapping = valTbl.getExternalMapping(mmd, MappingConsumer.MAPPING_TYPE_EXTERNAL_FK); } subStmt = new SQLStatement(stmt, storeMgr, valTbl, null, null); subStmt.setClassLoaderResolver(clr); JavaTypeMapping oneMapping = storeMgr.getMappingManager().getMapping(Integer.class); subStmt.select(exprFactory.newLiteral(subStmt, oneMapping, 1), null); // Restrict to map owner (on value table) SQLExpression ownerExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), ownerMapping); SQLExpression ownerIdExpr = exprFactory.newExpression( stmt, mapExpr.getSQLTable(), mapExpr.getSQLTable().getTable().getIdMapping()); subStmt.whereAnd(ownerExpr.eq(ownerIdExpr), true); if (valIsUnbound) { // Bind the variable in the QueryGenerator valExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), valTbl.getIdMapping()); stmt.getQueryGenerator() .bindVariable(varName, valCmd, valExpr.getSQLTable(), valExpr.getJavaTypeMapping()); } else { // Add restrict to value JavaTypeMapping valMapping = valTbl.getIdMapping(); SQLExpression valIdExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), valMapping); subStmt.whereAnd(valIdExpr.eq(valExpr), true); } } else if (mmd.getMap().getMapType() == MapType.MAP_TYPE_VALUE_IN_KEY) { AbstractClassMetaData keyCmd = mmd.getMap().getKeyClassMetaData(clr, mmgr); DatastoreClass keyTbl = storeMgr.getDatastoreClass(mmd.getMap().getKeyType(), clr); JavaTypeMapping ownerMapping = null; if (mmd.getMappedBy() != null) { ownerMapping = keyTbl.getMemberMapping(keyCmd.getMetaDataForMember(mmd.getMappedBy())); } else { ownerMapping = keyTbl.getExternalMapping(mmd, MappingConsumer.MAPPING_TYPE_EXTERNAL_FK); } AbstractMemberMetaData keyValMmd = keyCmd.getMetaDataForMember(mmd.getValueMetaData().getMappedBy()); if (valCmd == null) { subStmt = new SQLStatement(stmt, storeMgr, keyTbl, null, null); subStmt.setClassLoaderResolver(clr); JavaTypeMapping oneMapping = storeMgr.getMappingManager().getMapping(Integer.class); subStmt.select(exprFactory.newLiteral(subStmt, oneMapping, 1), null); // Restrict to map owner (on key table) SQLExpression ownerExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), ownerMapping); SQLExpression ownerIdExpr = exprFactory.newExpression( stmt, mapExpr.getSQLTable(), mapExpr.getSQLTable().getTable().getIdMapping()); subStmt.whereAnd(ownerExpr.eq(ownerIdExpr), true); if (valIsUnbound) { // Bind the variable in the QueryGenerator valExpr = exprFactory.newExpression( subStmt, subStmt.getPrimaryTable(), keyTbl.getMemberMapping(keyValMmd)); stmt.getQueryGenerator() .bindVariable(varName, null, valExpr.getSQLTable(), valExpr.getJavaTypeMapping()); } else { // Add restrict to value JavaTypeMapping valMapping = keyTbl.getMemberMapping(keyValMmd); SQLExpression valIdExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), valMapping); subStmt.whereAnd(valIdExpr.eq(valExpr), true); } } else { DatastoreClass valTbl = storeMgr.getDatastoreClass(mmd.getMap().getValueType(), clr); subStmt = new SQLStatement(stmt, storeMgr, valTbl, null, null); subStmt.setClassLoaderResolver(clr); JavaTypeMapping oneMapping = storeMgr.getMappingManager().getMapping(Integer.class); subStmt.select(exprFactory.newLiteral(subStmt, oneMapping, 1), null); // Join to key table SQLTable keySqlTbl = subStmt.innerJoin( subStmt.getPrimaryTable(), valTbl.getIdMapping(), keyTbl, null, keyTbl.getMemberMapping(keyValMmd), null, null); // Restrict to map owner (on key table) SQLExpression ownerExpr = exprFactory.newExpression(subStmt, keySqlTbl, ownerMapping); SQLExpression ownerIdExpr = exprFactory.newExpression( stmt, mapExpr.getSQLTable(), mapExpr.getSQLTable().getTable().getIdMapping()); subStmt.whereAnd(ownerExpr.eq(ownerIdExpr), true); if (valIsUnbound) { // Bind the variable in the QueryGenerator valExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), valTbl.getIdMapping()); stmt.getQueryGenerator() .bindVariable(varName, valCmd, valExpr.getSQLTable(), valExpr.getJavaTypeMapping()); } else { // Add restrict to value SQLExpression valIdExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), valTbl.getIdMapping()); subStmt.whereAnd(valIdExpr.eq(valExpr), true); } } } return new BooleanSubqueryExpression(stmt, "EXISTS", subStmt); }