Example #1
0
    def test_int_packer(self):
        v = [801000, 801001, 801002, 801003, 801004, 801005, 801006, 801007, 801008, 801009, 801010, 801011, 801012, 801013, 801014, 801015, 801016, 801017, 801018, 801019, 801020, 801021, 801022, 801023,
             801024, 801025, 801026, 801028, 801029, 801030, 801032, 801034, 801035, 801036, 801037, 801038, 801040, 801042, 801043, 801044, 801045, 801047, 801048, 801049, 801050, 801051, 801052, 801053,
             801055, 801056, 801057, 801058, 801059, 801060, 801061, 801062, 801063, 801065, 801066, 801067, 801068, 801069, 801070, 801071, 801072, 801073, 801074, 801075, 801076, 801077, 801078, 801079,
             801080, 801081, 801083, 801084, 801085, 801086, 801087, 801088, 801089, 801090, 801091, 801092, 801093, 801094, 801095, 801096, 801097, 801098, 801099, 801100, 801101, 801102, 801103, 801104,
             801105, 801106, 801107, 801108, 801109, 801110, 801111, 801112, 801113, 801116, 801117, 801118, 801119, 801120, 801121, 801122, 801123, 801124, 801125, 801126, 801128, 801129, 801130, 801131,
             801132, 801133, 801134, 801135, 801136, 801137, 801138, 801139, 801140, 801141, 801142, 801143, 801144, 801145, 801146, 801147, 801148, 801149, 801150, 801151, 801152, 801153, 801154, 801155,
             801156, 801158, 801159, 801160, 801161, 801162, 801163, 801164, 801165, 801166, 801167, 801168, 801169, 801170, 801171, 801172, 801173, 801174, 801175, 801176, 801177, 801178, 801179, 801180,
             801181, 801182, 801183, 801184, 801185, 801186, 801187, 801188, 801189, 801190, 801191, 801192, 801193, 801194, 801196, 801197, 801198, 801199, 801200, 801201, 801202, 801203, 801204, 801205,
             801207, 801208, 801209, 801210, 801211, 801212, 801213, 801214, 801215, 801216, 801217, 801218, 801219, 801222, 801223, 801224, 801225, 801226, 801229, 801230, 801231, 801232, 801233, 801235,
             801236, 801237, 801238, 801239, 801240, 801241, 801242, 801243, 801244, 801245, 801246, 801247, 801253, 801254, 801255, 801256, 801257, 801258, 801260, 801261, 801262, 801263, 801264, 801265,
             801266, 801267, 801268, 801269, 801270, 801271, 801272, 801273, 801274, 801275, 801276, 801277, 801278, 801279, 801280, 801281, 801282, 801283, 801284, 801285, 801286, 801287, 801288, 801289,
             801290, 801291, 801292, 801293, 801294, 801295, 801296, 801297, 801298, 801300, 801301, 801303, 801304, 801305, 801306, 801307, 801308, 801309, 801310, 801311, 801312, 801313, 801314, 801315,
             801316, 801317, 801318, 801319, 801320, 801321, 801322, 801323, 801324, 801325, 801326, 801327, 801328, 801329, 801331, 801332, 801333, 801334, 801336, 801337, 801338, 801339, 801340, 801341,
             801343, 801344, 801345, 801346, 801347, 801348, 801349, 801350, 801351, 801352, 801353, 801354, 801355, 801356, 801357, 801358, 801359, 801360, 801361, 801362, 801363, 801364, 801365, 801367,
             801368, 801369, 801370, 801371, 801372, 801373, 801374, 801375, 801376, 801377, 801378, 801379, 801380, 801381, 801382, 801383, 801384, 801385, 801386, 801387, 801388, 801389, 801390, 801391,
             801393, 801394, 801395, 801396, 801397, 801398, 801399, 801400, 801401, 801402, 801403, 801404, 801405, 801406, 801407, 801408, 801409, 801410, 801411, 801412, 801413, 801414, 801415, 801416,
             801417, 801418, 801419, 801420, 801421, 801422, 801423, 801424, 801425, 801426, 801427, 801428, 801429, 801430, 801431, 801432, 801433, 801434, 801435, 801436, 801437, 801439, 801440, 801441,
             801442, 801443, 801444, 801445, 801446, 801447, 801448, 801449, 801450, 801451, 801452, 801453, 801454, 801455, 801456, 801457, 801458, 801459, 801460, 801461, 801462, 801463, 801464, 801465,
             801466, 801467, 801468, 801469, 801470, 801471, 801472, 801473, 801474, 801475, 801476, 801477, 801478, 801479, 801480, 801481, 801482, 801483, 801484, 801485, 801486, 801487, 801488, 801489,
             801490, 801491, 801492, 801493, 801494, 801495, 801496, 801497, 801498, 801499, 801500, 801501, 801502, 801503, 801505, 801506, 801507, 801508, 801509, 801510, 801511, 801512, 801513, 801514,
             801515, 801516, 801517, 801518, 801519, 801520, 801521, 801522, 801523, 801524, 801525, 801526, 801527, 801528, 801529, 801530, 801531, 801532, 801533, 801534, 801535, 801536, 801537, 801538,
             801539, 801540, 801541, 801542, 801543, 801544, 801545, 801546, 801547, 801548, 801549, 801550, 801551, 801552, 801553, 801554, 801555, 801556, 801557, 801558, 801559, 801560, 801561, 801562,
             801563, 801564, 801565, 801566, 801567, 801568, 801569, 801571, 801572, 801573, 801574, 801575, 801576, 801577, 801578, 801579, 801580, 801581, 801582, 801583, 801584, 801585, 801587, 801589,
             801590, 801591, 801592, 801593, 801595, 801596, 801597, 801598, 801599, 801600, 801601, 801602, 801603, 801604, 801605, 801606, 801607, 801608, 801609, 801610, 801611, 801612, 801613, 801614,
             801615, 801616, 801617, 801618, 801619, 801620, 801621, 801622, 801623, 801624, 801625, 801626, 801627, 801628, 801629, 801630, 801631, 801632, 801633, 801634, 801635, 801636, 801637, 801639,
             801640, 801642, 801643, 801644, 801645, 801646, 801647, 801649, 801650, 801651, 801652, 801653, 801655, 801656, 801658, 801659, 801660, 801661, 801662, 801663, 801664, 801665, 801666, 801667,
             801668, 801669, 801670, 801671, 801672, 801674, 801675, 801676, 801677, 801678, 801679, 801680, 801681, 801682, 801683, 801684, 801685, 801686, 801687, 801688, 801690, 801691, 801693, 801694,
             801695, 801696, 801697, 801698, 801699, 801701, 801702, 801703, 801705, 801706, 801707, 801708, 801710, 801711, 801712, 801713, 801714, 801715, 801716, 801717, 801718, 801719, 801720, 801721,
             801722, 801723, 801724, 801725, 801726, 801727, 801729, 801730, 801731, 801732, 801733, 801734, 801737, 801738, 801739, 801740, 801741, 801742, 801743, 801744, 801745, 801747, 801748, 801749,
             801750, 801752, 801753, 801754, 801755, 801756, 801757, 801758, 801759, 801760, 801761, 801763, 801764, 801765, 801766, 801767, 801769, 801771, 801773, 801774, 801775, 801776, 801778, 801779,
             801780, 801781, 801782, 801783, 801784, 801785, 801786, 801787, 801788, 801789, 801791, 801792, 801793, 801794, 801795, 801796, 801797, 801798, 801799, 801800, 801801, 801802, 801803, 801804,
             801805, 801806, 801807, 801808, 801809, 801810, 801811, 801812, 801813, 801814, 801816, 801817, 801818, 801819, 801820, 801821, 801823, 801824, 801825, 801826, 801827, 801828, 801829, 801830,
             801832, 801833, 801834, 801835, 801836, 801837, 801838, 801839, 801840, 801841, 801842, 801843, 801844, 801845, 801846, 801847, 801849, 801850, 801852, 801855, 801856, 801857, 801858, 801859,
             801860, 801862, 801869, 801872, 801874, 801880, 801882, 801883, 801884, 801885, 801891, 801892, 801895, 801897, 801898, 801899, 801902, 801905, 801906, 801909, 801911, 801912, 801913, 801914,
             801915, 801916, 801917, 801918, 801919, 801920, 801921, 801922, 801923, 801924, 801925, 801926, 801927, 801928, 801929, 801930, 801931, 801932, 801934, 801935, 801936, 801937, 801938, 801941,
             801942, 801943, 801944, 801945, 801946, 801947, 801948, 801949, 801950, 801951, 801952, 801953, 801954, 801955, 801956, 801957, 801958, 801960, 801961, 801962, 801964, 801965, 801966, 801967,
             801969, 801970, 801971, 801972, 801973, 801974, 801976, 801977, 801978, 801979, 801980, 801981, 801982, 801983, 801984, 801985, 801986, 801987, 801988, 801989, 801990, 801991, 801993, 801994,
             801995, 801996, 801998]

        int_list = convert.value2intlist(v)
        result = mysql.int_list_packer("bug_id", int_list)
        reference = {"or": [{"terms": {"bug_id": [801869, 801872, 801874, 801880, 801882, 801883, 801884, 801885, 801891, 801892, 801895, 801897, 801898, 801899, 801902, 801905, 801906, 801909, 801911, 801912, 801913, 801914, 801915, 801916, 801917, 801918, 801919, 801920, 801921, 801922, 801923, 801924, 801925, 801926, 801927, 801928, 801929, 801930, 801931, 801932, 801934, 801935, 801936, 801937, 801938, 801941, 801942, 801943, 801944, 801945, 801946, 801947, 801948, 801949, 801950, 801951, 801952, 801953, 801954, 801955, 801956, 801957, 801958, 801960, 801961, 801962, 801964, 801965, 801966, 801967, 801969, 801970, 801971, 801972, 801973, 801974, 801976, 801977, 801978, 801979, 801980, 801981, 801982, 801983, 801984, 801985, 801986, 801987, 801988, 801989, 801990, 801991, 801993, 801994, 801995, 801996, 801998]}}, {"and": [{"or": [{"range": {"bug_id": {"gte": 801000, "lte": 801045}}}, {"range": {"bug_id": {"gte": 801047, "lte": 801247}}}, {"range": {"bug_id": {"gte": 801253, "lte": 801862}}}]}, {"not": {"terms": {"bug_id": [801027, 801031, 801033, 801039, 801041, 801054, 801064, 801082, 801114, 801115, 801127, 801157, 801195, 801206, 801220, 801221, 801227, 801228, 801234, 801259, 801299, 801302, 801330, 801335, 801342, 801366, 801392, 801438, 801504, 801570, 801586, 801588, 801594, 801638, 801641, 801648, 801654, 801657, 801673, 801689, 801692, 801700, 801704, 801709, 801728, 801735, 801736, 801746, 801751, 801762, 801768, 801770, 801772, 801777, 801790, 801815, 801822, 801831, 801848, 801851, 801853, 801854, 801861]}}}]}]}

        self.assertEqual(result, reference)
def _esfilter2sqlwhere(db, esfilter):
    """
    CONVERT ElassticSearch FILTER TO SQL FILTER
    db - REQUIRED TO PROPERLY QUOTE VALUES AND COLUMN NAMES
    """
    esfilter = wrap(esfilter)

    if esfilter is True:
        return "1=1"
    elif esfilter["and"]:
        return _isolate("AND", [esfilter2sqlwhere(db, a) for a in esfilter["and"]])
    elif esfilter["or"]:
        return _isolate("OR", [esfilter2sqlwhere(db, a) for a in esfilter["or"]])
    elif esfilter["not"]:
        return "NOT (" + esfilter2sqlwhere(db, esfilter["not"]) + ")"
    elif esfilter.term:
        return _isolate("AND", [db.quote_column(col) + "=" + db.quote_value(val) for col, val in esfilter.term.items()])
    elif esfilter.terms:
        for col, v in esfilter.terms.items():
            if len(v) == 0:
                return "FALSE"

            try:
                int_list = convert.value2intlist(v)
                has_null = False
                for vv in v:
                    if vv == None:
                        has_null = True
                        break
                if int_list:
                    filter = int_list_packer(col, int_list)
                    if has_null:
                        return esfilter2sqlwhere(db, {"or": [{"missing": col}, filter]})
                    else:
                        return esfilter2sqlwhere(db, filter)
                else:
                    if has_null:
                        return esfilter2sqlwhere(db, {"missing": col})
                    else:
                        return "false"
            except Exception, e:
                pass
            return db.quote_column(col) + " in (" + ",\n".join([db.quote_value(val) for val in v]) + ")"
Example #3
0
def _esfilter2sqlwhere(db, esfilter):
    """
    CONVERT ElassticSearch FILTER TO SQL FILTER
    db - REQUIRED TO PROPERLY QUOTE VALUES AND COLUMN NAMES
    """
    esfilter = wrap(esfilter)

    if esfilter is True:
        return "1=1"
    elif esfilter["and"]:
        return _isolate("AND", [esfilter2sqlwhere(db, a) for a in esfilter["and"]])
    elif esfilter["or"]:
        return _isolate("OR", [esfilter2sqlwhere(db, a) for a in esfilter["or"]])
    elif esfilter["not"]:
        return "NOT (" + esfilter2sqlwhere(db, esfilter["not"]) + ")"
    elif esfilter.term:
        return _isolate("AND", [db.quote_column(col) + "=" + db.quote_value(val) for col, val in esfilter.term.items()])
    elif esfilter.terms:
        for col, v in esfilter.terms.items():
            if len(v) == 0:
                return "FALSE"

            try:
                int_list = convert.value2intlist(v)
                has_null = False
                for vv in v:
                    if vv == None:
                        has_null = True
                        break
                if int_list:
                    filter = int_list_packer(col, int_list)
                    if has_null:
                        return esfilter2sqlwhere(db, {"or": [{"missing": col}, filter]})
                    else:
                        return esfilter2sqlwhere(db, filter)
                else:
                    if has_null:
                        return esfilter2sqlwhere(db, {"missing": col})
                    else:
                        return "false"
            except Exception, e:
                pass
            return db.quote_column(col) + " in (" + ",\n".join([db.quote_value(val) for val in v]) + ")"
def _esfilter2sqlwhere(db, esfilter):
    """
    CONVERT ElassticSearch FILTER TO SQL FILTER
    db - REQUIRED TO PROPERLY QUOTE VALUES AND COLUMN NAMES
    """
    esfilter = wrap(esfilter)

    if esfilter is True:
        return "1=1"
    elif esfilter["and"]:
        return _isolate("AND",
                        [esfilter2sqlwhere(db, a) for a in esfilter["and"]])
    elif esfilter["or"]:
        return _isolate("OR",
                        [esfilter2sqlwhere(db, a) for a in esfilter["or"]])
    elif esfilter["not"]:
        return "NOT (" + esfilter2sqlwhere(db, esfilter["not"]) + ")"
    elif esfilter.term:
        return _isolate("AND", [
            db.quote_column(col) + "=" + db.quote_value(val)
            for col, val in esfilter.term.items()
        ])
    elif esfilter.terms:
        for col, v in esfilter.terms.items():
            if len(v) == 0:
                return "FALSE"

            with suppress_exception:
                int_list = convert.value2intlist(v)
                has_null = False
                for vv in v:
                    if vv == None:
                        has_null = True
                        break
                if int_list:
                    filter = int_list_packer(col, int_list)
                    if has_null:
                        return esfilter2sqlwhere(
                            db, {"or": [{
                                "missing": col
                            }, filter]})
                    else:
                        return esfilter2sqlwhere(db, filter)
                else:
                    if has_null:
                        return esfilter2sqlwhere(db, {"missing": col})
                    else:
                        return "false"
            return db.quote_column(col) + SQL(
                " in (" + ",\n".join([db.quote_value(val) for val in v]) + ")")
    elif esfilter.script:
        return "(" + esfilter.script + ")"
    elif esfilter.range:
        name2sign = {"gt": ">", "gte": ">=", "lte": "<=", "lt": "<"}

        def single(col, r):
            min = coalesce(r["gte"], r[">="])
            max = coalesce(r["lte"], r["<="])
            if min and max:
                # SPECIAL CASE (BETWEEN)
                return db.quote_column(col) + SQL(
                    " BETWEEN ") + db.quote_value(min) + SQL(
                        " AND ") + db.quote_value(max)
            else:
                return " AND ".join(
                    db.quote_column(col) + name2sign[sign] +
                    db.quote_value(value) for sign, value in r.items())

        output = _isolate(
            "AND",
            [single(col, ranges) for col, ranges in esfilter.range.items()])
        return output
    elif esfilter.missing:
        if isinstance(esfilter.missing, basestring):
            return "(" + db.quote_column(esfilter.missing) + " IS Null)"
        else:
            return "(" + db.quote_column(esfilter.missing.field) + " IS Null)"
    elif esfilter.exists:
        if isinstance(esfilter.exists, basestring):
            return "(" + db.quote_column(esfilter.exists) + " IS NOT Null)"
        else:
            return "(" + db.quote_column(
                esfilter.exists.field) + " IS NOT Null)"
    elif esfilter.match_all:
        return "1=1"
    elif esfilter.instr:
        return _isolate("AND", [
            "instr(" + db.quote_column(col) + ", " + db.quote_value(val) +
            ")>0" for col, val in esfilter.instr.items()
        ])
    else:
        Log.error("Can not convert esfilter to SQL: {{esfilter}}",
                  esfilter=esfilter)
def _esfilter2sqlwhere(db, esfilter):
    """
    CONVERT ElassticSearch FILTER TO SQL FILTER
    db - REQUIRED TO PROPERLY QUOTE VALUES AND COLUMN NAMES
    """
    esfilter = wrap(esfilter)

    if esfilter is True:
        return "1=1"
    elif esfilter["and"]:
        return _isolate("AND", [esfilter2sqlwhere(db, a) for a in esfilter["and"]])
    elif esfilter["or"]:
        return _isolate("OR", [esfilter2sqlwhere(db, a) for a in esfilter["or"]])
    elif esfilter["not"]:
        return "NOT (" + esfilter2sqlwhere(db, esfilter["not"]) + ")"
    elif esfilter.term:
        return _isolate("AND", [db.quote_column(col) + "=" + db.quote_value(val) for col, val in esfilter.term.items()])
    elif esfilter.terms:
        for col, v in esfilter.terms.items():
            if len(v) == 0:
                return "FALSE"

            with suppress_exception:
                int_list = convert.value2intlist(v)
                has_null = False
                for vv in v:
                    if vv == None:
                        has_null = True
                        break
                if int_list:
                    filter = int_list_packer(col, int_list)
                    if has_null:
                        return esfilter2sqlwhere(db, {"or": [{"missing": col}, filter]})
                    else:
                        return esfilter2sqlwhere(db, filter)
                else:
                    if has_null:
                        return esfilter2sqlwhere(db, {"missing": col})
                    else:
                        return "false"
            return db.quote_column(col) + " in (" + ",\n".join([db.quote_value(val) for val in v]) + ")"
    elif esfilter.script:
        return "(" + esfilter.script + ")"
    elif esfilter.range:
        name2sign = {
            "gt": ">",
            "gte": ">=",
            "lte": "<=",
            "lt": "<"
        }

        def single(col, r):
            min = coalesce(r["gte"], r[">="])
            max = coalesce(r["lte"], r["<="])
            if min and max:
                # SPECIAL CASE (BETWEEN)
                return db.quote_column(col) + " BETWEEN " + db.quote_value(min) + " AND " + db.quote_value(max)
            else:
                return " AND ".join(
                    db.quote_column(col) + name2sign[sign] + db.quote_value(value)
                    for sign, value in r.items()
                )

        output = _isolate("AND", [single(col, ranges) for col, ranges in esfilter.range.items()])
        return output
    elif esfilter.missing:
        if isinstance(esfilter.missing, basestring):
            return "(" + db.quote_column(esfilter.missing) + " IS Null)"
        else:
            return "(" + db.quote_column(esfilter.missing.field) + " IS Null)"
    elif esfilter.exists:
        if isinstance(esfilter.exists, basestring):
            return "(" + db.quote_column(esfilter.exists) + " IS NOT Null)"
        else:
            return "(" + db.quote_column(esfilter.exists.field) + " IS NOT Null)"
    elif esfilter.match_all:
        return "1=1"
    elif esfilter.instr:
        return _isolate("AND", ["instr(" + db.quote_column(col) + ", " + db.quote_value(val) + ")>0" for col, val in esfilter.instr.items()])
    else:
        Log.error("Can not convert esfilter to SQL: {{esfilter}}", esfilter=esfilter)
Example #6
0
def _esfilter2sqlwhere(db, esfilter):
    """
    CONVERT ElassticSearch FILTER TO SQL FILTER
    db - REQUIRED TO PROPERLY QUOTE VALUES AND COLUMN NAMES
    """
    esfilter = wrap(esfilter)

    if esfilter is True:
        return SQL_TRUE
    elif esfilter["and"]:
        return sql_iso(SQL_AND.join([esfilter2sqlwhere(db, a) for a in esfilter["and"]]))
    elif esfilter["or"]:
        return sql_iso(SQL_OR.join([esfilter2sqlwhere(db, a) for a in esfilter["or"]]))
    elif esfilter["not"]:
        return SQL_NOT + sql_iso(esfilter2sqlwhere(db, esfilter["not"]))
    elif esfilter.term:
        return sql_iso(SQL_AND.join([
            quote_column(col) + SQL("=") + quote_value(val)
            for col, val in esfilter.term.items()
        ]))
    elif esfilter.terms:
        for col, v in esfilter.terms.items():
            if len(v) == 0:
                return "FALSE"

            try:
                int_list = convert.value2intlist(v)
                has_null = False
                for vv in v:
                    if vv == None:
                        has_null = True
                        break
                if int_list:
                    filter = int_list_packer(col, int_list)
                    if has_null:
                        return esfilter2sqlwhere(db, {"or": [{"missing": col}, filter]})
                    elif 'terms' in filter and set(filter['terms'].get(col, []))==set(int_list):
                        return quote_column(col) + " in " + quote_list(int_list)
                    else:
                        return esfilter2sqlwhere(db, filter)
                else:
                    if has_null:
                        return esfilter2sqlwhere(db, {"missing": col})
                    else:
                        return "false"
            except Exception as e:
                e = Except.wrap(e)
                pass
            return quote_column(col) + " in " + quote_list(v)
    elif esfilter.script:
        return sql_iso(esfilter.script)
    elif esfilter.range:
        name2sign = {
            "gt": SQL(">"),
            "gte": SQL(">="),
            "lte": SQL("<="),
            "lt": SQL("<")
        }

        def single(col, r):
            min = coalesce(r["gte"], r[">="])
            max = coalesce(r["lte"], r["<="])
            if min != None and max != None:
                # SPECIAL CASE (BETWEEN)
                sql = quote_column(col) + SQL(" BETWEEN ") + quote_value(min) + SQL_AND + quote_value(max)
            else:
                sql = SQL_AND.join(
                    quote_column(col) + name2sign[sign] + quote_value(value)
                    for sign, value in r.items()
                )
            return sql

        terms = [single(col, ranges) for col, ranges in esfilter.range.items()]
        if len(terms) == 1:
            output = terms[0]
        else:
            output = sql_iso(SQL_AND.join(terms))
        return output
    elif esfilter.missing:
        if isinstance(esfilter.missing, text_type):
            return sql_iso(quote_column(esfilter.missing) + SQL_IS_NULL)
        else:
            return sql_iso(quote_column(esfilter.missing.field) + SQL_IS_NULL)
    elif esfilter.exists:
        if isinstance(esfilter.exists, text_type):
            return sql_iso(quote_column(esfilter.exists) + SQL_IS_NOT_NULL)
        else:
            return sql_iso(quote_column(esfilter.exists.field) + SQL_IS_NOT_NULL)
    elif esfilter.match_all:
        return SQL_TRUE
    elif esfilter.instr:
        return sql_iso(SQL_AND.join(["instr" + sql_iso(quote_column(col) + ", " + quote_value(val)) + ">0" for col, val in esfilter.instr.items()]))
    else:
        Log.error("Can not convert esfilter to SQL: {{esfilter}}", esfilter=esfilter)
Example #7
0
def _esfilter2sqlwhere(db, esfilter):
    """
    CONVERT ElassticSearch FILTER TO SQL FILTER
    db - REQUIRED TO PROPERLY QUOTE VALUES AND COLUMN NAMES
    """
    esfilter = wrap(esfilter)

    if esfilter is True:
        return SQL_TRUE
    elif esfilter["and"]:
        return _isolate(SQL_AND, [esfilter2sqlwhere(db, a) for a in esfilter["and"]])
    elif esfilter["or"]:
        return _isolate("OR", [esfilter2sqlwhere(db, a) for a in esfilter["or"]])
    elif esfilter["not"]:
        return "NOT " + sql_iso(esfilter2sqlwhere(db, esfilter["not"]))
    elif esfilter.term:
        return _isolate(SQL_AND, [db.quote_column(col) + SQL("=") + db.quote_value(val) for col, val in esfilter.term.items()])
    elif esfilter.terms:
        for col, v in esfilter.terms.items():
            if len(v) == 0:
                return "FALSE"

            with suppress_exception:
                int_list = convert.value2intlist(v)
                has_null = False
                for vv in v:
                    if vv == None:
                        has_null = True
                        break
                if int_list:
                    filter = int_list_packer(col, int_list)
                    if has_null:
                        return esfilter2sqlwhere(db, {"or": [{"missing": col}, filter]})
                    else:
                        return esfilter2sqlwhere(db, filter)
                else:
                    if has_null:
                        return esfilter2sqlwhere(db, {"missing": col})
                    else:
                        return "false"
            return db.quote_column(col) + " in " + sql_iso(sql_list([db.quote_value(val) for val in v]))
    elif esfilter.script:
        return sql_iso(esfilter.script)
    elif esfilter.range:
        name2sign = {
            "gt": SQL(">"),
            "gte": SQL(">="),
            "lte": SQL("<="),
            "lt": SQL("<")
        }

        def single(col, r):
            min = coalesce(r["gte"], r[">="])
            max = coalesce(r["lte"], r["<="])
            if min != None and max != None:
                # SPECIAL CASE (BETWEEN)
                sql = db.quote_column(col) + SQL(" BETWEEN ") + db.quote_value(min) + SQL_AND + db.quote_value(max)
            else:
                sql = SQL_AND.join(
                    db.quote_column(col) + name2sign[sign] + db.quote_value(value)
                    for sign, value in r.items()
                )
            return sql

        output = _isolate(SQL_AND, [single(col, ranges) for col, ranges in esfilter.range.items()])
        return output
    elif esfilter.missing:
        if isinstance(esfilter.missing, text_type):
            return sql_iso(db.quote_column(esfilter.missing) + SQL_IS_NULL)
        else:
            return sql_iso(db.quote_column(esfilter.missing.field) + SQL_IS_NULL)
    elif esfilter.exists:
        if isinstance(esfilter.exists, text_type):
            return sql_iso(db.quote_column(esfilter.exists) + SQL_IS_NOT_NULL)
        else:
            return sql_iso(db.quote_column(esfilter.exists.field) + SQL_IS_NOT_NULL)
    elif esfilter.match_all:
        return SQL_TRUE
    elif esfilter.instr:
        return _isolate(SQL_AND, ["instr" + sql_iso(db.quote_column(col) + ", " + db.quote_value(val)) + ">0" for col, val in esfilter.instr.items()])
    else:
        Log.error("Can not convert esfilter to SQL: {{esfilter}}", esfilter=esfilter)