
[[filters]]
= Filters
:description: Learn about the database schema file in OpenNMS {page-component-title} and how to use filters (rules) to select IP addresses from the ipinterface table.

A filter (also known as a rule) is a shorthand expression that allows you to select IP addresses from the ipinterface table.
The rule builds the WHERE clause of a SQL query.
The https://github.com/OpenNMS/opennms/blob/develop/opennms-config/src/main/resources/database-schema.xml[database-schema.xml] file in the `/opt/opennms/etc` directory informs the filter parser which tables can be used in an expression.

== Explanation of database-schema.xml file

Each table the filter code uses appears in a `<table>` tag.
If a table has an attribute of `visible=false`, then none of the columns in that table can be used in the WHERE clause and thus cannot appear in the rule.
You will get a syntax exception if it sees any non-visible columns in the rule.
The same applies to a non-visible column in a table.

A `<join>` tag tells the filter module how to relate this table to the ipinterface table. 

=== Operators

You can use C/Java-style comparison operators with data types they apply to.
(You can use `==` and `!=` on strings, as well as the SQL `LIKE` keyword.)

For LIKE comparisons, the character "_" matches any single character and "%" matches any series of characters (or none at all).
For example, "F_o%"" matches "Foo", "Foom", and "Flowers" but not "Foip".

To handle NULL values (which include cases where you've joined across to a table where there is no matching row), use the `IS NULL` and `IS NOT NULL` operators.
Comparing a null value to anything with any other operator always returns false, so `categoryName != 'SomeCategory'` will not return anything with a null categoryName.
Instead, you would need to use `categoryName != 'SomeCategory' | categoryName IS NULL` to exclude all nodes that are tagged with `SomeCategory`.

You can use parentheses to group expressions and can apply boolean operators anywhere in an expression.

NOTE: In a departure from C/Java convention, boolean operators are single characters rather than double, so they look more like the bitwise arithmetic operators in C:

[options="header, autowidth"]
|===
| Operator | Bitwise Expression
| AND      | &amp;
| OR       | \|
| NOT      | !
|===

Each comparison is joined together with the `&` or `|` operators meaning logical AND, logical OR operations.
Anything delimited by an `&` or `|` character gets translated into a sub-select that selects IP addresses based on the comparison for that clause.

NOTE: Depending on the format you use in your rules, you might need to escape your AND operator.
See xref:configuration/filters/rule-formats.adoc#filter-rule-format[Rule_formats].

Here is an example:

Rule:

`(nodesysname == 'something') & (snmpifdescr == 'something else')`

SQL

[source, sql]
----
SELECT DISTINCT ipInterface.ipAddr
FROM ipinterface
JOIN node ON (ipInterface.nodeID = node.nodeID)
JOIN snmpInterface ON (ipInterface.snmpinterfaceid = snmpInterface.id)
WHERE (node.nodesysname = 'something')
AND (snmpInterface.snmpifdescr = 'something else')
LIMIT 1
----

The IPLIKE function is shorthand to call a PostgreSQL function that was written in C to compare ipaddresses using *, lists, and ranges.
isService is shorthand to build a complicated join to match on a service name.
notisService is also available.
