/** 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 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;
  }
Ejemplo n.º 3
0
  /**
   * 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;
  }