Find an Answer
join() — traverses a tree and concatenates all values with a provided string, or selects data from two or more paths and joins the data to make the result complete.
The join() function returns a string and takes 2 parameters, a tree and a string:
string join(tree input, string input)
The join() function returns a string.
The join() function traverses a tree and concatenates all values with a provided string, or selects data from two or more paths and joins the data to make the result complete. The join() function must include 2 parameters, a tree or path, and a string.
You can try the following examples against your own data in the GoToAssist search field, or against fictitious data in the Query Sandbox:
Query: What are the IP addresses of all the interfaces?
SELECT join(interface/inet/ip_address, ', ') as ip FROM /network/device
This query uses the join() function to traverse a tree and concatenate all values with a provided string.
The PQL join() function is useful in situations like this one, where you don't know exactly what a PQL tree holds, and have no clear logic for choosing a sub-tree, such as if you want to print the IP address of a device with multiple interfaces.
Results: Depending on the database, this query returns results similar to this:
row:
ip: null
row:
ip: 10.10.10.10
row:
ip: 10.10.10.20
row:
ip: 10.10.10.30
row:
ip: 10.10.10.77, 10.10.10.78, 10.10.10.79
row:
ip: 10.10.10.93, 10.10.10.94
. . .
Note that devices with multiple interfaces are represented by rows with multiple IP addresses.
Query: What ports are open on the first network device?
SELECT coalesce(system/dns_name, first(interface/inet/ip_address)) as "Device", join(evidence/tcp_port/param/port, ',') as "TCP Ports", join(evidence/udp_port/param/port, ',') as "UDP Ports" FROM /network/device ORDER BY 1
This query shows the open TCP and UDP ports for the first device on the network. The query uses the join() function to traverse the tree and concatenate all values with the provided string.
Results: Depending on the database, this query returns results similar to this:
row Device 10.10.10.102 TCP Ports 9100,631,515,514,80,23,21 UDP Ports 161 row Device 10.10.10.111 TCP Ports 111,81,80,22 UDP Ports null row Device 10.10.10.13 TCP Ports 280,80,23 UDP Ports 161 row Device 10.10.10.14 TCP Ports 23 UDP Ports 161 . . .
Query: Which hosts have been discovered on my network?
SELECT nvl(system/dns_name,system/name) as "Name", join(interface/inet/ip_address, ', ') as "IP Address", system/computed_vendor as "Vendor", last_seen FROM /network/device WHERE system is not null
This query finds all the devices found on your network. The query uses the join() function to select data from multiple paths and combine the data to make the result complete.
Results: Depending on the database, this query returns results similar to this:
Name firewall.altoworks.local IP Address 1.4.6.26, 1.2.3.66, 192.168.1.2, 192.168.1.1 Vendor Juniper Networks last_seen 2008-06-18T17:22:27.0000000Z row Name HP ProCurve IP Address 192.168.1.4, 192.168.1.4 Vendor Hewlett-Packard last_seen 2008-06-18T17:29:10.0000000Z row Name pluto.altoworks.local IP Address 192.168.1.120 Vendor Ubuntu last_seen 2008-06-18T18:22:36.0000000Z row Name neptune IP Address 192.168.1.119, 127.0.0.1 Vendor Lanier last_seen 2008-06-18T17:40:16.0000000Z . . .
Query: Show me everything on my network, starting from root.
SELECT join(/, ',') FROM /
This query is impossibly broad and would be very expensive to run. The join function truncates at 500 characters to avoid problems with a query like this one.
Results: Depending on the database, this query returns results similar to this:
row
join(, ,)44,67,66,2007/02/01 17:07:49,2008/04/04
14:57:19,MSSQLSvc/paris.altoworks.local,
HOST/paris.altoworks.local,HOST/VOLANS,5.1
(2600),Service Pack 2,Windows XP Professional,79,
192,54,211,0,62,177,69,133,162,71,5,16,214,175,75,
VOLANS,2008/01/31 16:53:14,2008/01/31 16:53:14,
2008/01/31 16:53:14,1601/01/08 -15:-10:-55,
paris.altoworks.local,CN=VOLANS,OU=Altoworks,
DC=altoworks,DC=local,VOLANS$,VOLANS$,1,5,0,0,0,0,
0,5,21,0,0,0,22,242,224,162,94,55,174,52,101,104,1,
167,237,4,0,0,top,person,organizationalPerson,user,
computer . . .
Query: What ports are open on each machine on the network?
SELECT nvl(system/dns_name,
first(interface/inet/ip_address)) as "Device",
join(evidence/tcp_port/param/port, ',')
as "Open TCP Ports",
join(evidence/udp_port/param/port, ',')
as "Open UDP Ports"
from /network/device
order by 1
Since the nvl() and coalesce() functions are interchangeable, they work the same way in the same query:
SELECT coalesce(system/dns_name,
first(interface/inet/ip_address)) as "Device",
join(evidence/tcp_port/param/port, ',')
as "Open TCP Ports",
join(evidence/udp_port/param/port, ',')
as "Open UDP Ports"
from /network/device
order by 1
Both queries display the name of every device on the network, alongside the TCP and UDP ports that are open on that device.
In the first line, either the nvl() or coalesce() function identifies the device by the DNS name or IP address. The coalesce() function uses the first non-NULL value, which displays the IP address for devices that don't have DNS names. The first() function is applied to the IP address so that the query only uses the first IP address of the device. The next 2 lines gather the lists of TCP and UDP ports that are open. The join() function takes the port trees and turns them into comma-separated lists. The data comes from the /network/device level of the tree, and put in order by the first column.
Results: Depending on the database, this query returns results similar to this:
row Device 10.10.10.102 Open TCP Ports 9100,631,515,514,80,23,21 Open UDP Ports 161 row Device 10.10.10.111 Open TCP Ports 111,81,80,22 Open UDP Ports null row Device 10.10.10.13 Open TCP Ports 280,80,23 Open UDP Ports null . . .
These results are easier to read when converted to a table:
Query: What ports are open on a specific device?
The query from Example 5 can be modified so you can look up the open ports on any single device. This is handy to post on a dashboard, and uses a search template so you can choose which device to display by selecting the IP address of that device.
SELECT coalesce(system/dns_name,
first(interface/inet/ip_address)) as "Device",
join(evidence/tcp_port/param/port, ',')
as "Open TCP Ports",
join(evidence/udp_port/param/port, ',')
as "Open UDP Ports"
from /network/device
where interface/inet/ip_address =
'[[1param|All hosts|select first(interface/inet/ip_address),
coalesce(system/dns_name || ' - ' ||
first(interface/inet/ip_address),
first(interface/inet/ip_address))
from /network/device
where interface/inet/ip_address is not null
order by 2]]'
order by 1
To see other PQL functions, see Functions.
Related topics