From cf83de21d3513ae5ebec20d7509396e09571858b Mon Sep 17 00:00:00 2001 From: Muhammet Orazov Date: Wed, 2 Dec 2020 14:03:29 +0100 Subject: [PATCH] #85: Added Databricks cluster deployment to the user guide (#86) It adds short description how to setup the connector as dependency in the Databrick cluster. It also updates the Spark version to `3.0.1` and Exasol JDBC version to `7.0.4`. Switches Java JDK version to 11 in the Travis CI. --- .gitignore | 1 + .travis.yml | 33 +++++++----------- doc/changes/changelog.md | 1 + doc/changes/changes_1.0.0.md | 33 ++++++++++++++++++ doc/images/databricks-deployment.png | Bin 0 -> 35961 bytes doc/user_guide/user_guide.md | 23 ++++++++++++ project/Dependencies.scala | 14 ++++---- project/Settings.scala | 26 ++++++++++++++ project/build.properties | 2 +- project/plugins.sbt | 12 +++---- sbtx | 8 ++--- scripts/ci.sh | 4 +-- .../containers/ExasolDockerContainer.java | 2 +- .../com/exasol/spark/rdd/ExasolRDD.scala | 4 +-- .../com/exasol/spark/util/Converter.scala | 11 ------ .../com/exasol/spark/util/FiltersSuite.scala | 8 ++--- 16 files changed, 122 insertions(+), 60 deletions(-) create mode 100644 doc/changes/changes_1.0.0.md create mode 100644 doc/images/databricks-deployment.png diff --git a/.gitignore b/.gitignore index f110044b..a101a857 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ project/.gnupg/local* project/target target/ .history +.bsp # Java *.class diff --git a/.travis.yml b/.travis.yml index 6573eac2..e154407d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,29 +9,22 @@ addons: packages: - shellcheck -before_install: - - git fetch --tags - - docker pull exasol/docker-db:7.0.2 - - docker pull exasol/docker-db:6.2.9-d1 - - docker network create -d bridge --subnet 192.168.0.0/24 --gateway 192.168.0.1 dockernet - -matrix: - include: - - jdk: openjdk8 - scala: 2.11.12 - env: SPARK_VERSION="2.4.5" EXASOL_DOCKER_VERSION="6.2.9-d1" +jdk: + - openjdk11 - - jdk: openjdk8 - scala: 2.11.12 - env: SPARK_VERSION="2.4.5" EXASOL_DOCKER_VERSION="7.0.2" +scala: + - 2.12.12 - - jdk: openjdk8 - scala: 2.12.12 - env: SPARK_VERSION="2.4.5" EXASOL_DOCKER_VERSION="6.2.9-d1" +env: + - SPARK_VERSION="2.4.5" EXASOL_DOCKER_VERSION="6.2.12-d1" + - SPARK_VERSION="2.4.5" EXASOL_DOCKER_VERSION="7.0.4" + - SPARK_VERSION="3.0.1" EXASOL_DOCKER_VERSION="6.2.12-d1" + - SPARK_VERSION="3.0.1" EXASOL_DOCKER_VERSION="7.0.4" - - jdk: openjdk8 - scala: 2.12.12 - env: SPARK_VERSION="2.4.5" EXASOL_DOCKER_VERSION="7.0.2" +before_install: + - git fetch --tags + - docker pull "exasol/docker-db:$EXASOL_DOCKER_VERSION" + - docker network create -d bridge --subnet 192.168.0.0/24 --gateway 192.168.0.1 dockernet script: - travis_wait 30 ./scripts/ci.sh diff --git a/doc/changes/changelog.md b/doc/changes/changelog.md index 01de10a3..9ce0e825 100644 --- a/doc/changes/changelog.md +++ b/doc/changes/changelog.md @@ -1,5 +1,6 @@ # Releases +* [1.0.0](changes_1.0.0.md) * [0.3.2](changes_0.3.2.md) * [0.3.1](changes_0.3.1.md) * [0.3.0](changes_0.3.0.md) diff --git a/doc/changes/changes_1.0.0.md b/doc/changes/changes_1.0.0.md new file mode 100644 index 00000000..072f64ee --- /dev/null +++ b/doc/changes/changes_1.0.0.md @@ -0,0 +1,33 @@ +# Spark Exasol Connector 1.0.0, released 2020-12-DD + +## Features / Improvements + + +## Documentation + +* #85: Updated documentation with configuration for the Databricks cluster (PR #86) + +## Dependency Updates + +### Runtime Dependency Updates + +* Updated to `com.exasol:exasol-jdbc:7.0.4` (was `7.0.0`) +* Updated to `org.apache.spark:spark-core:3.0.1` (was `2.4.5`) +* Updated to `org.apache.spark:spark-sql:3.0.1` (was `2.4.5`) + +### Test Dependency Updates + +* Updated to `org.scalatest:scalatest:3.2.2` (was `3.2.2`) +* Updated to `org.testcontainers:jdbc:1.15.0` (was `1.14.3`) +* Updated to `com.holdenkarau:spark-testing-base:3.0.1_1.0.0` (was `2.4.5_0.14.0) +* Updated to `org.mockito:mockito-core:3.6.28` (was `3.5.13`) +* Updated to `com.dimafeng:testcontainers-scala:0.38.7` (was `0.38.4`) + +### Plugin Updates + +* Updated to `sbt.version:1.4.4` (was `1.3.13`) +* Updated to `org.wartremover:sbt-wartremover:2.4.13` (was `2.4.10`) +* Updated to `org.wartremover:sbt-wartremover-contrib:1.3.11` (was `1.3.8`) +* Updated to `com.jsuereth:sbt-pgp:2.0.2` (was `2.0.1`) +* Updated to `org.xerial.sbt:sbt-sonatype:3.9.5` (was `3.9.4`) +* Removed `io.get-coursier:sbt-coursier` diff --git a/doc/images/databricks-deployment.png b/doc/images/databricks-deployment.png new file mode 100644 index 0000000000000000000000000000000000000000..463a97486c1bd96bb46a9e85eda47998ba6282e7 GIT binary patch literal 35961 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 literal 0 HcmV?d00001 diff --git a/doc/user_guide/user_guide.md b/doc/user_guide/user_guide.md index 5d5efaa2..e7302600 100644 --- a/doc/user_guide/user_guide.md +++ b/doc/user_guide/user_guide.md @@ -86,6 +86,29 @@ libraryDependencies += "com.exasol" % "spark-connector" %% "" Similar to the Java dependency, we add the resolver to the Exasol Artifactory so that the Exasol JDBC driver can be found. +### Spark Exasol Connector as Databricks Cluster Dependency + +Similar to using maven, you should provide maven artifact coordinates to the +[Databricks Workspace Library][databricks-install]. + +[databricks-install]: https://docs.databricks.com/libraries/workspace-libraries.html#maven-libraries + +databricks-deployment + +Go to your cluster, then to `Libraries`, and click `Install New`: + +- Select Maven as a Library Source. +- In the Coordinate field, enter artifact coordinates + `com.exasol:spark-connector_2.12:`. Please notice that we use the + Scala version 2.12, change it to 2.11 if your Databricks Runtime version + requires it. +- In the Repository field, enter the Exasol Artifactory + `https://maven.exasol.com/artifactory/exasol-releases`. +- Click Install. + +Please change the `` to one of the latest Spark Exasol Connector +releases. + ### Spark Exasol Connector With Spark Shell You can also integrate the Spark Exasol Connector to the Spark Shell. Provide diff --git a/project/Dependencies.scala b/project/Dependencies.scala index 1e89cf62..381c7b4f 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -6,19 +6,19 @@ import sbt._ object Dependencies { // Versions - private val DefaultSparkVersion = "2.4.5" - private val ExasolJdbcVersion = "7.0.0" + private val DefaultSparkVersion = "3.0.1" + private val ExasolJdbcVersion = "7.0.4" - private val ScalaTestVersion = "3.2.2" + private val ScalaTestVersion = "3.2.3" private val ScalaTestMockitoVersion = "1.0.0-M2" - private val MockitoVersion = "3.5.13" - private val ContainersJdbcVersion = "1.14.3" - private val ContainersScalaVersion = "0.38.4" + private val MockitoVersion = "3.6.28" + private val ContainersJdbcVersion = "1.15.0" + private val ContainersScalaVersion = "0.38.7" private val sparkCurrentVersion = sys.env.getOrElse("SPARK_VERSION", DefaultSparkVersion) - private val SparkTestingBaseVersion = s"${sparkCurrentVersion}_0.14.0" + private val SparkTestingBaseVersion = s"${sparkCurrentVersion}_1.0.0" val Resolvers: Seq[Resolver] = Seq( "Exasol Releases" at "https://maven.exasol.com/artifactory/exasol-releases" diff --git a/project/Settings.scala b/project/Settings.scala index 01cdca43..4d1e9f7a 100644 --- a/project/Settings.scala +++ b/project/Settings.scala @@ -19,6 +19,7 @@ object Settings { buildSettings(scalaVersion) ++ miscSettings ++ assemblySettings ++ + apiDocSettings ++ scalaStyleSettings ++ Publishing.publishSettings() @@ -70,6 +71,31 @@ object Settings { } ) + def apiDocSettings(): Seq[Setting[_]] = Seq( + autoAPIMappings := true, + apiMappings ++= scalaInstance.value.libraryJars.collect { + case file if file.getName.startsWith("scala-library") && file.getName.endsWith(".jar") => + file -> url(s"http://www.scala-lang.org/api/${scalaVersion.value}/") + }.toMap ++ + // Since Java 9+ introduced modules, API links changed, update these + // links based on used Java modules. + Map( + file("/modules/java.sql") -> url( + "https://docs.oracle.com/en/java/javase/11/docs/api/java.sql" + ) + ), + // Override doc task in 2.11.x versions since linking external Java + // 11+ classes does not work. + (Compile / doc) := Def.taskDyn { + val docTaskValue = (Compile / doc).taskValue + if (scalaBinaryVersion.value == "2.11") { + (Compile / doc / target).toTask + } else { + Def.task(docTaskValue.value) + } + }.value + ) + def scalaStyleSettings(): Seq[Setting[_]] = { // Creates a Scalastyle task that runs with tests lazy val mainScalastyle = taskKey[Unit]("mainScalastyle") diff --git a/project/build.properties b/project/build.properties index 0837f7a1..7de0a938 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.3.13 +sbt.version=1.4.4 diff --git a/project/plugins.sbt b/project/plugins.sbt index f21b4c4e..92bee8b7 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,14 +1,10 @@ -// Adds a pure Scala artifact fetcher `coursier` -// https://github.com/coursier/coursier -addSbtPlugin("io.get-coursier" % "sbt-coursier" % "1.0.3") - // Adds a `wartremover` a flexible Scala code linting tool // http://github.com/puffnfresh/wartremover -addSbtPlugin("org.wartremover" % "sbt-wartremover" % "2.4.10") +addSbtPlugin("org.wartremover" % "sbt-wartremover" % "2.4.13") // Adds Contrib Warts // http://github.com/wartremover/wartremover-contrib/ -addSbtPlugin("org.wartremover" % "sbt-wartremover-contrib" % "1.3.8") +addSbtPlugin("org.wartremover" % "sbt-wartremover-contrib" % "1.3.11") // Adds a `assembly` task to create a fat JAR with all of its dependencies // https://github.com/sbt/sbt-assembly @@ -45,11 +41,11 @@ addSbtPlugin("net.virtual-void" % "sbt-dependency-graph" % "0.9.2") // Adds a `sonatype` release tasks // https://github.com/xerial/sbt-sonatype -addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.9.4") +addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.9.5") // Adds a `gnu-pgp` plugin // https://github.com/sbt/sbt-pgp -addSbtPlugin("com.jsuereth" % "sbt-pgp" % "2.0.1") +addSbtPlugin("com.jsuereth" % "sbt-pgp" % "2.0.2") // Adds a `git` plugin // https://github.com/sbt/sbt-git diff --git a/sbtx b/sbtx index 11a73fbc..004a6170 100755 --- a/sbtx +++ b/sbtx @@ -34,10 +34,10 @@ set -o pipefail -declare -r sbt_release_version="1.3.13" -declare -r sbt_unreleased_version="1.4.0-M1" +declare -r sbt_release_version="1.4.4" +declare -r sbt_unreleased_version="1.4.4" -declare -r latest_213="2.13.3" +declare -r latest_213="2.13.4" declare -r latest_212="2.12.12" declare -r latest_211="2.11.12" declare -r latest_210="2.10.7" @@ -471,7 +471,7 @@ process_args() { -trace) require_arg integer "$1" "$2" && trace_level="$2" && shift 2 ;; -debug-inc) addJava "-Dxsbt.inc.debug=true" && shift ;; - -no-colors) addJava "-Dsbt.log.noformat=true" && shift ;; + -no-colors) addJava "-Dsbt.log.noformat=true" && addJava "-Dsbt.color=false" && shift ;; -sbt-create) sbt_create=true && shift ;; -sbt-dir) require_arg path "$1" "$2" && sbt_dir="$2" && shift 2 ;; -sbt-boot) require_arg path "$1" "$2" && addJava "-Dsbt.boot.directory=$2" && shift 2 ;; diff --git a/scripts/ci.sh b/scripts/ci.sh index e29a6fbb..da654931 100755 --- a/scripts/ci.sh +++ b/scripts/ci.sh @@ -10,7 +10,7 @@ BASE_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )"/.. && pwd )" cd "$BASE_DIR" MAIN_SCALA_VERSION=2.12.12 -MAIN_SPARK_VERSION=2.4.5 +MAIN_SPARK_VERSION=3.0.1 if [[ -z "${TRAVIS_SCALA_VERSION:-}" ]]; then echo "Environment variable TRAVIS_SCALA_VERSION is not set" @@ -104,7 +104,7 @@ run_dependency_info () { ./sbtx \ -Dspark.currentVersion=$SPARK_VERSION \ ++$TRAVIS_SCALA_VERSION \ - dependencyUpdates pluginUpdates coursierDependencyTree + dependencyUpdates pluginUpdates dependencyTree } run_shell_check () { diff --git a/src/it/java/org/testcontainers/containers/ExasolDockerContainer.java b/src/it/java/org/testcontainers/containers/ExasolDockerContainer.java index fd56a073..601914ea 100644 --- a/src/it/java/org/testcontainers/containers/ExasolDockerContainer.java +++ b/src/it/java/org/testcontainers/containers/ExasolDockerContainer.java @@ -10,7 +10,7 @@ public class ExasolDockerContainer> extends JdbcDatabaseContainer { - private static final String DEFAULT_EXASOL_VERSION = "7.0.2"; + private static final String DEFAULT_EXASOL_VERSION = "7.0.4"; // wait for 5 minutes to startup private static final Integer EXASOL_STARTUP_TIME = 15 * 60; private String username = "sys"; diff --git a/src/main/scala/com/exasol/spark/rdd/ExasolRDD.scala b/src/main/scala/com/exasol/spark/rdd/ExasolRDD.scala index 1b3fddf1..11c0954b 100644 --- a/src/main/scala/com/exasol/spark/rdd/ExasolRDD.scala +++ b/src/main/scala/com/exasol/spark/rdd/ExasolRDD.scala @@ -13,11 +13,11 @@ import org.apache.spark.rdd.RDD import org.apache.spark.scheduler.SparkListener import org.apache.spark.scheduler.SparkListenerApplicationEnd import org.apache.spark.sql.Row +import org.apache.spark.sql.execution.datasources.jdbc.JdbcUtils import org.apache.spark.sql.types.StructType import com.exasol.jdbc.EXAConnection import com.exasol.jdbc.EXAResultSet -import com.exasol.spark.util.Converter import com.exasol.spark.util.ExasolConnectionManager /** @@ -155,7 +155,7 @@ class ExasolRDD( conn = manager.subConnection(partition.connectionUrl) resultSet = conn.DescribeResult(subHandle) - Converter.resultSetToRows(resultSet, querySchema) + JdbcUtils.resultSetToRows(resultSet, querySchema) } // scalastyle:on null return diff --git a/src/main/scala/com/exasol/spark/util/Converter.scala b/src/main/scala/com/exasol/spark/util/Converter.scala index f4c32356..80286664 100644 --- a/src/main/scala/com/exasol/spark/util/Converter.scala +++ b/src/main/scala/com/exasol/spark/util/Converter.scala @@ -6,7 +6,6 @@ import java.sql.ResultSet import org.apache.spark.internal.Logging import org.apache.spark.sql.Row import org.apache.spark.sql.catalyst.InternalRow -import org.apache.spark.sql.catalyst.encoders.RowEncoder import org.apache.spark.sql.catalyst.expressions.SpecificInternalRow import org.apache.spark.sql.catalyst.util.DateTimeUtils import org.apache.spark.sql.types._ @@ -21,16 +20,6 @@ import org.apache.spark.unsafe.types.UTF8String */ object Converter extends Logging { - /** - * Converts a [[java.sql.ResultSet]] into an iterator of - * [[org.apache.spark.sql.Row]]-s. - */ - def resultSetToRows(resultSet: ResultSet, schema: StructType): Iterator[Row] = { - val encoder = RowEncoder(schema).resolveAndBind() - val internalRows = resultSetToSparkInternalRows(resultSet, schema) - internalRows.map(encoder.fromRow) - } - @SuppressWarnings(Array("org.wartremover.warts.AsInstanceOf")) def resultSetToSparkInternalRows( resultSet: ResultSet, diff --git a/src/test/scala/com/exasol/spark/util/FiltersSuite.scala b/src/test/scala/com/exasol/spark/util/FiltersSuite.scala index 69560d86..756b6360 100644 --- a/src/test/scala/com/exasol/spark/util/FiltersSuite.scala +++ b/src/test/scala/com/exasol/spark/util/FiltersSuite.scala @@ -41,7 +41,7 @@ class FiltersSuite extends AnyFunSuite with Matchers { | str_col <= '123' |AND int_col > 42 |AND (in_col NOT IN (1,2,3)) - """.stripMargin.lines.mkString(" ").trim + """.stripMargin.replaceAll("\\s+", " ").trim() assert(createWhereClause(testSchema, filters) === expected) } @@ -78,7 +78,7 @@ class FiltersSuite extends AnyFunSuite with Matchers { |AND (str_col LIKE '%inside%') |AND (str_col LIKE 'prefix%') |AND (in_col IN (1,2,3)) - """.stripMargin.lines.mkString(" ").trim + """.stripMargin.replaceAll("\\s+", " ").trim() assert(createWhereClause(testSchema, filters) === expected) } @@ -108,7 +108,7 @@ class FiltersSuite extends AnyFunSuite with Matchers { |AND double_col = 100.0 |AND date_col = date '2018-01-01' |AND datetime_col = timestamp '2018-01-01 00:00:59.123' - """.stripMargin.lines.mkString(" ").trim + """.stripMargin.replaceAll("\\s+", " ").trim() assert(createWhereClause(testSchema, filters) === expected) } @@ -126,7 +126,7 @@ class FiltersSuite extends AnyFunSuite with Matchers { |((str_col = 'abc') OR (int_col = 123)) |AND (((NOT ((int_col IS NULL)))) OR ((str_col IS NOT NULL))) |AND ((str_col = 'xyz') OR (((float_col = 3.14) AND (int_col != 3)))) - """.stripMargin.lines.mkString(" ").trim + """.stripMargin.replaceAll("\\s+", " ").trim() assert(createWhereClause(testSchema, filters) === expected) }