private final void compileIfNeeded() {
    //
    // Check: if is alread compiled, there is no need to compile it again
    if (_compiled) {
      return;
    }

    //
    // Check: if we have no filters, we can set the status right away
    if (filters.isEmpty()) {
      _sqlWhereClause = isDefaultAccept() ? DEFAULT_SQL_TRUE : DEFAULT_SQL_FALSE;
      _sqlFilters = Collections.emptyList();
      _nonSqlFilters = null;
      _compiled = true;
      return;
    }

    final List<ISqlQueryFilter> resultSqlFilters = new ArrayList<ISqlQueryFilter>();
    final StringBuilder resultSqlWhereClause = new StringBuilder();
    final List<IQueryFilter<T>> resultNonSqlFilters = new ArrayList<IQueryFilter<T>>();
    final List<IQueryFilter<T>> resultAllFiltersSoFar =
        new ArrayList<IQueryFilter<T>>(filters.size());
    boolean allowSqlFilters = true; // do we allow SQL filter?

    for (final IQueryFilter<T> filter : filters) {
      final List<ISqlQueryFilter> sqlFilters;
      final List<IQueryFilter<T>> nonSqlFilters;

      //
      // Case: we are not accepting SQL filters
      // => no point to check forward but treat this filter as a nonSQL filter
      if (!allowSqlFilters) {
        sqlFilters = null;
        nonSqlFilters = Collections.singletonList(filter);
      }
      //
      // Case: Composite Filter (SQL and non-SQL)
      else if (filter instanceof ICompositeQueryFilter) {
        final ICompositeQueryFilter<T> compositeFilter = (ICompositeQueryFilter<T>) filter;

        // Case: our composite is a pure SQL filter
        if (compositeFilter.isPureSql()) {
          final ISqlQueryFilter sqlFilter = compositeFilter.asSqlQueryFilter();
          sqlFilters = Collections.singletonList(sqlFilter);
          nonSqlFilters = null;
        }
        // Case: our composite is not a pure SQL filter but it's join method is AND
        // => we can mix this kind of filters
        else if (compositeFilter.isJoinAnd() == this.isJoinAnd() == true) {
          sqlFilters = compositeFilter.getSqlFilters();
          nonSqlFilters = compositeFilter.getNonSqlFilters();
        }
        // Case: our composite is not a pure SQL filter and it's join method is not AND
        // => we cannot mix SQL and nonSQL in this way so we consider the whole compositeFilter as
        // non-sql
        else {
          sqlFilters = null;
          nonSqlFilters = Collections.<IQueryFilter<T>>singletonList(compositeFilter);
        }
      }
      //
      // Case: Pure SQL Filter
      else if (filter instanceof ISqlQueryFilter) {
        final ISqlQueryFilter sqlFilter = (ISqlQueryFilter) filter;
        sqlFilters = Collections.singletonList(sqlFilter);
        nonSqlFilters = null;
      }
      //
      // Case: non-SQL filter:
      else {
        sqlFilters = null;
        nonSqlFilters = Collections.singletonList(filter);
      }

      //
      // Append the SQL Part (if any)
      appendSqlWhereClause(resultSqlWhereClause, resultSqlFilters, sqlFilters);

      //
      // Append Non-SQL part (if any)
      if (nonSqlFilters != null && !nonSqlFilters.isEmpty()) {
        resultNonSqlFilters.addAll(nonSqlFilters);
      }

      //
      // Update our all filters so far list
      resultAllFiltersSoFar.add(filter);

      //
      // Case: Until now we allowed SQL filters but our join method is not AND
      // ... and we already have SQL Filters and nonSQL filters accumulated
      //
      // => make all filters as nonSQL
      // => clear "resultNonSqlFilters" and "resultSqlWhereClause" because we will not use them from
      // now on
      // => don't allow SQL filters from now on
      if (allowSqlFilters
          && !this.isJoinAnd()
          && !resultSqlFilters.isEmpty()
          && !resultNonSqlFilters.isEmpty()) {
        resultNonSqlFilters.clear();
        resultNonSqlFilters.addAll(resultAllFiltersSoFar);
        resultSqlFilters.clear();
        resultSqlWhereClause.setLength(0);
        // we are not allowing mixing filters anymore
        // => we allow only nonSQL filters; all SQL filters will be considered nonSQL from now on
        allowSqlFilters = false;
      }
    }

    this._sqlFilters = Collections.unmodifiableList(resultSqlFilters);
    this._nonSqlFilters = Collections.unmodifiableList(resultNonSqlFilters);
    this._sqlWhereClause = resultSqlWhereClause.toString();
    this._compiled = true;
  }