trait ShardingFunction[K] {
def selectShard(k: K): Session
}
class ShardedTable[A,K](table: Table[A], invokeShardedFieldGetter: A => AnyRef, shardedFieldMetaData: FieldMetaData, f: ShardingFunction[K]) {
def shardedLookup(k: K)(implicit dsl: QueryDsl) = {
import dsl._
using(f.selectShard(k)) {
val q = from(table)(a => dsl.where {
FieldReferenceLinker.createEqualityExpressionWithLastAccessedFieldReferenceAndConstant(invokeShardedFieldGetter(a), k)
} select(a))
q
}
}
}
class ShardedTablePrecursor[A](table: Table[A]) {
def shardedOn[K,T](f: A => T)(implicit dsl: QueryDsl, ev: T => TypedExpressionNode[K], sf: ShardingFunction[K]) = {
import dsl._
val q = from(table)(a=> select(a)) : Query[A]
val n =
Utils.mapSampleObject(q, (a0:A) => ev(f(a0)))
val invoker = f.asInstanceOf[A=>AnyRef]
new ShardedTable[A,K](table, invoker, n._fieldMetaData, sf)
}
}
implicit object yourHashFunction extends ShardingFunction[Long] {
def selectShard(k: Long): Session = sys.error("implemente me !")
}
Then you define a sharded table :
val shardedTable = table[YourObject].shardedOn(_.theShardingKey)
shardedTable.shardedLookup(k) // here it is enforced at compile time that k is the same type as _.theShardingKey ...
It probably would be wise to disable the partial update function, i.e. only update with def update(a: A),
or maybe provide a partial update that takes a shard key in a first argument list