@@ -53,4 +53,47 @@ class PostgresDialect : BasicJdbcDialect() {
53
53
updPart,
54
54
)
55
55
}
56
+
57
+ override fun loadQuery (
58
+ fullTblName : String ,
59
+ keyCols : Collection <String >,
60
+ cols : Iterable <String >,
61
+ keyCnt : Int ,
62
+ ): String {
63
+ assert (! keyCols.isEmpty())
64
+ if (keyCols.size == 1 || keyCnt == 1 ) return super .loadQuery(fullTblName, keyCols, cols, keyCnt)
65
+
66
+ /*
67
+ The default implementation generates a query that looks like this:
68
+
69
+ SELECT "repository","key","value"
70
+ FROM "modelix"."model"
71
+ WHERE
72
+ (repository=? AND key=?) OR
73
+ (repository=? AND key=?)
74
+
75
+ Postgres creates a query plan that still uses the index, but is not optimal.
76
+
77
+ For single column primary keys a query using the IN operator would be generated and that leads to a more
78
+ efficient query plan.
79
+
80
+ For the following query a plan is created that is comparable in performance to the IN operator.
81
+
82
+ SELECT repository, key, value
83
+ FROM modelix.model
84
+ JOIN (
85
+ VALUES
86
+ (?, ?),
87
+ (?, ?)
88
+ ) as t (k0,k1)
89
+ ON k0 = repository AND k1 = key
90
+ */
91
+
92
+ val valuesList = (1 .. keyCnt).joinToString(" , " ) { " (?, ?)" }
93
+ val subSelectColumns = keyCols.withIndex().joinToString(" ," ) { " k${it.index} " }
94
+ val joinCondition = keyCols.withIndex().joinToString(" AND " ) { " k${it.index} = ${it.value} " }
95
+ val joinPart = """ JOIN (VALUES $valuesList ) as t ($subSelectColumns ) ON $joinCondition """
96
+ val result = """ SELECT ${cols.joinToString(" , " )} FROM $fullTblName $joinPart """
97
+ return result
98
+ }
56
99
}
0 commit comments