-
Notifications
You must be signed in to change notification settings - Fork 2
/
QuereaseResolvers.scala
116 lines (108 loc) · 5.13 KB
/
QuereaseResolvers.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
package org.mojoz.querease
import org.mojoz.metadata.{FieldDef, ViewDef}
import scala.collection.immutable.Seq
import org.tresql.ast.Ident
trait QuereaseResolvers {
this: QuereaseMetadata with QueryStringBuilder with QuereaseExpressions with FilterTransformer =>
import parser._
def allResolvers(view: ViewDef, f: FieldDef): Seq[String] =
allResolversRaw(view, f)
.map(transformResolver(view, f, _))
protected def allResolversRaw(view: ViewDef, f: FieldDef): Seq[String] = {
val name = f.name
val alias = f.fieldName
val saveToMulti = view.saveTo != null && view.saveTo.nonEmpty
val saveTo = if (!saveToMulti) Seq(view.table) else view.saveTo
// TODO view validation - validate f.saveTo and resolvers!
// TODO support refs to ^view.field for expressions and/or resolvers
// TODO support save-to table or alias qualifier
// TODO support some qualifiers in expression?
def explicitResolvers(f: FieldDef) =
Option(f.resolver)
.map(r => Seq(r))
def impliedResolvers(f: FieldDef, doRebaseTable: Boolean) = {
val fSaveTo = Option(f.saveTo) getOrElse name
saveTo
.map(tableMetadata.tableDef(_, view.db))
.filter(_.cols.exists(_.name == fSaveTo))
.flatMap(_.refs.filter(_.cols == Seq(fSaveTo)))
.map { ref =>
val refTable = ref.refTable
val refCol = ref.refCols.head
val expressionOpt =
if (doRebaseTable)
Option(f.expression)
.map(parseExp)
.map(transformer {
case i: Ident =>
if (i.ident.size > 1) i.copy(ident = i.ident.tail) else i
})
.map(_.tresql)
else
Option(f.expression)
val expression = expressionOpt.getOrElse(name)
s"$refTable[$expression = _]{$refCol}" // FIXME use queryString(...)
}
}
def impliedSelfResolvers(f: FieldDef) = {
val fSaveTo = Option(f.saveTo) getOrElse name
saveTo
.map(tableMetadata.tableDef(_, view.db))
.filter(_.cols.exists(_.name == fSaveTo))
.filter(t =>
t.pk.exists(_.cols == Seq(fSaveTo)) ||
t.uk.exists(_.cols == Seq(fSaveTo)))
.map { t =>
val saveToField =
new org.mojoz.metadata.FieldDef(fSaveTo)
.copy(table = t.name /* TODO? tableAlias = refViewDef.tableAlias*/)
val expression = Option(f.expression).getOrElse(name)
queryString(view, Seq(saveToField), Seq(f), s"$expression = _")
}
}
def impliedRefResolvers(f: FieldDef, refViewDef: ViewDef, refFieldDef: FieldDef) = {
val fSaveTo = Option(f.saveTo) getOrElse name
saveTo
.map(tableMetadata.tableDef(_, view.db))
.filter(_.cols.exists(_.name == fSaveTo))
.flatMap(_.refs.filter(_.cols == Seq(fSaveTo)))
.map { ref =>
val refTable = ref.refTable
val refCol = ref.refCols(0)
val expression = Option(refFieldDef.expression).getOrElse(refFieldDef.name)
// TODO check refTable in view tables?
val refColField =
new org.mojoz.metadata.FieldDef(refCol)
.copy(table = refViewDef.table, tableAlias = refViewDef.tableAlias)
queryString(refViewDef, Seq(refColField), Seq(refFieldDef), s"$expression = _")
}
}
def referencedResolvers =
Option(f.expression)
.filter(FieldRefRegexp.pattern.matcher(_).matches)
.map {
case FieldRefRegexp(refViewName, refFieldName, _, _) =>
val refViewDef = viewDefOption(refViewName)
.getOrElse{
throw new RuntimeException(
s"View $refViewName referenced from ${view.name}.$alias is not found")
}
val refFieldDef = refViewDef.fieldOpt(refFieldName)
.getOrElse {
throw new RuntimeException(
s"Field $refViewName.$refFieldName referenced from ${view.name}.$alias is not found")
}
explicitResolvers(refFieldDef)
.getOrElse(impliedRefResolvers(f, refViewDef, refFieldDef))
}
if (f.saveTo != null || f.resolver != null)
explicitResolvers(f)
.orElse(referencedResolvers)
.orElse(Option(impliedResolvers(f, doRebaseTable = true)).filter(_.nonEmpty))
.getOrElse(impliedSelfResolvers(f))
else
Nil
}
protected def transformResolver(view: ViewDef, field: FieldDef, resolver: String): String =
transformExpression(resolver, view, field, QuereaseExpressions.Resolver)
}