Skip to content
This repository was archived by the owner on Mar 24, 2025. It is now read-only.

Commit a484b26

Browse files
Optimize (#206)
* csv support vector set * fix
1 parent fe8b981 commit a484b26

File tree

14 files changed

+178
-74
lines changed

14 files changed

+178
-74
lines changed

smt-common/src/main/scala/org/bitlap/common/AbstractMacroProcessor.scala

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -218,8 +218,10 @@ abstract class AbstractMacroProcessor(val c: blackbox.Context) {
218218
case t if t =:= typeOf[Long] =>
219219
q"0L"
220220
case t if t weak_<:< typeOf[List[_]] => q"_root_.scala.Nil"
221-
case t if t weak_<:< typeOf[Seq[_]] => q"_root_.scala.Nil"
222221
case t if t weak_<:< typeOf[Option[_]] => q"_root_.scala.None"
222+
case t if t weak_<:< typeOf[Set[_]] => q"_root_.scala.Predef.Set.empty"
223+
case t if t weak_<:< typeOf[Vector[_]] => q"_root_.scala.Vector.empty"
224+
case t if t weak_<:< typeOf[Seq[_]] => q"_root_.scala.Nil"
223225
case _ =>
224226
q"null"
225227
}
@@ -237,12 +239,12 @@ abstract class AbstractMacroProcessor(val c: blackbox.Context) {
237239
isList = true
238240
case t if t weak_<:< weakTypeOf[Option[_]] =>
239241
isOption = true
240-
case t if !isList && (t weak_<:< weakTypeOf[Seq[_]]) =>
241-
isSeq = true
242242
case t if t weak_<:< weakTypeOf[Vector[_]] =>
243243
isVector = true
244244
case t if t weak_<:< weakTypeOf[Set[_]] =>
245245
isSet = true
246+
case t if !isList && (t weak_<:< weakTypeOf[Seq[_]]) =>
247+
isSeq = true
246248
case _ =>
247249
}
248250
Tuple5(isOption, isSeq, isList, isVector, isSet)

smt-common/src/main/scala/org/bitlap/common/MacroCache.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,5 +43,5 @@ object MacroCache {
4343

4444
lazy val classFieldNameMapping: mutable.Map[Int, mutable.Map[String, String]] = mutable.Map.empty
4545

46-
lazy val classFieldValueMapping: mutable.Map[Int, mutable.Map[String, Any]] = mutable.Map.empty
46+
lazy val classFieldTypeMapping: mutable.Map[Int, mutable.Map[String, Any]] = mutable.Map.empty
4747
}

smt-common/src/main/scala/org/bitlap/common/Transformable.scala

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,6 @@ class Transformable[From, To] {
2929

3030
/** @param selectFromField
3131
* Select the name of the field to be mapped in the `From` class.
32-
* @param selectToField
33-
* Selects which field of `To` the `From` will eventually be mapped to.
3432
* @param map
3533
* Specify the type mapping of the field, which must be provided when the type is incompatible, or else attempt to
3634
* search for an implicit `Transformer[FromField, ToField]` (a failed search will result in a compile failure).
@@ -43,21 +41,20 @@ class Transformable[From, To] {
4341
* Transformable
4442
*/
4543
@unchecked
46-
def mapField[FromField, ToField](
44+
def setType[FromField, ToField](
4745
selectFromField: From => FromField,
48-
selectToField: To => ToField,
4946
map: FromField => ToField
5047
): Transformable[From, To] =
51-
macro TransformerMacro.mapFieldWithValueImpl[From, To, FromField, ToField]
48+
macro TransformerMacro.mapTypeImpl[From, To, FromField, ToField]
5249

5350
/** Same method as above, but without the map parameter. That is, no type mapping needs to be configured.
5451
*/
5552
@unchecked
56-
def mapField[FromField, ToField](
53+
def setName[FromField, ToField](
5754
selectFromField: From => FromField,
5855
selectToField: To => ToField
5956
): Transformable[From, To] =
60-
macro TransformerMacro.mapFieldImpl[From, To, FromField, ToField]
57+
macro TransformerMacro.mapNameImpl[From, To, FromField, ToField]
6158

6259
def instance: Transformer[From, To] = macro TransformerMacro.instanceImpl[From, To]
6360

@@ -66,7 +63,7 @@ class Transformable[From, To] {
6663
object Transformable {
6764

6865
/** Automatically derive `Transformable[From, To]` for case classes only, for non-case classes you should use the
69-
* `mapField` method to configure the mapping relationship.
66+
* `setType` method to configure the mapping relationship.
7067
* @tparam From
7168
* @tparam To
7269
* @return

smt-common/src/main/scala/org/bitlap/common/TransformerMacro.scala

Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -30,32 +30,28 @@ import scala.reflect.macros.whitebox
3030
* @version 1.0,6/15/22
3131
*/
3232
class TransformerMacro(override val c: whitebox.Context) extends AbstractMacroProcessor(c) {
33+
3334
import c.universe._
3435

3536
protected val packageName = q"_root_.org.bitlap.common"
3637
private val builderFunctionPrefix = "_TransformableFunction$"
3738
private val annoBuilderPrefix = "_AnonObjectTransformable$"
3839
private val fromTermName = TermName("from")
3940

40-
def mapFieldWithValueImpl[From, To, FromField, ToField](
41+
def mapTypeImpl[From, To, FromField, ToField](
4142
selectFromField: Expr[From => FromField],
42-
selectToField: Expr[To => ToField],
4343
map: Expr[FromField => ToField]
4444
): Expr[Transformable[From, To]] = {
4545
val Function(_, Select(_, fromName)) = selectFromField.tree
46-
val Function(_, Select(_, toName)) = selectToField.tree
4746
val builderId = getBuilderId(annoBuilderPrefix)
48-
MacroCache.classFieldNameMapping
49-
.getOrElseUpdate(builderId, mutable.Map.empty)
50-
.update(toName.decodedName.toString, fromName.decodedName.toString)
51-
MacroCache.classFieldValueMapping
47+
MacroCache.classFieldTypeMapping
5248
.getOrElseUpdate(builderId, mutable.Map.empty)
53-
.update(toName.decodedName.toString, map)
49+
.update(fromName.decodedName.toString, map)
5450
val tree = q"new ${c.prefix.actualType}"
5551
exprPrintTree[Transformable[From, To]](force = false, tree)
5652
}
5753

58-
def mapFieldImpl[From, To, FromField, ToField](
54+
def mapNameImpl[From, To, FromField, ToField](
5955
selectFromField: Expr[From => FromField],
6056
selectToField: Expr[To => ToField]
6157
): Expr[Transformable[From, To]] = {
@@ -73,7 +69,8 @@ class TransformerMacro(override val c: whitebox.Context) extends AbstractMacroPr
7369
def instanceImpl[From: WeakTypeTag, To: WeakTypeTag]: Expr[BitlapTransformer[From, To]] = {
7470
val fromClassName = resolveClassTypeName[From]
7571
val toClassName = resolveClassTypeName[To]
76-
val tree = q"""
72+
val tree =
73+
q"""
7774
..$getPreTree
7875
new $packageName.Transformer[$fromClassName, $toClassName] {
7976
override def transform($fromTermName: $fromClassName): $toClassName = {
@@ -101,7 +98,7 @@ class TransformerMacro(override val c: whitebox.Context) extends AbstractMacroPr
10198
}
10299

103100
private def getPreTree: Iterable[Tree] = {
104-
val customTrees = MacroCache.classFieldValueMapping.getOrElse(getBuilderId(annoBuilderPrefix), mutable.Map.empty)
101+
val customTrees = MacroCache.classFieldTypeMapping.getOrElse(getBuilderId(annoBuilderPrefix), mutable.Map.empty)
105102
val (_, preTrees) = customTrees.collect { case (key, expr: Expr[Tree] @unchecked) =>
106103
expr.tree match {
107104
case buildFunction: Function =>
@@ -126,21 +123,24 @@ class TransformerMacro(override val c: whitebox.Context) extends AbstractMacroPr
126123

127124
val customFieldNameMapping =
128125
MacroCache.classFieldNameMapping.getOrElse(getBuilderId(annoBuilderPrefix), mutable.Map.empty)
129-
val customFieldValueMapping =
130-
MacroCache.classFieldValueMapping.getOrElse(getBuilderId(annoBuilderPrefix), mutable.Map.empty)
126+
val customFieldTypeMapping =
127+
MacroCache.classFieldTypeMapping.getOrElse(getBuilderId(annoBuilderPrefix), mutable.Map.empty)
131128
c.info(c.enclosingPosition, s"Field Name Mapping:$customFieldNameMapping", force = true)
132-
c.info(c.enclosingPosition, s"Field Value Mapping:$customFieldValueMapping", force = true)
129+
c.info(c.enclosingPosition, s"Field Type Mapping:$customFieldTypeMapping", force = true)
133130
val fields = toClassInfo.map { field =>
134-
val fromFieldName = customFieldNameMapping.get(field.fieldName)
135-
val realFromFieldName = fromFieldName.fold(field.fieldName)(x => x)
136-
if (customFieldValueMapping.contains(field.fieldName)) {
137-
q"""${TermName(builderFunctionPrefix + field.fieldName)}.apply(${q"$fromTermName.${TermName(realFromFieldName)}"})"""
138-
} else {
139-
checkFieldGetFieldTerm[From](
140-
realFromFieldName,
141-
fromClassInfo.find(_.fieldName == realFromFieldName),
142-
field
143-
)
131+
val fromFieldName = customFieldNameMapping.get(field.fieldName)
132+
val realToFieldName = fromFieldName.fold(field.fieldName)(x => x)
133+
fromFieldName match {
134+
case Some(fromName) if customFieldTypeMapping.contains(fromName) =>
135+
q"""${TermName(builderFunctionPrefix + fromName)}.apply(${q"$fromTermName.${TermName(realToFieldName)}"})"""
136+
case None if customFieldTypeMapping.contains(field.fieldName) =>
137+
q"""${TermName(builderFunctionPrefix + field.fieldName)}.apply(${q"$fromTermName.${TermName(realToFieldName)}"})"""
138+
case _ =>
139+
checkFieldGetFieldTerm[From](
140+
realToFieldName,
141+
fromClassInfo.find(_.fieldName == realToFieldName),
142+
field
143+
)
144144
}
145145
}
146146
q"""
@@ -161,7 +161,7 @@ class TransformerMacro(override val c: whitebox.Context) extends AbstractMacroPr
161161
if (fromFieldOpt.isEmpty) {
162162
c.abort(
163163
c.enclosingPosition,
164-
s"value `$realFromFieldName` is not a member of `$fromClassName`, Please consider using `mapField` method!"
164+
s"value `$realFromFieldName` is not a member of `$fromClassName`, Please consider using `setName` method!"
165165
)
166166
return fromFieldTerm
167167
}
@@ -192,7 +192,8 @@ class TransformerMacro(override val c: whitebox.Context) extends AbstractMacroPr
192192
case (information1, information2) =>
193193
c.warning(
194194
c.enclosingPosition,
195-
s"No implicit `Transformer` is defined for ${information1.fieldType} => ${information2.fieldType}, which may cause compilation errors!!!"
195+
s"No implicit `Transformer` is defined for ${information1.fieldType} => ${information2.fieldType}, which may cause compilation errors!!!" +
196+
s"Please consider using `setType` method, or define an `Transformer[${information1.fieldType}, ${information2.fieldType}]` implicit !"
196197
)
197198
q"""$packageName.Transformer[${information1.fieldType}, ${information2.fieldType}].transform($fromFieldTerm)"""
198199
}

smt-common/src/test/scala/org/bitlap/common/TransformableTest.scala

Lines changed: 38 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,13 @@ import org.scalatest.matchers.should.Matchers
3131
class TransformableTest extends AnyFlatSpec with Matchers {
3232

3333
"TransformableTest simple case" should "ok for Transformable" in {
34-
3534
case class A1(a: String, b: Int, cc: Long, d: Option[String])
3635
case class A2(a: String, b: Int, c: Int, d: Option[String])
3736

3837
val a = A1("hello", 1, 2, None)
3938
val b: A2 = Transformable[A1, A2] // todo `fromField: Long` type Long cannot be ignored.
40-
.mapField[Long, Int](_.cc, _.c, (fromField: Long) => if (fromField > 0) fromField.toInt else 0)
39+
.setName(_.cc, _.c)
40+
.setType[Long, Int](_.cc, fromField => if (fromField > 0) fromField.toInt else 0)
4141
.instance
4242
.transform(a)
4343

@@ -52,14 +52,27 @@ class TransformableTest extends AnyFlatSpec with Matchers {
5252
b2.toString shouldEqual "B2(List(hello))"
5353
}
5454

55+
"TransformableTest simple case, name is equals, but type not" should "ok for Transformable" in {
56+
case class A1(a: String)
57+
case class A2(a: Int)
58+
59+
val a = A1("1112")
60+
val b: A2 = Transformable[A1, A2]
61+
.setType[String, Int](_.a, _.toInt)
62+
.instance
63+
.transform(a)
64+
65+
b.toString shouldEqual "A2(1112)"
66+
}
67+
5568
"TransformableTest simple case" should "ok for implicit Transformable" in {
5669
case class A1(a: String, b: Int, cc: Long, d: Option[String])
5770
case class A2(a: String, b: Int, c: Int, d: Option[String])
5871
val a = A1("hello", 1, 2, None)
5972
implicit val transformer = Transformable[A1, A2]
60-
.mapField(_.b, _.c)
61-
.mapField(_.a, _.a)
62-
.mapField[Option[String], Option[String]](_.d, _.d, (map: Option[String]) => map)
73+
.setName(_.b, _.c)
74+
.setName(_.a, _.a)
75+
.setType[Option[String], Option[String]](_.d, (map: Option[String]) => map)
6376
.instance
6477

6578
Transformer[A1, A2].transform(a).toString shouldEqual "A2(hello,1,1,None)"
@@ -72,7 +85,7 @@ class TransformableTest extends AnyFlatSpec with Matchers {
7285
| case class A2(a: String, b: Int, c: Int, d: Option[String])
7386
| val a = A1("hello", 1, 2, None)
7487
| val b: A2 = Transformable[A1, A2]
75-
| .mapField(_.cc, _.c)
88+
| .setName(_.cc, _.c)
7689
| .instance
7790
| .transform(a)
7891
|""".stripMargin shouldNot compile
@@ -85,7 +98,7 @@ class TransformableTest extends AnyFlatSpec with Matchers {
8598
case class D2(c2: C2)
8699

87100
implicit val cTransformer: Transformer[C1, C2] = Transformable[C1, C2].instance
88-
implicit val dTransformer: Transformer[D1, D2] = Transformable[D1, D2].mapField(_.c1, _.c2).instance
101+
implicit val dTransformer: Transformer[D1, D2] = Transformable[D1, D2].setName(_.c1, _.c2).instance
89102

90103
val d1 = D1(C1(1))
91104
val d2: D2 = Transformer[D1, D2].transform(d1)
@@ -99,14 +112,14 @@ class TransformableTest extends AnyFlatSpec with Matchers {
99112
case class D2(c2: List[C2])
100113

101114
implicit val cTransformer: Transformer[C1, C2] = Transformable[C1, C2].instance
102-
implicit val dTransformer: Transformer[D1, D2] = Transformable[D1, D2].mapField(_.c1, _.c2).instance
115+
implicit val dTransformer: Transformer[D1, D2] = Transformable[D1, D2].setName(_.c1, _.c2).instance
103116

104117
val d1 = D1(List(C1(1), C1(2)))
105118
val d2: D2 = Transformer[D1, D2].transform(d1)
106119
println(d2)
107120
}
108121

109-
"TransformableTest more complex case for two-layer nest field" should "ok for implicit and non-implicit(mapField)" in {
122+
"TransformableTest more complex case for two-layer nest field" should "ok for implicit and non-implicit(setName)" in {
110123
case class C1(j: Int)
111124
case class D1(c1: List[List[C1]])
112125

@@ -119,11 +132,10 @@ class TransformableTest extends AnyFlatSpec with Matchers {
119132

120133
object D1 {
121134
implicit val dTransformer: Transformer[D1, D2] = Transformable[D1, D2]
122-
.mapField[List[List[C1]], List[List[C2]]](
135+
.setName(_.c1, _.c2)
136+
.setType[List[List[C1]], List[List[C2]]](
123137
_.c1,
124-
_.c2,
125-
// implicit values of nested dependencies cannot be at the same level, so move it to companion their object
126-
(c1: List[List[C1]]) => c1.map(_.map(Transformer[C1, C2].transform(_)))
138+
_.map(_.map(Transformer[C1, C2].transform(_)))
127139
)
128140
.instance
129141
}
@@ -162,12 +174,12 @@ class TransformableTest extends AnyFlatSpec with Matchers {
162174

163175
object D1 {
164176
implicit val dTransformer: Transformer[D1, D2] = Transformable[D1, D2]
165-
.mapField(_.a1, _.a2)
166-
.mapField(_.b1, _.b2)
167-
.mapField(_.c1, _.c2)
168-
.mapField(_.d1, _.d2)
169-
.mapField(_.map1, _.map2)
170-
.mapField(_.intMap1, _.intMap2)
177+
.setName(_.a1, _.a2)
178+
.setName(_.b1, _.b2)
179+
.setName(_.c1, _.c2)
180+
.setName(_.d1, _.d2)
181+
.setName(_.map1, _.map2)
182+
.setName(_.intMap1, _.intMap2)
171183
.instance
172184
}
173185

@@ -191,7 +203,7 @@ class TransformableTest extends AnyFlatSpec with Matchers {
191203
case class A1(a: String, b: Int, cc: Int, d: Option[String]) // weak conformance
192204
case class A2(a: String, b: Int, c: Long, d: Option[String])
193205
object A1 {
194-
implicit val aTransformer: Transformer[A1, A2] = Transformable[A1, A2].mapField(_.cc, _.c).instance
206+
implicit val aTransformer: Transformer[A1, A2] = Transformable[A1, A2].setName(_.cc, _.c).instance
195207
}
196208
val a1 = A1("hello", 1, 2, None)
197209
val a2 = Transformer[A1, A2].transform(a1)
@@ -201,11 +213,11 @@ class TransformableTest extends AnyFlatSpec with Matchers {
201213

202214
"TransformableTest type cannot match" should "compile failed if can't use weak conformance" in {
203215
"""
204-
| case class A1(a: String, b: Int, cc: Long, d: Option[String]) // Can't to use weak conformance, must use `mapField(?,?,?)` method for it.
216+
| case class A1(a: String, b: Int, cc: Long, d: Option[String]) // Can't to use weak conformance, must use `setName(?,?,?)` method for it.
205217
| case class A2(a: String, b: Int, c: Int, d: Option[String])
206218
| object A1 {
207219
|
208-
| implicit val aTransformer: Transformer[A1, A2] = Transformable[A1, A2].mapField(_.cc,_.c).instance
220+
| implicit val aTransformer: Transformer[A1, A2] = Transformable[A1, A2].setName(_.cc,_.c).instance
209221
| }
210222
| val a1 = A1("hello", 1, 2, None)
211223
| val a2 = Transformer[A1, A2].transform(a1)
@@ -269,7 +281,7 @@ class TransformableTest extends AnyFlatSpec with Matchers {
269281
object D1 {
270282

271283
implicit val dTransformer: Transformer[D1, D2] = Transformable[D1, D2]
272-
.mapField(_.a1, _.a2)
284+
.setName(_.a1, _.a2)
273285
.instance
274286
}
275287

@@ -306,9 +318,9 @@ class TransformableTest extends AnyFlatSpec with Matchers {
306318
object D1 {
307319

308320
implicit val dTransformer: Transformer[D1, D2] = Transformable[D1, D2]
309-
.mapField(_.a1, _.a2)
310-
.mapField(_.b1, _.b2)
311-
.mapField(_.c1, _.c2)
321+
.setName(_.a1, _.a2)
322+
.setName(_.b1, _.b2)
323+
.setName(_.c1, _.c2)
312324
.instance
313325
}
314326

smt-common/src/test/scala/org/bitlap/common/models.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ object models {
4040
// mapping name
4141
implicit val queryResultTransform: Transformer[FQueryResult, TQueryResult] =
4242
Transformable[FQueryResult, TQueryResult]
43-
.mapField(_.rows, _.trows)
44-
.mapField(_.tableSchema, _.ttableSchema)
43+
.setName(_.rows, _.trows)
44+
.setName(_.tableSchema, _.ttableSchema)
4545
.instance
4646
}
4747

@@ -69,7 +69,7 @@ object models {
6969

7070
object FColumnDesc {
7171
implicit val columnDescTransform: Transformer[FColumnDesc, TColumnDesc] = Transformable[FColumnDesc, TColumnDesc]
72-
.mapField(_.columnName, _.tcolumnName) // mapping name
72+
.setName(_.columnName, _.tcolumnName) // mapping name
7373
.instance
7474
}
7575
}

0 commit comments

Comments
 (0)