def METHOD_NAME(query, form_integer_fields=None, form_decimal_fields=None):
    """
    Returns where clause and related parameters.
    """
    if form_integer_fields is None:
        form_integer_fields = []
    if form_decimal_fields is None:
        form_decimal_fields = []
    known_integers = ["_id"] + form_integer_fields
    known_decimals = form_decimal_fields
    where = []
    where_params = []
    # pylint: disable=too-many-nested-blocks
    try:
        if query and isinstance(query, (dict, six.string_types)):
            query = (
                query
                if isinstance(query, dict)
                else json.loads(query, object_pairs_hook=_merge_duplicate_keys)
            )
            or_where = []
            or_params = []
            if isinstance(query, list):
                query = query[0]
            if isinstance(query, dict) and "$or" in list(query):
                or_dict = query.pop("$or")
                for or_query in or_dict:
                    for k, v in or_query.items():
                        if v is None:
                            or_where.extend([f"json->>'{k}' IS NULL"])
                        elif isinstance(v, list):
                            for value in v:
                                or_where.extend(["json->>%s = %s"])
                                or_params.extend([k, value])
                        else:
                            or_where.extend(["json->>%s = %s"])
                            or_params.extend([k, v])
                or_where = ["".join(["(", " OR ".join(or_where), ")"])]
            where, where_params = _parse_where(
                query, known_integers, known_decimals, or_where, or_params
            )
    except (ValueError, AttributeError) as e:
        if query and isinstance(query, six.string_types) and query.startswith("{"):
            raise e
        # cast query param to text
        where = ["json::text ~* cast(%s as text)"]
        where_params = [query]
    return where, where_params