@Override
  public List<Partition> getPartitionSpecsByFilterAndProjection(final Table table,
      GetProjectionsSpec partitionsProjectSpec,
      final GetPartitionsFilterSpec filterSpec) throws MetaException, NoSuchObjectException {
    List<String> fieldList = null;
    String inputIncludePattern = null;
    String inputExcludePattern = null;
    if (partitionsProjectSpec != null) {
      fieldList = partitionsProjectSpec.getFieldList();
      if (partitionsProjectSpec.isSetIncludeParamKeyPattern()) {
        inputIncludePattern = partitionsProjectSpec.getIncludeParamKeyPattern();
      }
      if (partitionsProjectSpec.isSetExcludeParamKeyPattern()) {
        inputExcludePattern = partitionsProjectSpec.getExcludeParamKeyPattern();
      }
    }
    if (fieldList == null || fieldList.isEmpty()) {
      // no fields are requested. Fallback to regular getPartitions implementation to return all the fields
      GetPartitionsArgs.GetPartitionsArgsBuilder argsBuilder = new GetPartitionsArgs.GetPartitionsArgsBuilder()
          .excludeParamKeyPattern(inputExcludePattern)
          .includeParamKeyPattern(inputIncludePattern);
      return getPartitionsInternal(table.getCatName(), table.getDbName(), table.getTableName(),
          true, true, argsBuilder.build());
    }

    // anonymous class below requires final String objects
    final String includeParamKeyPattern = inputIncludePattern;
    final String excludeParamKeyPattern = inputExcludePattern;

    return new GetListHelper<Partition>(table.getCatName(), table.getDbName(), table.getTableName(),
        fieldList, true, true) {
      private final SqlFilterForPushdown filter = new SqlFilterForPushdown();
      private ExpressionTree tree;

      @Override
      protected boolean canUseDirectSql(GetHelper<List<Partition>> ctx) throws MetaException {
        if (filterSpec.isSetFilterMode() && filterSpec.getFilterMode().equals(PartitionFilterMode.BY_EXPR)) {
          // if the filter mode is BY_EXPR initialize the filter and generate the expression tree
          // if there are more than one filter string we AND them together
          initExpressionTree();
          return directSql.generateSqlFilterForPushdown(table.getCatName(), table.getDbName(), table.getTableName(),
                  table.getPartitionKeys(), tree, null, filter);
        }
        // BY_VALUES and BY_NAMES are always supported
        return true;
      }

      private void initExpressionTree() throws MetaException {
        StringBuilder filterBuilder = new StringBuilder();
        int len = filterSpec.getFilters().size();
        List<String> filters = filterSpec.getFilters();
        for (int i = 0; i < len; i++) {
          filterBuilder.append('(');
          filterBuilder.append(filters.get(i));
          filterBuilder.append(')');
          if (i + 1 < len) {
            filterBuilder.append(" AND ");
          }
        }
        String filterStr = filterBuilder.toString();
        tree = PartFilterExprUtil.parseFilterTree(filterStr);
      }

      @Override
      protected List<Partition> getSqlResult(GetHelper<List<Partition>> ctx) throws MetaException {
        return directSql
            .getPartitionsUsingProjectionAndFilterSpec(ctx.getTable(), ctx.partitionFields,
                includeParamKeyPattern, excludeParamKeyPattern, filterSpec, filter);
      }

      @Override
      protected List<Partition> getJdoResult(
          GetHelper<List<Partition>> ctx) throws MetaException {
        // For single-valued fields we can use setResult() to implement projection of fields but
        // JDO doesn't support multi-valued fields in setResult() so currently JDO implementation
        // fallbacks to full-partition fetch if the requested fields contain multi-valued fields
        List<String> fieldNames = PartitionProjectionEvaluator.getMPartitionFieldNames(ctx.partitionFields);
          Map<String, Object> params = new HashMap<>();
          String jdoFilter = null;
          if (filterSpec.isSetFilterMode()) {
            // generate the JDO filter string
            switch(filterSpec.getFilterMode()) {
            case BY_EXPR:
              if (tree == null) {
                // tree could be null when directSQL is disabled
                initExpressionTree();
              }
              jdoFilter =
                  makeQueryFilterString(table.getCatName(), table.getDbName(), table, tree, params,
                      true);
              if (jdoFilter == null) {
                throw new MetaException("Could not generate JDO filter from given expression");
              }
              break;
            case BY_NAMES:
              jdoFilter = getJDOFilterStrForPartitionNames(table.getCatName(), table.getDbName(),
                  table.getTableName(), filterSpec.getFilters(), params);
              break;
            case BY_VALUES:
              jdoFilter = getJDOFilterStrForPartitionVals(table, filterSpec.getFilters(), params);
              break;
            default:
              throw new MetaException("Unsupported filter mode " + filterSpec.getFilterMode());
            }
          } else {
            // filter mode is not set create simple JDOFilterStr and params
            jdoFilter = "table.tableName == t1 && table.database.name == t2 && table.database.catalogName == t3";
            params.put("t1", normalizeIdentifier(tblName));
            params.put("t2", normalizeIdentifier(dbName));
            params.put("t3", normalizeIdentifier(catName));
          }
        try {
          List<MPartition> mparts = listMPartitionsWithProjection(fieldNames, jdoFilter, params);
          return convertToParts(catName, dbName, tblName, mparts, false, new GetPartitionsArgs.GetPartitionsArgsBuilder()
              .excludeParamKeyPattern(excludeParamKeyPattern)
              .includeParamKeyPattern(includeParamKeyPattern)
              .build());
        } catch (MetaException me) {
          throw me;
        } catch (Exception e) {
          throw new MetaException(e.getMessage());
        }
      }
    }.run(true);

  }
GetHelper for returning db info using directSql/JDO.
@param dbName The Database Name
@param allowSql Whether or not we allow DirectSQL to perform this query.
@param allowJdo Whether or not we allow ORM to perform this query.
standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/ObjectStore.java