def as_salesforce(self, compiler, connection):
        """
        Return the SQL version of the where clause and the value to be
        substituted in. Return '', [] if this node matches everything,
        None, [] if this node is empty, and raise EmptyResultSet if this
        node can't match anything.
        """

        # *** patch 1 (add) begin
        # # prepare SOQL translations
        if not isinstance(compiler, SQLCompiler):
            # future fix for DJANGO_20_PLUS, when deprecated "use_for_related_fields"
            # removed from managers,
            # "str(<UpdateQuery...>)" or "<UpdateQuery...>.get_compiler('default').as_sql()"
            return super(SalesforceWhereNode, self).as_sql(compiler, connection)
        soql_trans = compiler.query_topology()
        # *** patch 1 end

        result = []
        result_params = []
        if self.connector == AND:
            full_needed, empty_needed = len(self.children), 1
        else:
            full_needed, empty_needed = 1, len(self.children)

        for child in self.children:
            try:
                sql, params = compiler.compile(child)
            except EmptyResultSet:
                empty_needed -= 1
            else:
                if sql:

                    # *** patch 2 (add) begin
                    # # translate the alias of child to SOQL name
                    x_match = re.match(r'(\w+)\.(.*)', sql)
                    if x_match:
                        x_table, x_field = x_match.groups()
                        sql = '%s.%s' % (soql_trans[x_table], x_field)
                        # print('sql params:', sql, params)
                    # *** patch 2 end

                    result.append(sql)
                    result_params.extend(params)
                else:
                    full_needed -= 1
            # Check if this node matches nothing or everything.
            # First check the amount of full nodes and empty nodes
            # to make this node empty/full.
            # Now, check if this node is full/empty using the
            # counts.
            if empty_needed == 0:
                if self.negated:
                    return '', []
                else:
                    raise EmptyResultSet
            if full_needed == 0:
                if self.negated:
                    raise EmptyResultSet
                else:
                    return '', []
        conn = ' %s ' % self.connector
        sql_string = conn.join(result)
        if sql_string:
            if self.negated:
                # *** patch 3 (remove) begin
                # # Some backends (Oracle at least) need parentheses
                # # around the inner SQL in the negated case, even if the
                # # inner SQL contains just a single expression.
                # sql_string = 'NOT (%s)' % sql_string
                # *** patch 3 (add)
                # SOQL requires parentheses around "NOT" expression, if combined with AND/OR
                sql_string = '(NOT (%s))' % sql_string
                # *** patch 3 end

            # *** patch 4 (combine two versions into one compatible) begin
            # elif len(result) > 1:                                    # Django 1.10, 1.11
            # elif len(result) > 1 or self.resolved:                   # Django 2.0, 2.1
            elif len(result) > 1 or getattr(self, 'resolved', False):  # compatible code
                # *** patch 4 end

                sql_string = '(%s)' % sql_string
        return sql_string, result_params
Return the SQL version of the where clause and the value to be
        substituted in. Return '', [] if this node matches everything,
        None, [] if this node is empty, and raise EmptyResultSet if this
        node can't match anything.