@@ -53,4 +53,47 @@ class PostgresDialect : BasicJdbcDialect() {
5353 updPart,
5454 )
5555 }
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+ }
5699}
0 commit comments