Как вернуть логическое значение, если подзапрос возвращает какой-либо результат - PullRequest
0 голосов
/ 10 мая 2019

Я пытаюсь написать запрос для проверки таблицы IP-адресов по таблице перекрывающихся сетевых блоков.Отдельные блоки сети могут быть помечены как активные или неактивные с помощью BOOLEAN.Запрос аудита должен возвращать BOOLEAN как active в зависимости от активного столбца в таблице netblock.Если для какого-либо сетевого блока для столбца active установлено значение FALSE, то IP-адреса, содержащиеся в сетевом блоке, должны указывать как active, установленный в значение FALSE.

Ниже приведено определение таблицы ip:

CREATE TABLE IF NOT EXISTS ip
(  
   address          INET            NOT NULL UNIQUE,
   modified         timestamp       WITH TIME ZONE NOT NULL
                                    DEFAULT TIMESTAMP 'epoch',
   username         VARCHAR(64),
   acctSession      VARCHAR(32),
   nasId            INTEGER,
   PRIMARY KEY      ( address ),
   FOREIGN KEY      ( nasId )
      REFERENCES    nas
                    ( id )
);

Ниже приведены примеры записей в ip:

radius_ippool=> SELECT * FROM ip ORDER BY address;
   address    |           modified            |      username      |       acctsession       | nasid
--------------+-------------------------------+--------------------+-------------------------+-------
 209.193.4.0  | 1970-01-01 00:00:00-10        |                    |                         |
 209.193.4.1  | 1970-01-01 00:00:00-10        |                    |                         |
 209.193.4.2  | 1970-01-01 00:00:00-10        |                    |                         |
 209.193.4.3  | 1970-01-01 00:00:00-10        |                    |                         |
 209.193.4.4  | 1970-01-01 00:00:00-10        |                    |                         |
 209.193.4.5  | 1970-01-01 00:00:00-10        |                    |                         |
 209.193.4.6  | 1970-01-01 00:00:00-10        |                    |                         |
 209.193.4.7  | 1970-01-01 00:00:00-10        |                    |                         |
 209.193.4.8  | 2019-05-09 11:55:20.456856-08 | jdoe8@example.net  | aqaqqaasdqweaasdqa8     |     3
 209.193.4.9  | 2019-05-09 11:55:20.638136-08 | jdoe9@aexample.net | qweadszcxqweasdzcx9     |     3
 209.193.4.10 | 2019-05-09 11:55:20.85176-08  | jdoe10@example.net | user:jdoe10@example.net |     3
 209.193.4.11 | 2019-05-09 11:55:20.872469-08 | jdoe11@example.net | user:jdoe11@example.net |     3
 209.193.4.12 | 2019-05-09 11:55:20.894765-08 | jdoe12@example.net | user:jdoe12@example.net |     3
 209.193.4.13 | 2019-05-09 11:55:21.02472-08  | jdoe13@example.net | user:jdoe13@example.net |     3
 209.193.4.14 | 1970-01-01 00:00:00-10        |                    |                         |
 209.193.4.15 | 1970-01-01 00:00:00-10        |                    |                         |
(16 rows)

Ниже приводится определение таблицы netblock:

CREATE TABLE IF NOT EXISTS netblock
(  
   id               SERIAL,
   network          CIDR            NOT NULL UNIQUE,
   poolId           INTEGER         NOT NULL,
   regionId         INTEGER,
   active           BOOLEAN         NOT NULL DEFAULT TRUE,
   description      VARCHAR(256),
   PRIMARY KEY      ( id ),
   FOREIGN KEY      ( poolId )
      REFERENCES    pool
                    ( id ),
   FOREIGN KEY      ( regionId )
      REFERENCES    region
                    ( id )
);

Ниже приведены примеры записей в таблице netblock:

radius_ippool=> SELECT * FROM netblock ORDER BY network;
 id |    network     | poolid | regionid | active |              description
----+----------------+--------+----------+--------+----------------------------------------
  1 | 209.193.4.0/28 |      1 |        2 | t      |
  2 | 209.193.4.0/29 |      1 |        2 | f      | Reserved for engineering test accounts
  4 | 209.193.4.4/30 |      1 |        2 | t      |
(3 rows)

Я разработал запрос для перечисления всех «активных» и «неактивных» IP-адресов в отдельных запросах:

-- query to return "inactive" IP addresses
SELECT DISTINCT      netblock.regionId AS  regionId,
                     ip.address        AS  ipAddress,
                     netblock.active   AS  active
   FROM              ip
   INNER JOIN        netblock
      ON             ip.address        <<= netblock.network
   WHERE             netblock.active   =   FALSE
   ORDER BY          ipAddress;

-- query to return "active" IP addresses
SELECT DISTINCT      netblock.regionId AS  regionId,
                     ip.address        AS  ipAddress,
                     netblock.active   AS  active
   FROM              ip
   INNER JOIN        netblock       
      ON             ip.address        <<= netblock.network
   WHERE             netblock.active   =   TRUE
      AND            ip.address             NOT IN
                     (
                       SELECT          address AS ipAddress
                          FROM         ip
                          INNER JOIN   netblock
                             ON        ip.address          <<= netblock.network
                                AND    netblock.active     =   FALSE
                     )
   ORDER BY          ipAddress;

Результаты указанного выше запроса:

 regionid |  ipaddress  | active
----------+-------------+--------
        2 | 209.193.4.0 | f
        2 | 209.193.4.1 | f
        2 | 209.193.4.2 | f
        2 | 209.193.4.3 | f
        2 | 209.193.4.4 | f
        2 | 209.193.4.5 | f
        2 | 209.193.4.6 | f
        2 | 209.193.4.7 | f
(8 rows)

 regionid |  ipaddress   | active
----------+--------------+--------
        2 | 209.193.4.8  | t
        2 | 209.193.4.9  | t
        2 | 209.193.4.10 | t
        2 | 209.193.4.11 | t
        2 | 209.193.4.12 | t
        2 | 209.193.4.13 | t
        2 | 209.193.4.14 | t
        2 | 209.193.4.15 | t
(8 rows)

Как заменить статическое значение unknown для столбца active в следующей таблице, поставив в очередь таблицу сетевых блоков для inactvie / активных сетевых блоков?

SELECT DISTINCT      netblock.regionId AS regionId,
                     ip.address        AS address,
                     'unknown'         AS active,
                     (
                       nasId           IS NOT NULL
                       OR
                       acctSession     IS NOT NULL
                     )                 AS assigned,
                     ip.modified       AS modified,
                     ip.nasid          AS nasId,
                     ip.username       AS username,
                     ip.acctSession    AS acctSession
   FROM              ip
   INNER JOIN        netblock
      ON             ip.address        <<= netblock.network
   ORDER BY          address;

Результаты вышеуказанного запроса:

 regionid |   address    | active  | assigned |           modified            | nasid |      username      |       acctsession
----------+--------------+---------+----------+-------------------------------+-------+--------------------+-------------------------
        2 | 209.193.4.0  | unknown | f        | 1970-01-01 00:00:00-10        |       |                    |
        2 | 209.193.4.1  | unknown | f        | 1970-01-01 00:00:00-10        |       |                    |
        2 | 209.193.4.2  | unknown | f        | 1970-01-01 00:00:00-10        |       |                    |
        2 | 209.193.4.3  | unknown | f        | 1970-01-01 00:00:00-10        |       |                    |
        2 | 209.193.4.4  | unknown | f        | 1970-01-01 00:00:00-10        |       |                    |
        2 | 209.193.4.5  | unknown | f        | 1970-01-01 00:00:00-10        |       |                    |
        2 | 209.193.4.6  | unknown | f        | 1970-01-01 00:00:00-10        |       |                    |
        2 | 209.193.4.7  | unknown | f        | 1970-01-01 00:00:00-10        |       |                    |
        2 | 209.193.4.8  | unknown | t        | 2019-05-09 11:55:20.456856-08 |     3 | jdoe8@example.net  | aqaqqaasdqweaasdqa8
        2 | 209.193.4.9  | unknown | t        | 2019-05-09 11:55:20.638136-08 |     3 | jdoe9@aexample.net | qweadszcxqweasdzcx9
        2 | 209.193.4.10 | unknown | t        | 2019-05-09 11:55:20.85176-08  |     3 | jdoe10@example.net | user:jdoe10@example.net
        2 | 209.193.4.11 | unknown | t        | 2019-05-09 11:55:20.872469-08 |     3 | jdoe11@example.net | user:jdoe11@example.net
        2 | 209.193.4.12 | unknown | t        | 2019-05-09 11:55:20.894765-08 |     3 | jdoe12@example.net | user:jdoe12@example.net
        2 | 209.193.4.13 | unknown | t        | 2019-05-09 11:55:21.02472-08  |     3 | jdoe13@example.net | user:jdoe13@example.net
        2 | 209.193.4.14 | unknown | f        | 1970-01-01 00:00:00-10        |       |                    |
        2 | 209.193.4.15 | unknown | f        | 1970-01-01 00:00:00-10        |       |                    |
(16 rows)

1 Ответ

1 голос
/ 10 мая 2019

Вы можете использовать ALL и подзапрос, чтобы проверить, активны ли все сетевые блоки, в которых находится IP.

SELECT ...
       true = ALL (SELECT nb2.active
                          FROM netblock nb2
                          WHERE ip.address <<= nb2.network) active,
       ...

В качестве альтернативы вы можете использовать NOT EXISTS:

SELECT ...
       NOT EXISTS (SELECT *
                          FROM netblock nb2
                          WHERE ip.address <<= nb2.network
                                AND NOT nb2.active) active,
       ...
...