Skip to content

Commit

Permalink
Scala 3 migration (#158)
Browse files Browse the repository at this point in the history
* Scala 3 migration

* Scala 3 migration

* More adjustments

* Compilation fix WIP

* tests fix driveby

* Final fix

* fixes

* revert tests

* Added 3.3.1 Scala support for CI

* Compilation fix

* tests fix driveby

* tests fix driveby

* tests fix driveby

* tests fix driveby

* tests fix driveby

* tests fix driveby

* tests fix driveby

* tests fix driveby

* tests fix driveby

* tests fix driveby

* tests fix driveby

* tests fix driveby

* tests fix driveby

* tests fix driveby

* tests fix driveby

* tests fix driveby

* tests fix driveby

* tests fix driveby

* THis fixes it

* test conv

* Test fix

* tests fix driveby

* more fixes

* Fix ins

* fix

* Fixes

* test

* Scala version update

* Addressed comments

* Fixed Scala 2 version in Ci/CD

* test

* fix

* test fix

---------

Co-authored-by: andriyshevchenko <andriy@crobox.com>
  • Loading branch information
aShevc and andriyshevchenko authored Mar 20, 2024
1 parent 338ebd5 commit 8509bf5
Show file tree
Hide file tree
Showing 27 changed files with 339 additions and 208 deletions.
20 changes: 15 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
fail-fast: false
matrix:
os: [ubuntu-latest]
scala: [2.13.8]
scala: [2.13.13, 3.3.1]
java: [temurin@17]
clickhouse: [21.3, 21.8.14, 22.3]
runs-on: ${{ matrix.os }}
Expand Down Expand Up @@ -82,7 +82,7 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest]
scala: [2.13.8]
scala: [2.13.13, 3.3.1]
java: [temurin@17]
runs-on: ${{ matrix.os }}
steps:
Expand Down Expand Up @@ -110,12 +110,22 @@ jobs:
~/Library/Caches/Coursier/v1
key: ${{ runner.os }}-sbt-cache-v2-${{ hashFiles('**/*.sbt') }}-${{ hashFiles('project/build.properties') }}

- name: Download target directories (2.13.8)
- name: Download target directories (3.3.1)
uses: actions/download-artifact@v2
with:
name: target-${{ matrix.os }}-2.13.8-${{ matrix.java }}
name: target-${{ matrix.os }}-3.3.1-${{ matrix.java }}

- name: Inflate target directories (2.13.8)
- name: Inflate target directories (3.3.1)
run: |
tar xf targets.tar
rm targets.tar
- name: Download target directories (2.13.13)
uses: actions/download-artifact@v2
with:
name: target-${{ matrix.os }}-2.13.13-${{ matrix.java }}

- name: Inflate target directories (2.13.13)
run: |
tar xf targets.tar
rm targets.tar
Expand Down
4 changes: 2 additions & 2 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ lazy val root = (project in file("."))
inThisBuild(
List(
organization := "com.crobox.clickhouse",
scalaVersion := "2.13.8",
crossScalaVersions := List("2.13.8"),
scalaVersion := "2.13.13",
crossScalaVersions := List("2.13.13", "3.3.1"),
javacOptions ++= Seq("-g", "-Xlint:unchecked", "-Xlint:deprecation", "-source", "11", "-target", "11"),
scalacOptions ++= Seq("-unchecked", "-deprecation", "-feature", "-language:_", "-encoding", "UTF-8"),
publishTo := {
Expand Down
53 changes: 53 additions & 0 deletions dsl/src/it/scala-2/com/crobox/clickhouse/dsl/QueryITTypeCast.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package com.crobox.clickhouse.dsl

import com.crobox.clickhouse.DslITSpec
class QueryITTypeCast extends DslITSpec {

// This test uses extension methods removed in Scala 3. Hence only making it available for Scala 2
it should "perform typecasts" in {

type TakeIntGiveIntTypes = Column => (TypeCastColumn[T] with Reinterpretable) forSome {
type T >: Long with String with Float with Serializable
}

val takeIntGiveIntCast = Set(
toUInt8 _,
toUInt16 _,
toUInt32 _,
toUInt64 _,
toInt8 _,
toInt16 _,
toInt32 _,
toInt64 _,
toFloat32 _,
toFloat64 _
)

val takeIntGiveStringCast = Set(
toDate _,
toDateTime _,
toStringRep _
)

val reinterpToIntCast = takeIntGiveIntCast

val reinterpToStringCast = Set(
toStringRep _
)

val takeStringGiveIntCast = Set(
toUInt8OrZero _,
toUInt16OrZero _,
toUInt32OrZero _,
toUInt64OrZero _,
toInt8OrZero _,
toInt16OrZero _,
toInt32OrZero _,
toInt64OrZero _,
toFloat32OrZero _,
toFloat64OrZero _,
(col: TableColumn[_]) => toFixedString(col, 10),
toStringCutToZero _
)
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package com.crobox.clickhouse.dsl

import com.crobox.clickhouse.DslITSpec
import com.crobox.clickhouse.{ClickhouseClient, DslITSpec}
import com.crobox.clickhouse.dsl.execution.QueryResult
import com.crobox.clickhouse.dsl.marshalling.ClickhouseJsonSupport._
import com.crobox.clickhouse.time.{IntervalStart, MultiDuration, MultiInterval, TimeUnit, TotalDuration}
import org.joda.time.{DateTime, DateTimeZone, Days}
import org.scalactic.TripleEqualsSupport
import org.scalatest.prop.TableDrivenPropertyChecks
import spray.json.RootJsonFormat

import java.util.UUID
import scala.concurrent.Future
Expand All @@ -17,10 +18,10 @@ class ClickhouseTimeSeriesIT extends DslITSpec with TableDrivenPropertyChecks {
case class CustomResult(time: IntervalStart, shields: String)

object CustomResult {
implicit val format = jsonFormat2(CustomResult.apply)
implicit val format: RootJsonFormat[CustomResult] = jsonFormat2(CustomResult.apply)
}

implicit val clickhouseClient = clickClient
implicit val clickhouseClient: ClickhouseClient = clickClient
val startInterval = DateTime.parse("2019-03-01").withTimeAtStartOfDay().withZone(DateTimeZone.UTC)
val secondsId = UUID.randomUUID()
val dayId = UUID.randomUUID()
Expand Down
47 changes: 0 additions & 47 deletions dsl/src/it/scala/com/crobox/clickhouse/dsl/QueryIT.scala
Original file line number Diff line number Diff line change
Expand Up @@ -30,53 +30,6 @@ class QueryIT extends DslITSpec {
results.futureValue.rows.map(_.empty).head should be(1)
}

it should "perform typecasts" in {

type TakeIntGiveIntTypes = Column => (TypeCastColumn[_$1] with Reinterpretable) forSome {
type _$1 >: Long with String with Float with Serializable
}

val takeIntGiveIntCast = Set(
toUInt8 _,
toUInt16 _,
toUInt32 _,
toUInt64 _,
toInt8 _,
toInt16 _,
toInt32 _,
toInt64 _,
toFloat32 _,
toFloat64 _
)

val takeIntGiveStringCast = Set(
toDate _,
toDateTime _,
toStringRep _
)

val reinterpToIntCast = takeIntGiveIntCast

val reinterpToStringCast = Set(
toStringRep _
)

val takeStringGiveIntCast = Set(
toUInt8OrZero _,
toUInt16OrZero _,
toUInt32OrZero _,
toUInt64OrZero _,
toInt8OrZero _,
toInt16OrZero _,
toInt32OrZero _,
toInt64OrZero _,
toFloat32OrZero _,
toFloat64OrZero _,
(col: TableColumn[_]) => toFixedString(col, 10),
toStringCutToZero _
)
}

def runQry(query: OperationalQuery): Future[String] = {
val che = queryExecutor.asInstanceOf[DefaultClickhouseQueryExecutor]
clickhouseClient.query(che.toSql(query.internalQuery))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,8 @@ class ComparisonFunctionsIT extends DslITSpec {
r(someNum >= 3) shouldBe "1"
r(someNum <= 3) shouldBe "0"
r(someNum isEq 3) shouldBe "0"
r(someNum === 3) shouldBe "0"
r(someNum !== 3) shouldBe "1"
r(notEquals(1,2)) shouldBe "1"
r(_equals(2L,2)) shouldBe "1"
r(isEqual(2L,2)) shouldBe "1"
r(less(1.0,200)) shouldBe "1"
r(greater(1L,2L)) shouldBe "0"
r(lessOrEquals(1,2)) shouldBe "1"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package com.crobox.clickhouse.dsl.column
import com.crobox.clickhouse.DslITSpec
import com.crobox.clickhouse.dsl.misc.LogicalOperatorImprovements.ExpressionColumnImpr
import com.crobox.clickhouse.dsl.select
import com.crobox.clickhouse.dsl._
import scala.language.implicitConversions

import java.util.UUID

Expand Down Expand Up @@ -36,8 +38,8 @@ class INFunctionsIT extends DslITSpec {
.from(TwoTestTable)
.where(
col4.in(select(col4).from(ThreeTestTable)) and
col2.in(select(col2).from(TwoTestTable)) and
col2.in(select(col4).from(ThreeTestTable))
col2.in(select(col2).from(TwoTestTable)) and
col2.in(select(col4).from(ThreeTestTable))
)
).futureValue should be("")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ class NumericColFunctionIT extends DslITSpec {
it should "have correct types so reduce can be used" in {
val exp = Seq(
Const(true),
2 === 2,
3 === 3
2 isEq 2,
3 isEq 3
).reduce(_ or _)

toSql(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ object JoinQuery {
case class JoinQuery(joinType: JoinType,
other: FromQuery,
on: Seq[JoinCondition] = Seq.empty,
using: Seq[Column] = Seq.empty,
`using`: Seq[Column] = Seq.empty,
global: Boolean = false)

case class JoinCondition(left: Column, operator: String, right: Column) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ trait OperationalQuery extends Query {
): OperationalQuery = {
require(internalQuery.join.isDefined)

val newJoin = this.internalQuery.join.get.copy(using = (column +: columns).distinct)
val newJoin = this.internalQuery.join.get.copy(`using` = (column +: columns).distinct)
OperationalQuery(internalQuery.copy(join = Some(newJoin)))
}

Expand Down
2 changes: 1 addition & 1 deletion dsl/src/main/scala/com/crobox/clickhouse/dsl/Query.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package com.crobox.clickhouse.dsl
import scala.util.Try

trait Table {
val database: String
def database: String
val name: String
lazy val quoted: String =
s"${ClickhouseStatement.quoteIdentifier(database)}.${ClickhouseStatement.quoteIdentifier(name)}"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.crobox.clickhouse.dsl.column

import com.crobox.clickhouse.dsl.{EmptyColumn, ExpressionColumn, TableColumn}
import org.joda.time.{DateTime, LocalDate}
import scala.language.implicitConversions

trait ArithmeticFunctions { self: Magnets =>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,31 @@ package com.crobox.clickhouse.dsl.column

import com.crobox.clickhouse.dsl.{EmptyColumn, ExpressionColumn}

trait ComparisonFunctions { self: Magnets =>

case class ComparisonColumn(left: Magnet[_], operator: String, right: Magnet[_]) extends ExpressionColumn[Boolean](EmptyColumn)

trait ComparableWith[M <: Magnet[_]] { self: Magnet[_] =>
def <(other: M): ExpressionColumn[Boolean] = ComparisonColumn(self, "<", other)
def >(other: M): ExpressionColumn[Boolean] = ComparisonColumn(self, ">", other)
def <>(other: M): ExpressionColumn[Boolean] = ComparisonColumn(self, "!=", other)
def isEq(other: M): ExpressionColumn[Boolean] = ComparisonColumn(self, "=", other)
def notEq(other: M): ExpressionColumn[Boolean] = ComparisonColumn(self, "!=", other)
def ===(other: M): ExpressionColumn[Boolean] = ComparisonColumn(self, "=", other)
def !==(other: M): ExpressionColumn[Boolean] = ComparisonColumn(self, "!=", other)
def <=(other: M): ExpressionColumn[Boolean] = ComparisonColumn(self, "<=", other)
def >=(other: M): ExpressionColumn[Boolean] = ComparisonColumn(self, ">=", other)
}

def _equals(col1: ConstOrColMagnet[_], col2: ConstOrColMagnet[_]): ExpressionColumn[Boolean] = ComparisonColumn(col1 , "=", col2)
def notEquals(col1: ConstOrColMagnet[_], col2: ConstOrColMagnet[_]): ExpressionColumn[Boolean] = ComparisonColumn(col1 , "!=", col2)
def less(col1: ConstOrColMagnet[_], col2: ConstOrColMagnet[_]): ExpressionColumn[Boolean] = ComparisonColumn(col1 , "<", col2)
def greater(col1: ConstOrColMagnet[_], col2: ConstOrColMagnet[_]): ExpressionColumn[Boolean] = ComparisonColumn(col1 , ">", col2)
def lessOrEquals(col1: ConstOrColMagnet[_], col2: ConstOrColMagnet[_]): ExpressionColumn[Boolean] = ComparisonColumn(col1 , "<=", col2)
def greaterOrEquals(col1: ConstOrColMagnet[_], col2: ConstOrColMagnet[_]): ExpressionColumn[Boolean] = ComparisonColumn(col1 , ">=", col2)
trait ComparisonFunctions {
self: Magnets =>

case class ComparisonColumn(left: Magnet[_], operator: String, right: Magnet[_])
extends ExpressionColumn[Boolean](EmptyColumn)

@deprecated("Use isEqual instead")
def _equals(col1: ConstOrColMagnet[_], col2: ConstOrColMagnet[_]): ExpressionColumn[Boolean] =
ComparisonColumn(col1, "=", col2)

def isEqual(col1: ConstOrColMagnet[_], col2: ConstOrColMagnet[_]): ExpressionColumn[Boolean] =
ComparisonColumn(col1, "=", col2)

def notEquals(col1: ConstOrColMagnet[_], col2: ConstOrColMagnet[_]): ExpressionColumn[Boolean] =
ComparisonColumn(col1, "!=", col2)

def less(col1: ConstOrColMagnet[_], col2: ConstOrColMagnet[_]): ExpressionColumn[Boolean] =
ComparisonColumn(col1, "<", col2)

def greater(col1: ConstOrColMagnet[_], col2: ConstOrColMagnet[_]): ExpressionColumn[Boolean] =
ComparisonColumn(col1, ">", col2)

def lessOrEquals(col1: ConstOrColMagnet[_], col2: ConstOrColMagnet[_]): ExpressionColumn[Boolean] =
ComparisonColumn(col1, "<=", col2)

def greaterOrEquals(col1: ConstOrColMagnet[_], col2: ConstOrColMagnet[_]): ExpressionColumn[Boolean] =
ComparisonColumn(col1, ">=", col2)
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.crobox.clickhouse.dsl.column

import com.crobox.clickhouse.dsl.{Const, EmptyColumn, ExpressionColumn}
import com.crobox.clickhouse.dsl.marshalling.QueryValueFormats._

trait InFunctions { self: Magnets =>

Expand Down
38 changes: 35 additions & 3 deletions dsl/src/main/scala/com/crobox/clickhouse/dsl/column/Magnets.scala
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package com.crobox.clickhouse.dsl.column

import java.util.UUID

import com.crobox.clickhouse.dsl.marshalling.{QueryValue, QueryValueFormats}
import com.crobox.clickhouse.dsl.{Const, EmptyColumn, OperationalQuery, Table, TableColumn}
import com.crobox.clickhouse.dsl.marshalling.QueryValueFormats._
import com.crobox.clickhouse.dsl.schemabuilder.ColumnType.SimpleColumnType
import com.crobox.clickhouse.dsl.{Const, EmptyColumn, ExpressionColumn, OperationalQuery, Table, TableColumn}
import org.joda.time.{DateTime, LocalDate}
import scala.language.implicitConversions

trait Magnets {
self: ArithmeticFunctions
Expand All @@ -28,6 +30,36 @@ trait Magnets {
val column: TableColumn[C]
}

// ComparabeWith trait and Cast case class were members of ComparisonFunctions and TypeCastFunctions trait
// respectively. But placing them in the mixin traits causes Scala 3 compiler to crash. Hence, placing these
// constructs here is a workaround allowing for the codebase to be compiled with Scala 3.
trait ComparableWith[M <: Magnet[_]] {
self: Magnet[_] =>
def <(other: M): ExpressionColumn[Boolean] = ComparisonColumn(self, "<", other)

def >(other: M): ExpressionColumn[Boolean] = ComparisonColumn(self, ">", other)

def <>(other: M): ExpressionColumn[Boolean] = ComparisonColumn(self, "!=", other)

def isEq(other: M): ExpressionColumn[Boolean] = ComparisonColumn(self, "=", other)

def notEq(other: M): ExpressionColumn[Boolean] = ComparisonColumn(self, "!=", other)

def ===(other: M): ExpressionColumn[Boolean] = ComparisonColumn(self, "=", other)

def !==(other: M): ExpressionColumn[Boolean] = ComparisonColumn(self, "!=", other)

def <=(other: M): ExpressionColumn[Boolean] = ComparisonColumn(self, "<=", other)

def >=(other: M): ExpressionColumn[Boolean] = ComparisonColumn(self, ">=", other)
}

case class Cast[T](tableColumn: ConstOrColMagnet[_], simpleColumnType: SimpleColumnType)
extends TypeCastColumn[T](tableColumn)
with ConstOrColMagnet[T] {
override val column: TableColumn[T] = this
}

/**
* Any constant or column.
* Sidenote: The current implementation doesn't represent collections.
Expand Down Expand Up @@ -88,7 +120,7 @@ trait Magnets {

implicit def arrayColMagnetFromIterableConst[T: QueryValue](s: scala.Iterable[T]): ArrayColMagnet[scala.Iterable[T]] =
new ArrayColMagnet[scala.Iterable[T]] {
val qvForIterable = QueryValueFormats.queryValueToSeq(implicitly[QueryValue[T]])
val qvForIterable = QueryValueFormats.queryValueToSeq(implicitly[QueryValue[T]])
override val column = Const(s)(qvForIterable)
}

Expand Down
Loading

0 comments on commit 8509bf5

Please sign in to comment.