PostgreSQL将cidr扩展到单个地址

PostgreSQL将cidr扩展到单个地址,第1张

概述我在以下布局中存储的网络中有大量子网列表.它用作主表来存储资产,这些资产将用于定期通过 Python脚本自动探测状态. CREATE TEMP TABLE tmp_networks ( network cidr PRIMARY KEY); 让我们假设它为了演示而填充了这些值: > 10.0.0.0/8 > 10.0.1.0/24 > 192.168.0.0/24 当我运行脚本时,Pyth 我在以下布局中存储的网络中有大量子网列表.它用作主表来存储资产,这些资产将用于定期通过 Python脚本自动探测状态.

CREATE TEMP table tmp_networks (    network cIDr PRIMARY KEY);

让我们假设它为了演示而填充了这些值:

> 10.0.0.0/8
> 10.0.1.0/24
> 192.168.0.0/24

当我运行脚本时,Python脚本将执行以下查询以删除任何重叠:

SELECT network    FROM tmp_networks    WHERE NOT EXISTS (        SELECT network        FROM tmp_networks n        WHERE n.network >> tmp_networks.network);

除了一个小问题外,这很有效.我还有一份应该从工作中排除的个人地址列表.这也是数据库中的一个表:

CREATE TEMP table tmp_except (    address inet PRIMARY KEY);

让我们假设它包含以下地址:

> 10.0.0.100
> 192.168.0.10

现在,我找不到从数据库输出中删除这些特定地址的好方法.在我的想法中,解决方案将是这样的:

>选择所有子网
>如果在子网中找到任何异常地址,则将子网拆分为较小的部分,直到可以删除单个异常地址并保留所有其他地址

我试图调查在纯Postgresql中是否可以做这样的事情,但是没有找到解决这个问题的方法.关于如何解决这个问题的任何指示?

解决方法 我会用两个函数来解决这个问题.第一个函数接受一个cIDr和一个异常地址,并返回一组cIDrs,它们等同于原始cIDr减去异常地址.该函数的工作原理是将cIDr分成两半,然后递归地从它所在的一半中删除异常地址.更复杂的算法可以避免一些不必要的分裂.简单的函数如下所示:

CREATE OR REPLACE FUNCTION split_cIDr(net cIDr,exc inet) returns setof cIDr language plpgsql AS $$DECLARE  r cIDr;  lower cIDr;  upper cIDr;BEGIN  IF masklen(net) >= 32 THEN RETURN; END IF;  lower = set_masklen(net,masklen(net)+1);  upper = set_masklen( (lower | ~ netmask(lower)) + 1,masklen(lower));  IF exc << upper THEN    RETURN NEXT lower;    FOR r IN SELECT * from split_cIDr(upper,exc)    LOOP RETURN NEXT r;    END LOOP;  ELSE    FOR r IN SELECT * from split_cIDr(lower,exc)    LOOP RETURN NEXT r;    END LOOP;    RETURN NEXT upper;  END IF;  RETURN;END $$;

有了这个功能,人们就可以遍历网络列表,将其应用到包含异常地址的网络.以下函数将网络地址列表拆分为包含异常的列表和不包含异常的列表.那些没有返回的,那些已经应用了上述功能的那些.这不涉及网络包含多于异常地址的情况.

CREATE OR REPLACE FUNCTION DOIT() RETURNS Setof cIDr  language plpgsql AS $$DECLARE r cIDr; x cIDr; z inet;BEGIN -- these are the rows where the network has no exceptions FOR r in SELECT network FROM tmp_networks n WHERE NOT EXISTS (   SELECT address FROM tmp_except WHERE address << n.network ) LOOP RETURN NEXT r; END LOOP; -- these are the rows where the network has an exception FOR r,z in SELECT network,address from tmp_networks full join tmp_except on true where address << network LOOP   FOR x IN SELECT * FROM split_cIDr(r,z)   LOOP RETURN NEXT x;   END LOOP; END LOOP;END $$;

通过修改split_cIDr来获取异常地址数组而不是单个异常地址,然后将每个网络的异常聚合到一个数组中,并为网络调用split_cIDr_array及其异常数组,我将接近每个网络多个异常地址的情况.

总结

以上是内存溢出为你收集整理的PostgreSQL将cidr扩展到单个地址全部内容,希望文章能够帮你解决PostgreSQL将cidr扩展到单个地址所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/sjk/1160999.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-01
下一篇 2022-06-01

发表评论

登录后才能评论

评论列表(0条)

保存