From e3aacb183b2604e0c06cb5ad7fd1748e7b752578 Mon Sep 17 00:00:00 2001 From: kobayashi Date: Sun, 12 Jan 2020 16:44:15 -0500 Subject: [PATCH] optimize query --- netbox/ipam/fields.py | 2 +- netbox/ipam/filters.py | 5 +---- netbox/ipam/lookups.py | 41 +++++++++++++++++++++++++++++------------ 3 files changed, 31 insertions(+), 17 deletions(-) diff --git a/netbox/ipam/fields.py b/netbox/ipam/fields.py index 612340607..845820432 100644 --- a/netbox/ipam/fields.py +++ b/netbox/ipam/fields.py @@ -95,6 +95,6 @@ IPAddressField.register_lookup(lookups.NetContainedOrEqual) IPAddressField.register_lookup(lookups.NetContains) IPAddressField.register_lookup(lookups.NetContainsOrEquals) IPAddressField.register_lookup(lookups.NetHost) -IPAddressField.register_lookup(lookups.NetHostIn) +IPAddressField.register_lookup(lookups.NetIn) IPAddressField.register_lookup(lookups.NetHostContained) IPAddressField.register_lookup(lookups.NetMaskLength) diff --git a/netbox/ipam/filters.py b/netbox/ipam/filters.py index 934ded93c..e9baf98cc 100644 --- a/netbox/ipam/filters.py +++ b/netbox/ipam/filters.py @@ -372,10 +372,7 @@ class IPAddressFilter(TenancyFilterSet, CustomFieldFilterSet, CreatedUpdatedFilt def filter_address(self, queryset, name, value): try: - return queryset.filter( - Q(address__in=value) | - Q(address__net_host_in=value) - ) + return queryset.filter(address__net_in=value) except ValidationError: return queryset.none() diff --git a/netbox/ipam/lookups.py b/netbox/ipam/lookups.py index c5b6081f1..457cd7734 100644 --- a/netbox/ipam/lookups.py +++ b/netbox/ipam/lookups.py @@ -100,23 +100,40 @@ class NetHost(Lookup): return 'HOST(%s) = %s' % (lhs, rhs), params -class NetHostIn(Lookup): - lookup_name = 'net_host_in' +class NetIn(Lookup): + lookup_name = 'net_in' def as_sql(self, qn, connection): lhs, lhs_params = self.process_lhs(qn, connection) rhs, rhs_params = self.process_rhs(qn, connection) - in_elements = ['HOST(%s) IN (' % lhs] - params = [] - for offset in range(0, len(rhs_params[0])): + with_mask, without_mask = [], [] + for address in rhs_params[0]: + if '/' in address: + with_mask.append(address) + else: + without_mask.append(address) + + address_in_clause = self.create_in_clause('{} IN ('.format(lhs), len(with_mask)) + host_in_clause = self.create_in_clause('HOST({}) IN ('.format(lhs), len(without_mask)) + + if with_mask and not without_mask: + return address_in_clause, with_mask + elif not with_mask and without_mask: + return host_in_clause, without_mask + + in_clause = '({}) OR ({})'.format(address_in_clause, host_in_clause) + with_mask.extend(without_mask) + return in_clause, with_mask + + @staticmethod + def create_in_clause(clause_part, max_size): + clause_elements = [clause_part] + for offset in range(0, max_size): if offset > 0: - in_elements.append(', ') - params.extend(lhs_params) - sqls_params = rhs_params[0][offset] - in_elements.append(rhs) - params.append(sqls_params) - in_elements.append(')') - return ''.join(in_elements), params + clause_elements.append(', ') + clause_elements.append('%s') + clause_elements.append(')') + return ''.join(clause_elements) class NetHostContained(Lookup):