8

I am new to Slick and using Slick 3.1.1. My table looks like

import java.sql.{Blob, Timestamp}

import slick.collection.heterogeneous.HNil

import slick.driver.MySQLDriver.api._


case class AnomalyC(id: Int, serviceName: String, serviceId: String, timeUpdated: Timestamp, timestamp: Timestamp, anomalyCategoryId: Int,
                    userGroup:Int, riskValue: Float, activityTypeId: Int, destinationHost: String, userName: String, tenantId: Int, information:Blob, timeCreated: Timestamp, userId: Int, anomalyType:Int, anomalyValue:String, measure:Int,
                    userAction:Int, uniqueIdentifier:Int, similarCount:Int, trainingValue:String, state: Int, riskLevel:Int, userRiskLevel:Int,
                    userRiskScore: Float, response:Int)
class Anomaly(tag:Tag) extends Table[AnomalyC](tag, "Anomaly") {
  def id = column[Int]("id")
  def serviceName = column[String]("ServiceName")
  def serviceId = column[Int]("ServiceId")
  def timeUpdated = column[Timestamp]("TimeUpdated")
  def timestamp = column[Timestamp]("Timestamp")
  def anomalyCategoryId = column[Int]("AnomalyCategoryId")
  def userGroup = column[Int]("UserGroup")
  def riskValue = column[Float]("RiskValue")
  def activityTypeId = column[Int]("ActivityTypeId")
  def destinationHost = column[String]("DestinationHost")
  def userName = column[String]("UserName")
  def tenantId = column[Int]("TenantId")
  def information = column[Blob]("Information")
  def timeCreated = column[Timestamp]("TimeCreated")
  def userId = column[Int]("UserId")
  def anomalyType = column[Int]("AnomalyType")
  def anomalyValue = column[String]("AnomalyValue")
  def measure = column[Int]("Measure")
  def userAction = column[Int]("UserAction")
  def uniqueIdentifier = column[String]("UniqueIdentifier")
  def similarCount = column[Int]("SimilarCount")
  def trainingValue = column[String]("TrainingValue")
  def state = column[Int]("State")
  def riskLevel = column[Int]("RiskLevel")
  def userRiskLevel = column[Int]("UserRiskLevel")
  def userRiskScore = column[Float]("UserRiskScore")
  def response = column[Int]("Response")

  def * = (id, serviceName, serviceId, timeUpdated, timestamp, anomalyCategoryId, userGroup,
    riskValue, activityTypeId, destinationHost, userName, tenantId, information, timeCreated, userId, anomalyType, anomalyValue,
    measure, userAction, uniqueIdentifier, similarCount, trainingValue, state, riskLevel, userRiskLevel, userRiskScore, response)

}

When I run this, I get error as

Error:(57, 11) too many elements for tuple: 27, allowed: 22
  def * = (id, serviceName, serviceId, timeUpdated, timestamp, anomalyCategoryId, userGroup,
          ^

What do I do?

daydreamer
  • 87,243
  • 191
  • 450
  • 722
  • As suggested, HLists are the way to go currently. [Here's an example](https://stackoverflow.com/questions/36618280/slick-codegen-tables-with-22-columns/49659436#49659436), including how you customize Slick's codegeneration capability to automatically define huge tables for you. – ecoe Jun 13 '18 at 16:41

6 Answers6

3

You could use HLists. Slick has it's own implementation or for probably better interoperability you could use Shapeless. Here is an article that explains it: http://underscore.io/blog/posts/2015/08/08/slickless.html

Alternatively you can use a case class instead of a tuple.

cvogt
  • 11,260
  • 30
  • 46
3

The following worked for me based on the direction provided by @cvogt.

import java.sql.{Blob, Timestamp}

import slick.collection.heterogeneous.HNil
import slick.collection.heterogeneous.syntax._
import slick.driver.MySQLDriver.api._

class Anomaly(tag:Tag) extends Table[Int :: String :: Int :: Timestamp :: Timestamp :: Int :: Int :: Float :: Int :: String
   :: String :: Int ::Blob :: Timestamp :: Int ::Int ::String ::Int ::Int ::String ::Int ::String :: Int ::Int ::Int ::
  Float :: Int :: HNil ](tag, "Anomaly") {

  def id = column[Int]("id")
  def serviceName = column[String]("ServiceName")
  def serviceId = column[Int]("ServiceId")
  def timeUpdated = column[Timestamp]("TimeUpdated")
  def timestamp = column[Timestamp]("Timestamp")
  def anomalyCategoryId = column[Int]("AnomalyCategoryId")
  def userGroup = column[Int]("UserGroup")
  def riskValue = column[Float]("RiskValue")
  def activityTypeId = column[Int]("ActivityTypeId")
  def destinationHost = column[String]("DestinationHost")
  def userName = column[String]("UserName")
  def tenantId = column[Int]("TenantId")
  def information = column[Blob]("Information")
  def timeCreated = column[Timestamp]("TimeCreated")
  def userId = column[Int]("UserId")
  def anomalyType = column[Int]("AnomalyType")
  def anomalyValue = column[String]("AnomalyValue")
  def measure = column[Int]("Measure")
  def userAction = column[Int]("UserAction")
  def uniqueIdentifier = column[String]("UniqueIdentifier")
  def similarCount = column[Int]("SimilarCount")
  def trainingValue = column[String]("TrainingValue")
  def state = column[Int]("State")
  def riskLevel = column[Int]("RiskLevel")
  def userRiskLevel = column[Int]("UserRiskLevel")
  def userRiskScore = column[Float]("UserRiskScore")
  def response = column[Int]("Response")

   def *  = id :: serviceName :: serviceId :: timeUpdated :: timestamp :: anomalyCategoryId :: userGroup ::
  riskValue :: activityTypeId :: destinationHost :: userName :: tenantId :: information :: timeCreated :: userId :: anomalyType :: anomalyValue ::
  measure :: userAction :: uniqueIdentifier :: similarCount :: trainingValue :: state :: riskLevel :: userRiskLevel :: userRiskScore :: response :: HNil
}

The build runs and test pass, however, I still see IntelliJ complains with the following error

enter image description here

daydreamer
  • 87,243
  • 191
  • 450
  • 722
2

As per answer from @insan-e, I re-wrote this and this works as well. I like this approach better however I do not understand the code in it's entirety

import java.sql.{Blob, Timestamp}

import slick.driver.MySQLDriver.api._

case class Anomaly1(id:Int, serviceName:String, serviceId: Int, timeUpdated: Timestamp, timeStamp: Timestamp,
                    anomalyCategoryId: Int, userGroup: Int, riskValue: Float, activityTypeId: Int, destinationHost: String, userName: String)

case class Anomaly2(tenantId: Int, information:Blob, timeCreated: Timestamp, userId: Int, anomalyType:Int, anomalyValue: String, measure: Int, userAction: Int,
                   uniqueIdentifier: String, similarCount: Int, trainingValue: String, state: Int, riskLevel: Int,
                    userRiskLevel: Int, userRiskScore: Float, response: Int)

case class AnomalyRow(anomaly1: Anomaly1, anomaly2: Anomaly2)

class Anomaly(tag:Tag) extends Table[AnomalyRow](tag, "Anomaly") {

  def id = column[Int]("id")
  def serviceName = column[String]("ServiceName")
  def serviceId = column[Int]("ServiceId")
  def timeUpdated = column[Timestamp]("TimeUpdated")
  def timestamp = column[Timestamp]("Timestamp")
  def anomalyCategoryId = column[Int]("AnomalyCategoryId")
  def userGroup = column[Int]("UserGroup")
  def riskValue = column[Float]("RiskValue")
  def activityTypeId = column[Int]("ActivityTypeId")
  def destinationHost = column[String]("DestinationHost")
  def userName = column[String]("UserName")
  def tenantId = column[Int]("TenantId")
  def information = column[Blob]("Information")
  def timeCreated = column[Timestamp]("TimeCreated")
  def userId = column[Int]("UserId")
  def anomalyType = column[Int]("AnomalyType")
  def anomalyValue = column[String]("AnomalyValue")
  def measure = column[Int]("Measure")
  def userAction = column[Int]("UserAction")
  def uniqueIdentifier = column[String]("UniqueIdentifier")
  def similarCount = column[Int]("SimilarCount")
  def trainingValue = column[String]("TrainingValue")
  def state = column[Int]("State")
  def riskLevel = column[Int]("RiskLevel")
  def userRiskLevel = column[Int]("UserRiskLevel")
  def userRiskScore = column[Float]("UserRiskScore")
  def response = column[Int]("Response")

  private type Anomaly1TupleType = (Int, String, Int, Timestamp, Timestamp, Int, Int, Float, Int, String, String)
  private type Anomaly2TupleType = (Int, Blob, Timestamp, Int, Int, String, Int, Int, String, Int, String, Int, Int, Int, Float, Int)
  private type AnomalyRowTupleType = (Anomaly1TupleType, Anomaly2TupleType)

  private val anomalyShapedValue = (
    (id, serviceName, serviceId, timeUpdated, timestamp, anomalyCategoryId, userGroup, riskValue, activityTypeId, destinationHost, userName),
    (tenantId, information, timeCreated, userId, anomalyType, anomalyValue, measure, userAction, uniqueIdentifier, similarCount, trainingValue, state, riskLevel, userRiskLevel, userRiskScore, response)
    ).shaped[AnomalyRowTupleType]

  private val toAnomalyRow: (AnomalyRowTupleType => AnomalyRow) = { anomalyTuple =>
    AnomalyRow(anomaly1 = Anomaly1.tupled.apply(anomalyTuple._1), anomaly2 = Anomaly2.tupled.apply(anomalyTuple._2))
  }

  private val toAnomalyTuple: (AnomalyRow => Option[AnomalyRowTupleType]) = { anomalyRow =>
    Some(Anomaly1.unapply(anomalyRow.anomaly1).get, Anomaly2.unapply(anomalyRow.anomaly2).get)
  }

  def * = anomalyShapedValue <> (toAnomalyRow, toAnomalyTuple)
}
daydreamer
  • 87,243
  • 191
  • 450
  • 722
0

As cvogt already said, you can use nested case classes, they are much easier to work with, see here. I know that HLists are powerful but IMHO people are forcing them too much... What's wrong with case classes? xD

You should compose your AnomalyC class from 2 or more case classes containing <= 22 fields.

insan-e
  • 3,883
  • 3
  • 18
  • 43
0

As slick does not allow for more than 22 columns and complains that the tupled and unapply methods are not found. The simplest solution is to go for nested case classes if possible. Example :

https://github.com/timgent/spray-slick-template/blob/master/src/main/scala/com/timmeh/openhr/openholidays/model/LargeTableExample1.scala

Shilpa
  • 578
  • 6
  • 17
0

With HList approach we need to change only the default projection *.

From documentation https://scala-slick.org/doc/3.3.3/cookbook.html

fgfernandez0321
  • 197
  • 1
  • 5