This is an automated email from the ASF dual-hosted git repository.

cgivre pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/drill.git


The following commit(s) were added to refs/heads/master by this push:
     new c1d699571e DRILL-8413: Add DNS Lookup Functions (#2778)
c1d699571e is described below

commit c1d699571e305e86614a35bc3716f6b38227c01c
Author: Charles S. Givre <[email protected]>
AuthorDate: Sun Mar 19 09:53:22 2023 -0400

    DRILL-8413: Add DNS Lookup Functions (#2778)
---
 contrib/udfs/README.md                             |   8 +
 contrib/udfs/pom.xml                               |  18 ++
 .../org/apache/drill/exec/udfs/DNSFunctions.java   | 258 +++++++++++++++++++++
 .../java/org/apache/drill/exec/udfs/DNSUtils.java  | 234 +++++++++++++++++++
 .../apache/drill/exec/udfs/TestDNSFunctions.java   |  79 +++++++
 pom.xml                                            |  28 +++
 6 files changed, 625 insertions(+)

diff --git a/contrib/udfs/README.md b/contrib/udfs/README.md
index 38046f9fc6..23ece7df6b 100644
--- a/contrib/udfs/README.md
+++ b/contrib/udfs/README.md
@@ -436,3 +436,11 @@ The functions are:
 
 [1]: https://github.com/target/huntlib
 
+
+# DNS Functions
+These functions enable DNS research using Drill.
+
+* `getHostName(<IP address>)`:  Returns the host name associated with an IP 
address.
+* `getHostAddress(<host>)`:  Returns an IP address associated with a host name.
+* `dnsLookup(<host>, [<Resolver>])`:  Performs a DNS lookup on a given host.  
You can optionally provide a resolver.  Possible resolver values are: 
`cloudflare`,  `cloudflare_secondary`, `google`, `google_secondary`, 
`verisign`, `verisign_secondary`, `yandex`, `yandex_secondary`.
+* `whois(<host>, [<Resolver>])`:  Performs a whois lookup on the given host 
name.  You can optionally provide a resolver URL. Note that not all providers 
allow bulk automated whois lookups, so please follow the terms fo service for 
your provider.
\ No newline at end of file
diff --git a/contrib/udfs/pom.xml b/contrib/udfs/pom.xml
index 8ab5ac1e0a..63187978ca 100644
--- a/contrib/udfs/pom.xml
+++ b/contrib/udfs/pom.xml
@@ -31,10 +31,22 @@
   <name>Drill : Contrib : UDFs</name>
 
   <dependencies>
+    <dependency>
+      <groupId>dnsjava</groupId>
+      <artifactId>dnsjava</artifactId>
+      <version>3.5.2</version>
+    </dependency>
+
     <dependency>
       <groupId>org.apache.drill.exec</groupId>
       <artifactId>drill-java-exec</artifactId>
       <version>${project.version}</version>
+      <exclusions>
+        <exclusion>
+          <groupId>dnsjava</groupId>
+          <artifactId>dnsjava</artifactId>
+        </exclusion>
+      </exclusions>
     </dependency>
 
     <dependency>
@@ -83,6 +95,12 @@
       <classifier>tests</classifier>
       <version>${project.version}</version>
       <scope>test</scope>
+      <exclusions>
+        <exclusion>
+          <groupId>dnsjava</groupId>
+          <artifactId>dnsjava</artifactId>
+        </exclusion>
+      </exclusions>
     </dependency>
 
     <dependency>
diff --git 
a/contrib/udfs/src/main/java/org/apache/drill/exec/udfs/DNSFunctions.java 
b/contrib/udfs/src/main/java/org/apache/drill/exec/udfs/DNSFunctions.java
new file mode 100644
index 0000000000..6a9e04841d
--- /dev/null
+++ b/contrib/udfs/src/main/java/org/apache/drill/exec/udfs/DNSFunctions.java
@@ -0,0 +1,258 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.drill.exec.udfs;
+
+import io.netty.buffer.DrillBuf;
+import org.apache.drill.exec.expr.DrillSimpleFunc;
+import org.apache.drill.exec.expr.annotations.FunctionTemplate;
+import org.apache.drill.exec.expr.annotations.Output;
+import org.apache.drill.exec.expr.annotations.Param;
+import org.apache.drill.exec.expr.annotations.Workspace;
+import org.apache.drill.exec.expr.holders.NullableVarCharHolder;
+import org.apache.drill.exec.expr.holders.VarCharHolder;
+import org.apache.drill.exec.vector.complex.writer.BaseWriter;
+
+import javax.inject.Inject;
+
+public class DNSFunctions {
+
+  private DNSFunctions() {
+  }
+
+  /* This function gets the host name associated with an IP address */
+  @FunctionTemplate(names = {"get_host_name", "getHostName", 
"reverse_ip_lookup"},
+      scope = FunctionTemplate.FunctionScope.SIMPLE,
+      nulls = FunctionTemplate.NullHandling.NULL_IF_NULL)
+  public static class ReverseIPLookup implements DrillSimpleFunc {
+
+    @Param
+    VarCharHolder ipaddress;
+
+    @Output
+    VarCharHolder out;
+
+    @Inject
+    DrillBuf buffer;
+
+    @Override
+    public void setup() {
+
+    }
+
+    @Override
+    public void eval() {
+      String ipString = 
org.apache.drill.exec.expr.fn.impl.StringFunctionHelpers.toStringFromUTF8(ipaddress.start,
 ipaddress.end, ipaddress.buffer);
+      String hostname = "";
+
+      try {
+        java.net.InetAddress address = 
java.net.InetAddress.getByName(ipString);
+        hostname = address.getHostName();
+
+      } catch (java.net.UnknownHostException e) {
+        hostname = "Unknown host";
+      }
+      out.buffer = buffer;
+      out.start = 0;
+      out.end = hostname.getBytes().length;
+      buffer.setBytes(0, hostname.getBytes());
+    }
+  }
+
+  /* This function takes a host name and returns the IP address associated 
with that host, and "Unknown if there is an error */
+  @FunctionTemplate(names = {"get_host_address", "getHostAddress", 
"host_lookup", "hostLookup"},
+      scope = FunctionTemplate.FunctionScope.SIMPLE,
+      nulls = FunctionTemplate.NullHandling.NULL_IF_NULL)
+  public static class HostLookup implements DrillSimpleFunc {
+
+    @Param
+    VarCharHolder hostname;
+
+    @Output
+    VarCharHolder out;
+
+    @Inject
+    DrillBuf buffer;
+
+    @Override
+    public void setup() {
+
+    }
+
+    @Override
+    public void eval() {
+      String host = 
org.apache.drill.exec.expr.fn.impl.StringFunctionHelpers.toStringFromUTF8(hostname.start,
 hostname.end, hostname.buffer);
+      String result = "";
+      try {
+        java.net.Inet4Address ip = (java.net.Inet4Address) 
java.net.Inet4Address.getByName(host);
+        result = ip.getHostAddress();
+      } catch (Exception e) {
+        result = "Unknown";
+      }
+
+      out.buffer = buffer;
+      out.start = 0;
+      out.end = result.getBytes().length;
+      buffer.setBytes(0, result.getBytes());
+    }
+  }
+
+  /* This function performs a complete DNS lookup */
+  @FunctionTemplate(names = {"dns_lookup", "dnsLookup", "dns"}, scope = 
FunctionTemplate.FunctionScope.SIMPLE)
+  public static class DNSLookupFunctionWithNull implements DrillSimpleFunc {
+
+    @Param
+    NullableVarCharHolder rawDomainName;
+
+    @Output
+    BaseWriter.ComplexWriter out;
+
+    @Inject
+    DrillBuf buffer;
+
+    @Override
+    public void setup() {
+      // no op
+    }
+
+    @Override
+    public void eval() {
+      if (rawDomainName.isSet == 0) {
+        org.apache.drill.exec.vector.complex.writer.BaseWriter.ListWriter 
listWriter = out.rootAsList();
+        org.apache.drill.exec.vector.complex.writer.BaseWriter.MapWriter 
rowMapWriter = listWriter.map();
+        listWriter.startList();
+        rowMapWriter.start();
+        rowMapWriter.end();
+        listWriter.endList();
+        return;
+      }
+
+      try {
+        String domainName = 
org.apache.drill.exec.expr.fn.impl.StringFunctionHelpers.toStringFromUTF8(rawDomainName.start,
 rawDomainName.end, rawDomainName.buffer);
+        org.apache.drill.exec.udfs.DNSUtils.getDNS(domainName, out, buffer);
+      } catch (Exception e) {
+        org.apache.drill.exec.vector.complex.writer.BaseWriter.ListWriter 
listWriter = out.rootAsList();
+        org.apache.drill.exec.vector.complex.writer.BaseWriter.MapWriter 
rowMapWriter = listWriter.map();
+        listWriter.startList();
+        rowMapWriter.start();
+        rowMapWriter.end();
+        listWriter.endList();
+      }
+    }
+  }
+
+  @FunctionTemplate(names = {"dns_lookup", "dnsLookup", "dns"}, scope = 
FunctionTemplate.FunctionScope.SIMPLE)
+  public static class DNSLookupFunctionWithResolver implements DrillSimpleFunc 
{
+
+    @Param
+    NullableVarCharHolder rawDomainName;
+
+    @Param(constant = true)
+    VarCharHolder resolverHolder;
+
+    @Output
+    BaseWriter.ComplexWriter out;
+
+    @Workspace
+    String resolver;
+
+    @Inject
+    DrillBuf buffer;
+
+    @Override
+    public void setup() {
+      resolver = 
org.apache.drill.exec.expr.fn.impl.StringFunctionHelpers.toStringFromUTF8(resolverHolder.start,
 resolverHolder.end, resolverHolder.buffer);
+    }
+
+    @Override
+    public void eval() {
+      if (rawDomainName.isSet == 0) {
+        org.apache.drill.exec.vector.complex.writer.BaseWriter.ListWriter 
listWriter = out.rootAsList();
+        org.apache.drill.exec.vector.complex.writer.BaseWriter.MapWriter 
rowMapWriter = listWriter.map();
+        listWriter.startList();
+        rowMapWriter.start();
+        rowMapWriter.end();
+        listWriter.endList();
+        return;
+      }
+
+      try {
+        String domainName = 
org.apache.drill.exec.expr.fn.impl.StringFunctionHelpers.toStringFromUTF8(rawDomainName.start,
 rawDomainName.end, rawDomainName.buffer);
+        org.apache.drill.exec.udfs.DNSUtils.getDNS(domainName, resolver, out, 
buffer);
+      } catch (Exception e) {
+        org.apache.drill.exec.vector.complex.writer.BaseWriter.ListWriter 
listWriter = out.rootAsList();
+        org.apache.drill.exec.vector.complex.writer.BaseWriter.MapWriter 
rowMapWriter = listWriter.map();
+        listWriter.startList();
+        rowMapWriter.start();
+        rowMapWriter.end();
+        listWriter.endList();
+      }
+    }
+  }
+
+  @FunctionTemplate(names = {"whois"},
+      scope = FunctionTemplate.FunctionScope.SIMPLE)
+  public static class WhoIsFunction implements DrillSimpleFunc {
+
+    @Param
+    NullableVarCharHolder rawDomainName;
+
+    @Output
+    BaseWriter.ComplexWriter out;
+
+    @Inject
+    DrillBuf buffer;
+    @Override
+    public void setup() {
+      // No op
+    }
+
+    @Override
+    public void eval() {
+      String domain = 
org.apache.drill.exec.expr.fn.impl.StringFunctionHelpers.toStringFromUTF8(rawDomainName.start,
 rawDomainName.end, rawDomainName.buffer);
+      org.apache.drill.exec.udfs.DNSUtils.whois(domain, out, buffer);
+    }
+  }
+
+  @FunctionTemplate(names = {"whois"}, scope = 
FunctionTemplate.FunctionScope.SIMPLE)
+  public static class WhoIsFunctionWithNonDefaultServer implements 
DrillSimpleFunc {
+
+    @Param
+    NullableVarCharHolder rawDomainName;
+
+    @Param(constant = true)
+    VarCharHolder serverHolder;
+
+    @Output
+    BaseWriter.ComplexWriter out;
+
+    @Inject
+    DrillBuf buffer;
+    @Override
+    public void setup() {
+      // No op
+    }
+
+    @Override
+    public void eval() {
+      String domain = 
org.apache.drill.exec.expr.fn.impl.StringFunctionHelpers.toStringFromUTF8(rawDomainName.start,
 rawDomainName.end, rawDomainName.buffer);
+      String server =  
org.apache.drill.exec.expr.fn.impl.StringFunctionHelpers.toStringFromUTF8(serverHolder.start,
 serverHolder.end, serverHolder.buffer);
+      org.apache.drill.exec.udfs.DNSUtils.whois(domain, server, out, buffer);
+    }
+  }
+}
diff --git 
a/contrib/udfs/src/main/java/org/apache/drill/exec/udfs/DNSUtils.java 
b/contrib/udfs/src/main/java/org/apache/drill/exec/udfs/DNSUtils.java
new file mode 100644
index 0000000000..08890350fd
--- /dev/null
+++ b/contrib/udfs/src/main/java/org/apache/drill/exec/udfs/DNSUtils.java
@@ -0,0 +1,234 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.drill.exec.udfs;
+
+import io.netty.buffer.DrillBuf;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.net.whois.WhoisClient;
+import org.apache.drill.common.exceptions.UserException;
+import org.apache.drill.exec.expr.holders.VarCharHolder;
+import org.apache.drill.exec.vector.complex.writer.BaseWriter.ComplexWriter;
+import org.apache.drill.exec.vector.complex.writer.BaseWriter.ListWriter;
+import org.apache.drill.exec.vector.complex.writer.BaseWriter.MapWriter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.xbill.DNS.Lookup;
+import org.xbill.DNS.Record;
+import org.xbill.DNS.SimpleResolver;
+import org.xbill.DNS.TextParseException;
+import org.xbill.DNS.Type;
+
+import java.io.IOException;
+import java.net.SocketException;
+import java.net.UnknownHostException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Utility class which contains various methods for performing DNS resolution 
and WHOIS lookups in Drill UDFs.
+ */
+public class DNSUtils {
+
+  private static final Logger logger = LoggerFactory.getLogger(DNSUtils.class);
+  /**
+   *  A list of known DNS resolvers.
+   */
+  private static final Map<String, String> KNOWN_RESOLVERS = new HashMap<>();
+  static {
+    KNOWN_RESOLVERS.put("cloudflare", "1.1.1.1");
+    KNOWN_RESOLVERS.put("cloudflare_secondary", "1.0.0.1");
+    KNOWN_RESOLVERS.put("google", "8.8.8.8");
+    KNOWN_RESOLVERS.put("google_secondary", "8.8.4.4");
+    KNOWN_RESOLVERS.put("verisign", "64.6.64.6");
+    KNOWN_RESOLVERS.put("verisign_secondary", "64.6.65.6");
+    KNOWN_RESOLVERS.put("yandex", "77.88.8.8");
+    KNOWN_RESOLVERS.put("yandex_secondary", "77.88.8.1");
+  }
+
+  private static final Pattern WHOIS_REGEX = Pattern.compile("([a-zA-Z0-9_ 
]+):\\s(.+)");
+
+  /**
+   * Performs the actual DNS lookup and returns the results in a {@link 
ComplexWriter}.  If the resolver
+   * is not null, we will use the provided resolver.  If a resolver is not 
provided, we'll use the local cache.
+   * <p>
+   *   Relating to the resolver, you can specify an IP or host, or you can use 
a name of a known resolver.  Known resolvers are:
+   *   <ul>
+   *     <li>cloudflare</li>
+   *     <li>cloudflare_secondary</li>
+   *     <li>google</li>
+   *     <li>google_secondary</li>
+   *     <li>verisign</li>
+   *     <li>verisign_secondary</li>
+   *     <li>yandex</li>
+   *     <li>yandex_secondary</li>
+   *   </ul>
+   *
+   * </p>
+   * @param domainName A {@link String} of a domain for which you want to look 
up.
+   * @param resolverName A {@link String} containing the resolver name.
+   * @param out The {@link ComplexWriter} to which the DNS results will be 
written.
+   * @param buffer The {@link DrillBuf} to which the data will be written.
+   * @throws TextParseException If the resolver is unparsable, throw an 
exception.
+   */
+  public static void getDNS(String domainName, String resolverName, 
ComplexWriter out, DrillBuf buffer) throws TextParseException {
+
+    Lookup look = new Lookup(domainName, Type.ANY);
+    String resolverIP;
+    // Add the resolver if it is provided.
+    if (StringUtils.isNotEmpty(resolverName)) {
+      // Create a resolver
+      resolverIP = KNOWN_RESOLVERS.getOrDefault(resolverName.toLowerCase(), 
resolverName);
+      try {
+        SimpleResolver resolver = new SimpleResolver(resolverIP);
+        look.setResolver(resolver);
+      } catch (UnknownHostException e) {
+        throw UserException.connectionError(e)
+            .message("Cannot find resolver: " + resolverName)
+            .build(logger);
+      }
+    }
+
+    Record[] records = look.run();
+
+    // Initialize writers
+    ListWriter listWriter = out.rootAsList();
+    MapWriter rowMapWriter = listWriter.map();
+    // If there are no records, return an empty list.
+    if (records == null) {
+      listWriter.startList();
+      rowMapWriter.start();
+      rowMapWriter.end();
+      listWriter.endList();
+      return;
+    }
+
+    for (Record record : records) {
+      VarCharHolder fieldHolder = new VarCharHolder();
+
+      rowMapWriter.start();
+      byte[] name = record.getName().toString().getBytes();
+      buffer = buffer.reallocIfNeeded(name.length);
+      buffer.setBytes(0, name);
+      rowMapWriter.varChar("name").writeVarChar(0, name.length, buffer);
+
+      byte[] completeRecord = record.toString().getBytes();
+      buffer = buffer.reallocIfNeeded(completeRecord.length);
+      buffer.setBytes(0, completeRecord);
+      fieldHolder.start = 0;
+      fieldHolder.end = completeRecord.length;
+      fieldHolder.buffer = buffer;
+      rowMapWriter.varChar("record").write(fieldHolder);
+
+      rowMapWriter.bigInt("ttl").writeBigInt(record.getTTL());
+
+      byte[] type = Type.string(record.getType()).getBytes();
+      buffer = buffer.reallocIfNeeded(type.length);
+      buffer.setBytes(0, type);
+      rowMapWriter.varChar("type").writeVarChar(0, type.length, buffer);
+
+      byte[] rdata = record.rdataToString().getBytes();
+      buffer.reallocIfNeeded(rdata.length);
+      buffer.setBytes(0, rdata);
+      rowMapWriter.varChar("rdata").writeVarChar(0, rdata.length, buffer);
+      rowMapWriter.end();
+    }
+  }
+
+  /**
+   * Performs the actual DNS lookup and returns the results in a {@link 
ComplexWriter}.  Uses the local cache as the
+   * DNS resolver.
+   * @param domainName A {@link String} of a domain for which you want to look 
up.
+   * @param out The {@link ComplexWriter} to which the DNS results will be 
written.
+   * @param buffer The {@link DrillBuf} to which the data will be written.
+   * @throws TextParseException If the domain is unparsable, throw an 
exception.
+   */
+  public static void getDNS(String domainName, ComplexWriter out, DrillBuf 
buffer) throws TextParseException {
+    getDNS(domainName, null, out, buffer);
+  }
+
+  /**
+   * Performs a WHOIS lookup and populates the results into a Drill map.  This 
method uses a default server.
+   * @param domainName The input domain name.
+   * @param out A {@link ComplexWriter} to which the results will be written
+   * @param buffer A {@link DrillBuf} which contains the output
+   */
+  public static void whois(String domainName, ComplexWriter out, DrillBuf 
buffer) {
+    whois(domainName, WhoisClient.DEFAULT_HOST, out, buffer);
+  }
+
+  /**
+   * Performs a WHOIS lookup and populates the results into a Drill map.  This 
method uses a default server.
+   * @param domainName The input domain name.
+   * @param whoisServer A {@link String} containing the whois server
+   * @param out A {@link ComplexWriter} to which the results will be written
+   * @param buffer A {@link DrillBuf} which contains the output
+   */
+  public static void whois(String domainName, String whoisServer, 
ComplexWriter out, DrillBuf buffer) {
+    WhoisClient whois = new WhoisClient();
+    MapWriter mapWriter = out.rootAsMap();
+
+    try {
+      whois.connect(whoisServer);
+      String whoisData = whois.query(domainName);
+      whois.disconnect();
+
+      // Split the result line by line
+      String[] lines = whoisData.split("\\R");
+
+      // Now iterate over those lines
+      mapWriter.start();
+      for (String line : lines) {
+        Matcher matcher = WHOIS_REGEX.matcher(line);
+        boolean matchFound = matcher.find();
+
+        // Map to output
+        if (matchFound) {
+          String key = matcher.group(1);
+          String value = matcher.group(2);
+
+          // Skip useless keys
+          if (key.contentEquals("NOTICE") ||
+              key.contentEquals("by the following terms of use") ||
+              key.contentEquals("TERMS OF USE") ||
+              key.contentEquals("to")
+          ) {
+            continue;
+          }
+
+          // Write to output map
+          byte[] valueBytes = value.getBytes();
+          buffer = buffer.reallocIfNeeded(valueBytes.length);
+          buffer.setBytes(0, valueBytes);
+          mapWriter.varChar(key.trim()).writeVarChar(0, valueBytes.length, 
buffer);
+        }
+      }
+      mapWriter.end();
+    } catch (SocketException e) {
+      throw UserException.connectionError(e)
+          .message("Error connecting to WHOIS server: " + e.getMessage())
+          .build(logger);
+    } catch (IOException e) {
+      throw UserException.connectionError(e)
+          .message("Error retrieving WHOIS results: " + e.getMessage())
+          .build(logger);
+    }
+  }
+}
diff --git 
a/contrib/udfs/src/test/java/org/apache/drill/exec/udfs/TestDNSFunctions.java 
b/contrib/udfs/src/test/java/org/apache/drill/exec/udfs/TestDNSFunctions.java
new file mode 100644
index 0000000000..8ffd907924
--- /dev/null
+++ 
b/contrib/udfs/src/test/java/org/apache/drill/exec/udfs/TestDNSFunctions.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.drill.exec.udfs;
+
+import org.apache.drill.categories.SqlFunctionTest;
+import org.apache.drill.categories.UnlikelyTest;
+import org.apache.drill.test.ClusterFixture;
+import org.apache.drill.test.ClusterFixtureBuilder;
+import org.apache.drill.test.ClusterTest;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+@Category({UnlikelyTest.class, SqlFunctionTest.class})
+public class TestDNSFunctions extends ClusterTest {
+
+  @BeforeClass
+  public static void setup() throws Exception {
+    ClusterFixtureBuilder builder = ClusterFixture.builder(dirTestWatcher);
+    startCluster(builder);
+  }
+
+  @Test
+  public void testGetHostAddress() throws Exception {
+    String query = "select get_host_address('apache.org') as hostname from 
(values(1))";
+    
testBuilder().sqlQuery(query).ordered().baselineColumns("hostname").baselineValues("151.101.2.132").go();
+
+    query = "select get_host_address('google') as hostname from (values(1))";
+    
testBuilder().sqlQuery(query).ordered().baselineColumns("hostname").baselineValues("Unknown").go();
+
+    query = "select get_host_address('') as hostname from (values(1))";
+    
testBuilder().sqlQuery(query).ordered().baselineColumns("hostname").baselineValues("127.0.0.1").go();
+
+    query = "select get_host_address(cast(null as varchar)) as hostname from 
(values(1))";
+    
testBuilder().sqlQuery(query).ordered().baselineColumns("hostname").baselineValues((String)null).go();
+  }
+
+  @Test
+  public void testGetHostName() throws Exception {
+    String query = "select get_host_name('142.251.16.102') as hostname from 
(values(1))";
+    
testBuilder().sqlQuery(query).ordered().baselineColumns("hostname").baselineValues("bl-in-f102.1e100.net").go();
+
+    query = "select get_host_name('sdfsdfafsdfadfdsf') as hostname from 
(values(1))";
+    
testBuilder().sqlQuery(query).ordered().baselineColumns("hostname").baselineValues("Unknown
 host").go();
+
+    query = "select get_host_name('') as hostname from (values(1))";
+    
testBuilder().sqlQuery(query).ordered().baselineColumns("hostname").baselineValues("localhost").go();
+
+    query = "select get_host_name(cast(null as varchar)) as hostname from 
(values(1))";
+    
testBuilder().sqlQuery(query).ordered().baselineColumns("hostname").baselineValues((String)null).go();
+  }
+
+  @Test
+  public void testDNSLookup() throws Exception {
+    String sql = "SELECT dns_lookup('google.com') AS dns_info FROM 
(VALUES(1))";
+    testBuilder().sqlQuery(sql).ordered().baselineColumns("dns_info").go();
+  }
+
+  @Test
+  public void testWhois() throws Exception {
+    String sql = "SELECT whois('google.com') AS whois FROM (VALUES(1))";
+    testBuilder().sqlQuery(sql).ordered().baselineColumns("whois").go();
+  }
+}
diff --git a/pom.xml b/pom.xml
index bc8f927ba4..4d2075e23b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -2207,6 +2207,10 @@
                 <groupId>commons-httpclient</groupId>
                 <artifactId>commons-httpclient</artifactId>
               </exclusion>
+              <exclusion>
+                <groupId>dnsjava</groupId>
+                <artifactId>dnsjava</artifactId>
+              </exclusion>
             </exclusions>
           </dependency>
           <dependency>
@@ -2374,6 +2378,10 @@
                 <groupId>commons-httpclient</groupId>
                 <artifactId>commons-httpclient</artifactId>
               </exclusion>
+              <exclusion>
+                <groupId>dnsjava</groupId>
+                <artifactId>dnsjava</artifactId>
+              </exclusion>
             </exclusions>
           </dependency>
           <dependency>
@@ -3034,6 +3042,10 @@
                 <groupId>commons-httpclient</groupId>
                 <artifactId>commons-httpclient</artifactId>
               </exclusion>
+              <exclusion>
+                <groupId>dnsjava</groupId>
+                <artifactId>dnsjava</artifactId>
+              </exclusion>
             </exclusions>
           </dependency>
           <dependency>
@@ -3541,6 +3553,10 @@
                 <groupId>org.mortbay.jetty</groupId>
                 <artifactId>servlet-api-2.5</artifactId>
               </exclusion>
+              <exclusion>
+                <groupId>dnsjava</groupId>
+                <artifactId>dnsjava</artifactId>
+              </exclusion>
             </exclusions>
           </dependency>
           <dependency>
@@ -3661,6 +3677,10 @@
                 <groupId>org.mortbay.jetty</groupId>
                 <artifactId>servlet-api-2.5</artifactId>
               </exclusion>
+              <exclusion>
+                <groupId>dnsjava</groupId>
+                <artifactId>dnsjava</artifactId>
+              </exclusion>
             </exclusions>
           </dependency>
           <dependency>
@@ -3991,6 +4011,10 @@
                 <groupId>commons-httpclient</groupId>
                 <artifactId>commons-httpclient</artifactId>
               </exclusion>
+              <exclusion>
+                <groupId>dnsjava</groupId>
+                <artifactId>dnsjava</artifactId>
+              </exclusion>
             </exclusions>
           </dependency>
           <dependency>
@@ -4240,6 +4264,10 @@
                 <groupId>javax.servlet</groupId>
                 <artifactId>servlet-api</artifactId>
               </exclusion>
+              <exclusion>
+                <groupId>dnsjava</groupId>
+                <artifactId>dnsjava</artifactId>
+              </exclusion>
             </exclusions>
           </dependency>
           <dependency>

Reply via email to