Skip to content

Commit 30abd2f

Browse files
committed
Merge branch 'DBTOOLS-1689-queries' into 'master'
DBTOOLS-1689 optimized queries See merge request codekeeper/pgcodekeeper-core!85
2 parents 7db32ae + 955f939 commit 30abd2f

10 files changed

Lines changed: 77 additions & 82 deletions

File tree

src/main/java/org/pgcodekeeper/core/loader/QueryBuilder.java

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ public final class QueryBuilder {
3333
private final List<String> joins = new ArrayList<>();
3434
private final List<String> wheres = new ArrayList<>();
3535
private final List<String> groups = new ArrayList<>();
36+
private final List<String> orders = new ArrayList<>();
3637
private String postAction;
3738

3839
/**
@@ -193,6 +194,17 @@ public QueryBuilder groupBy(String group) {
193194
return this;
194195
}
195196

197+
/**
198+
* Adds a ORDER BY expression to the query.
199+
*
200+
* @param order the ORDER BY expression
201+
* @return this builder for method chaining
202+
*/
203+
public QueryBuilder orderBy(String order) {
204+
orders.add(order);
205+
return this;
206+
}
207+
196208
/**
197209
* Builds and returns the complete SQL query string.
198210
*
@@ -220,13 +232,9 @@ public String build() {
220232
sb.append("\n").append(join);
221233
}
222234

223-
if (!wheres.isEmpty()) {
224-
sb.append("\nWHERE ").append(String.join("\n AND ", wheres));
225-
}
226-
227-
if (!groups.isEmpty()) {
228-
sb.append("\nGROUP BY ").append(String.join(", ", groups));
229-
}
235+
appendList(wheres, "\nWHERE ", "\n AND ", sb);
236+
appendList(groups, "\nGROUP BY ", ", ", sb);
237+
appendList(orders, "\nORDER BY ", ", ", sb);
230238

231239
if (postAction != null) {
232240
sb.append("\n").append(postAction);
@@ -235,6 +243,12 @@ public String build() {
235243
return sb.toString();
236244
}
237245

246+
private void appendList(List<String> list, String prefix, String delimiter, StringBuilder sb) {
247+
if (!list.isEmpty()) {
248+
sb.append(prefix).append(String.join(delimiter, list));
249+
}
250+
}
251+
238252
private void appendChild(StringBuilder sb, QueryBuilder childBuilder) {
239253
appendChild(sb, childBuilder, 2);
240254
}

src/main/java/org/pgcodekeeper/core/loader/jdbc/AbstractStatementReader.java

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ public abstract class AbstractStatementReader {
3939
.column("roleprinc.name AS r")
4040
.from("sys.database_principals roleprinc WITH (NOLOCK)")
4141
.join("JOIN sys.database_permissions perm WITH (NOLOCK) ON perm.grantee_principal_id = roleprinc.principal_id")
42-
.join("LEFT JOIN sys.columns col WITH (NOLOCK) ON col.object_id = perm.major_id AND col.column_id = perm.minor_id");
42+
.join("LEFT JOIN sys.columns col WITH (NOLOCK) ON col.object_id = perm.major_id AND col.column_id = perm.minor_id")
43+
.postAction("FOR XML RAW, ROOT");
4344

4445
protected static final QueryBuilder EXTENSION_DEPS_CTE_BUILDER = new QueryBuilder()
4546
.column("objid")
@@ -124,11 +125,7 @@ protected void addDescriptionPart(QueryBuilder builder, boolean checkColumn) {
124125
}
125126

126127
protected void addMsPriviligesPart(QueryBuilder builder) {
127-
var subSelect = new QueryBuilder()
128-
.column("*")
129-
.from(formatMsPriviliges(MS_PRIVILEGES_JOIN_SUBSELECT.copy()), "aa")
130-
.postAction("FOR XML RAW, ROOT");
131-
128+
var subSelect = formatMsPriviliges(MS_PRIVILEGES_JOIN_SUBSELECT.copy());
132129
builder
133130
.column("aa.acl")
134131
.join("CROSS APPLY", subSelect, "aa (acl)");

src/main/java/org/pgcodekeeper/core/loader/jdbc/ms/MsExtendedObjectsReader.java

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -197,16 +197,12 @@ private void addMsColumnsPart(QueryBuilder builder) {
197197
.column("t.is_user_defined AS ud")
198198
.from("sys.columns as c WITH (NOLOCK)")
199199
.join("JOIN sys.types t WITH (NOLOCK) ON c.user_type_id = t.user_type_id")
200-
.where("c.object_id = res.object_id");
201-
202-
QueryBuilder cols = new QueryBuilder()
203-
.column("*")
204-
.from(subSelect, "ccc ORDER BY ccc.id")
200+
.where("c.object_id = res.object_id")
201+
.orderBy("c.column_id")
205202
.postAction("FOR XML RAW, ROOT");
206203

207204
builder.column("ccc.cols");
208-
builder.join("CROSS APPLY", cols, "ccc (cols)");
209-
205+
builder.join("CROSS APPLY", subSelect, "ccc (cols)");
210206
}
211207

212208
private void addMsArgsPart(QueryBuilder builder) {
@@ -228,15 +224,11 @@ private void addMsArgsPart(QueryBuilder builder) {
228224
.join("JOIN sys.parameters p WITH (NOLOCK) ON so.object_id = p.object_id")
229225
.join("JOIN sys.types t WITH (NOLOCK) ON p.user_type_id = t.user_type_id")
230226
.where("p.parameter_id > 0")
231-
.where("so.object_id = res.object_id");
232-
233-
QueryBuilder args = new QueryBuilder()
234-
.column("*")
235-
.from(subSelect, "cc ORDER BY cc.id")
227+
.where("so.object_id = res.object_id")
228+
.orderBy("id")
236229
.postAction("FOR XML RAW, ROOT");
237230

238231
builder.column("cc.args");
239-
builder.join("CROSS APPLY", args, "cc (args)");
240-
232+
builder.join("CROSS APPLY", subSelect, "cc (args)");
241233
}
242234
}

src/main/java/org/pgcodekeeper/core/loader/jdbc/ms/MsFKReader.java

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -108,21 +108,17 @@ protected void fillQueryBuilder(QueryBuilder builder) {
108108

109109
protected void addMsColsPart(QueryBuilder builder) {
110110
QueryBuilder subSelect = new QueryBuilder()
111-
.column("sfkc.constraint_column_id AS id")
112111
.column("fc.name AS f")
113112
.column("rc.name AS r")
114113
.from("sys.foreign_key_columns AS sfkc WITH (NOLOCK)")
115114
.join("JOIN sys.columns fc WITH (NOLOCK) ON sfkc.parent_column_id=fc.column_id AND fc.object_id=sfkc.parent_object_id")
116115
.join("JOIN sys.columns rc WITH (NOLOCK) ON sfkc.referenced_column_id=rc.column_id AND rc.object_id=sfkc.referenced_object_id")
117-
.where("res.object_id=sfkc.constraint_object_id");
118-
119-
QueryBuilder cols = new QueryBuilder()
120-
.column("*")
121-
.from(subSelect, "cc ORDER BY cc.id")
116+
.where("res.object_id=sfkc.constraint_object_id")
117+
.orderBy("sfkc.constraint_column_id")
122118
.postAction("FOR XML RAW, ROOT");
123119

124120
builder.column("aa.cols");
125-
builder.join("CROSS APPLY", cols, "aa (cols)");
121+
builder.join("CROSS APPLY", subSelect, "aa (cols)");
126122
}
127123

128124
@Override

src/main/java/org/pgcodekeeper/core/loader/jdbc/ms/MsIndicesAndPKReader.java

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -213,27 +213,23 @@ protected void fillQueryBuilder(QueryBuilder builder) {
213213

214214
protected void addMsColsPart(QueryBuilder builder) {
215215
QueryBuilder subSelect = new QueryBuilder()
216-
.column("c.key_ordinal AS id")
217216
.column("sc.name")
218217
.column("c.is_descending_key AS is_desc")
219218
.column("c.is_included_column AS is_inc")
220219
.from("sys.index_columns c WITH (NOLOCK)")
221220
.join("JOIN sys.columns sc WITH (NOLOCK) ON c.object_id = sc.object_id AND c.column_id = sc.column_id")
222221
.where("c.object_id = res.object_id")
223-
.where("c.index_id = res.index_id");
222+
.where("c.index_id = res.index_id")
223+
.orderBy("c.key_ordinal")
224+
.postAction("FOR XML RAW, ROOT");
224225

225226
if (SupportedMsVersion.VERSION_22.isLE(loader.getVersion())) {
226227
subSelect.column("c.column_store_order_ordinal AS col_order");
227228
}
228229

229-
QueryBuilder cols = new QueryBuilder()
230-
.column("*")
231-
.from(subSelect, "cc ORDER BY cc.id")
232-
.postAction("FOR XML RAW, ROOT");
233-
234230
builder
235231
.column("cc.cols")
236-
.join("CROSS APPLY", cols, "cc (cols)");
232+
.join("CROSS APPLY", subSelect, "cc (cols)");
237233
}
238234

239235
@Override

src/main/java/org/pgcodekeeper/core/loader/jdbc/ms/MsRolesReader.java

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -83,15 +83,11 @@ private void addMsGroupsPart(QueryBuilder builder) {
8383
.column("p1.name AS m")
8484
.from("sys.database_role_members AS rm WITH (NOLOCK)")
8585
.join("INNER JOIN sys.database_principals p1 WITH (NOLOCK) ON rm.member_principal_id=p1.principal_id")
86-
.where("rm.role_principal_id=res.principal_id");
87-
88-
QueryBuilder group = new QueryBuilder()
89-
.column("*")
90-
.from(subSelect, "cc")
86+
.where("rm.role_principal_id=res.principal_id")
9187
.postAction("FOR XML RAW, ROOT");
9288

9389
builder.column("cc.groups");
94-
builder.join("CROSS APPLY", group, "cc (groups)");
90+
builder.join("CROSS APPLY", subSelect, "cc (groups)");
9591
}
9692

9793
@Override

src/main/java/org/pgcodekeeper/core/loader/jdbc/ms/MsStatisticsReader.java

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -87,15 +87,11 @@ protected void processResult(ResultSet res, AbstractSchema schema) throws SQLExc
8787
protected void fillQueryBuilder(QueryBuilder builder) {
8888
QueryBuilder subSelect = new QueryBuilder()
8989
.column("s_column.name AS name")
90-
.column("st_col.stats_column_id AS id")
9190
.from("sys.stats_columns st_col WITH (NOLOCK)")
9291
.join("LEFT JOIN sys.columns s_column WITH (NOLOCK) ON s_column.object_id = res.object_id AND s_column.column_id = st_col.column_id")
9392
.where("st_col.object_id = res.object_id")
94-
.where("st_col.stats_id = res.stats_id");
95-
96-
QueryBuilder cols = new QueryBuilder()
97-
.column("*")
98-
.from(subSelect, "st_col ORDER BY id")
93+
.where("st_col.stats_id = res.stats_id")
94+
.orderBy("st_col.stats_column_id")
9995
.postAction("FOR XML RAW, ROOT");
10096

10197
builder
@@ -106,7 +102,7 @@ protected void fillQueryBuilder(QueryBuilder builder) {
106102
.column("res.no_recompute")
107103
.column("res.is_incremental")
108104
.from("sys.stats res WITH (NOLOCK)")
109-
.join("CROSS APPLY", cols, "st_col (cols)")
105+
.join("CROSS APPLY", subSelect, "st_col (cols)")
110106
.join("LEFT JOIN sys.objects cont WITH (NOLOCK) ON cont.object_id = res.object_id")
111107
.where("res.user_created = 1");
112108

src/main/java/org/pgcodekeeper/core/loader/jdbc/ms/MsTablesReader.java

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -299,16 +299,13 @@ OR TYPE_NAME(t.system_type_id) IN ('TEXT', 'NTEXT','IMAGE' ,'XML')
299299
.join("LEFT JOIN sys.default_constraints dc WITH (NOLOCK) ON dc.parent_object_id = c.object_id AND c.column_id = dc.parent_column_id")
300300
.join("LEFT JOIN sys.objects so WITH (NOLOCK) ON so.object_id = c.object_id")
301301
.join("LEFT JOIN sys.masked_columns mc WITH (NOLOCK) ON mc.object_id = c.object_id AND c.column_id = mc.column_id")
302-
.where("c.object_id = res.object_id");
303-
304-
QueryBuilder cols = new QueryBuilder()
305-
.column("*")
306-
.from(subSelect, "cc ORDER BY cc.id")
302+
.where("c.object_id = res.object_id")
303+
.orderBy("c.column_id")
307304
.postAction("FOR XML RAW, ROOT");
308305

309306
builder
310307
.column("cc.cols")
311-
.join("CROSS APPLY", cols, "cc (cols)");
308+
.join("CROSS APPLY", subSelect, "cc (cols)");
312309
}
313310

314311
private void addMsTablespacePart(QueryBuilder builder) {

src/main/java/org/pgcodekeeper/core/loader/jdbc/ms/MsTypesReader.java

Lines changed: 8 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,6 @@ private void addMsConstraintsPart(QueryBuilder builder) {
182182
private void addMsColumnsPart(QueryBuilder builder) {
183183
QueryBuilder subSelect = new QueryBuilder()
184184
.column("c.name")
185-
.column("c.column_id AS id")
186185
.column("ss.name AS st")
187186
.column("usrt.name AS type")
188187
.column("usrt.is_user_defined AS ud")
@@ -206,31 +205,23 @@ private void addMsColumnsPart(QueryBuilder builder) {
206205
.join("LEFT OUTER JOIN sys.schemas ss WITH (NOLOCK) ON ss.schema_id = usrt.schema_id")
207206
.join("LEFT OUTER JOIN sys.types baset WITH (NOLOCK) ON (baset.user_type_id = c.system_type_id AND baset.user_type_id = baset.system_type_id)")
208207
.join(" OR (baset.system_type_id = c.system_type_id AND baset.user_type_id = c.user_type_id AND baset.is_user_defined = 0 AND baset.is_assembly_type = 1)")
209-
.where("ttt.type_table_object_id=c.object_id");
210-
211-
212-
QueryBuilder cols = new QueryBuilder()
213-
.column("*")
214-
.from(subSelect, "cc ORDER BY cc.id")
208+
.where("ttt.type_table_object_id=c.object_id")
209+
.orderBy("c.column_id")
215210
.postAction("FOR XML RAW, ROOT");
216211

217212
builder.column("cc.cols");
218-
builder.join("CROSS APPLY", cols, "cc (cols)");
213+
builder.join("CROSS APPLY", subSelect, "cc (cols)");
219214
}
220215

221216
private void addMsIndicesPart(QueryBuilder builder) {
222-
QueryBuilder subSubSubSelect = new QueryBuilder()
223-
.column("c.index_column_id AS id")
217+
QueryBuilder subSubSelect = new QueryBuilder()
224218
.column("sc.name")
225219
.column("c.is_descending_key AS is_desc")
226220
.from("sys.index_columns c WITH (NOLOCK)")
227221
.join("JOIN sys.columns sc WITH (NOLOCK) ON c.object_id = sc.object_id AND c.column_id = sc.column_id")
228222
.where("c.object_id = si.object_id")
229-
.where("c.index_id = si.index_id");
230-
231-
QueryBuilder subSubSelect = new QueryBuilder()
232-
.column("*")
233-
.from(subSubSubSelect, "cc ORDER BY cc.id")
223+
.where("c.index_id = si.index_id")
224+
.orderBy("c.index_column_id")
234225
.postAction("FOR XML RAW, ROOT");
235226

236227
QueryBuilder subSelect = new QueryBuilder()
@@ -248,15 +239,11 @@ private void addMsIndicesPart(QueryBuilder builder) {
248239
.join("CROSS APPLY", subSubSelect, "ccc (cols)")
249240
.where("si.object_id=ttt.type_table_object_id")
250241
.where("si.index_id > 0")
251-
.where("si.is_hypothetical = 0");
252-
253-
QueryBuilder indicesBuilder = new QueryBuilder()
254-
.column("*")
255-
.from(subSelect, "ii")
242+
.where("si.is_hypothetical = 0")
256243
.postAction("FOR XML RAW, ROOT");
257244

258245
builder.column("ii.indices");
259-
builder.join("CROSS APPLY", indicesBuilder, "ii (indices)");
246+
builder.join("CROSS APPLY", subSelect, "ii (indices)");
260247
}
261248

262249
@Override

src/test/java/org/pgcodekeeper/core/loader/QueryBuilderTest.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,30 @@ void testGroupBy() {
114114
assertEquals(expected, actual);
115115
}
116116

117+
@Test
118+
void testQuery() {
119+
String actual = new QueryBuilder()
120+
.column("c1")
121+
.from("public.t1")
122+
.where("c1 > 0")
123+
.orderBy("col1")
124+
.orderBy("col2")
125+
.groupBy("col1")
126+
.postAction("FOR XML RAW, ROOT")
127+
.build();
128+
129+
String expected = """
130+
SELECT
131+
c1
132+
FROM public.t1
133+
WHERE c1 > 0
134+
GROUP BY col1
135+
ORDER BY col1, col2
136+
FOR XML RAW, ROOT""";
137+
138+
assertEquals(expected, actual);
139+
}
140+
117141
@Test
118142
void testPostAction() {
119143
String actual = new QueryBuilder()

0 commit comments

Comments
 (0)