From a7f6ef330a5f8d96a924949820e50a6c3434b3d6 Mon Sep 17 00:00:00 2001 From: Elmir Shamsutdinov Date: Fri, 7 Aug 2026 12:03:32 +0300 Subject: [PATCH 1/4] added new columns --- .gitignore | 1 + .../pgsqlblocks/common/models/DBProcess.java | 17 ++++++++++- .../common/ui/DBProcessesViewDataSource.java | 8 ++++++ .../pgsqlblocks/l10n/PgSqlBlocks_en.java | 2 ++ .../pgsqlblocks/l10n/PgSqlBlocks_ru.java | 2 ++ .../taximaxim/pgsqlblocks/utils/Columns.java | 4 ++- .../xmlstore/DBBlocksXmlStore.java | 28 ++++++++++++------- .../tree/ExtendedTreeViewerComponent.java | 4 ++- src/main/resources/query.sql | 2 ++ src/main/resources/query_with_idle.sql | 2 ++ .../common/models/DBBlocksJournalTest.java | 2 +- 11 files changed, 58 insertions(+), 14 deletions(-) diff --git a/.gitignore b/.gitignore index d7e565a..e3d38c1 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,5 @@ /.classpath /.project /.settings/ +/.vscode github.token diff --git a/src/main/java/ru/taximaxim/pgsqlblocks/common/models/DBProcess.java b/src/main/java/ru/taximaxim/pgsqlblocks/common/models/DBProcess.java index 002ed54..5c112c4 100644 --- a/src/main/java/ru/taximaxim/pgsqlblocks/common/models/DBProcess.java +++ b/src/main/java/ru/taximaxim/pgsqlblocks/common/models/DBProcess.java @@ -37,16 +37,21 @@ public class DBProcess implements IObject { private final Date stateChange; //изменено private final DBProcessQuery query; private final DBProcessQueryCaller queryCaller; + private final String waitEventType; + private final String waitEventName; private DBProcessStatus status = DBProcessStatus.WORKING; - public DBProcess(int pid, String backendType, DBProcessQueryCaller queryCaller, String state, Date stateChange, DBProcessQuery query) { + public DBProcess(int pid, String backendType, DBProcessQueryCaller queryCaller, String state, Date stateChange, + DBProcessQuery query, String waitEventType, String waintEventName) { this.pid = pid; this.backendType = backendType; this.queryCaller = queryCaller; this.state = state; this.stateChange = stateChange; this.query = query; + this.waitEventType = waitEventType; + this.waitEventName = waintEventName; } public void addBlock(DBBlock block) { @@ -126,6 +131,14 @@ public DBProcessQueryCaller getQueryCaller() { return queryCaller; } + public String getWaitEventType() { + return waitEventType; + } + + public String getWaitEventName() { + return waitEventName; + } + @Override public List getChildren() { return children; @@ -160,6 +173,8 @@ public String toString() { ", stateChange=" + stateChange + ", query=" + query + ", queryCaller=" + queryCaller + + ", waitEventType=" + waitEventType + + ", waitEventName=" + waitEventName + ", status=" + status + '}'; } diff --git a/src/main/java/ru/taximaxim/pgsqlblocks/common/ui/DBProcessesViewDataSource.java b/src/main/java/ru/taximaxim/pgsqlblocks/common/ui/DBProcessesViewDataSource.java index ae32f75..b0012a0 100644 --- a/src/main/java/ru/taximaxim/pgsqlblocks/common/ui/DBProcessesViewDataSource.java +++ b/src/main/java/ru/taximaxim/pgsqlblocks/common/ui/DBProcessesViewDataSource.java @@ -97,6 +97,10 @@ public String getRowText(Object element, Columns column) { return String.valueOf(process.getQuery().isSlowQuery()); case QUERY: return process.getQuery().getQueryFirstLine(); + case WAIT_EVENT_TYPE: + return process.getWaitEventType(); + case WAIT_EVENT_NAME: + return process.getWaitEventName(); default: return ""; } @@ -189,6 +193,10 @@ public int compare(Object e1, Object e2, Columns column) { case SLOW_QUERY: return Boolean.compare(process1.getQuery().isSlowQuery(), process2.getQuery().isSlowQuery()); + case WAIT_EVENT_TYPE: + return process1.getWaitEventType().compareTo(process2.getWaitEventType()); + case WAIT_EVENT_NAME: + return process1.getWaitEventName().compareTo(process2.getWaitEventName()); default: return 0; } diff --git a/src/main/java/ru/taximaxim/pgsqlblocks/l10n/PgSqlBlocks_en.java b/src/main/java/ru/taximaxim/pgsqlblocks/l10n/PgSqlBlocks_en.java index 369b137..c8a895f 100644 --- a/src/main/java/ru/taximaxim/pgsqlblocks/l10n/PgSqlBlocks_en.java +++ b/src/main/java/ru/taximaxim/pgsqlblocks/l10n/PgSqlBlocks_en.java @@ -109,6 +109,8 @@ protected Object[][] getContents() { {"block_start_date", "Block started"}, {"block_end_date", "Block ended"}, {"duration", "Duration"}, + {"wait_event_type", "Wait event type"}, + {"wait_event", "Wait event name"}, // settings dialog {"processes", "Processes"}, diff --git a/src/main/java/ru/taximaxim/pgsqlblocks/l10n/PgSqlBlocks_ru.java b/src/main/java/ru/taximaxim/pgsqlblocks/l10n/PgSqlBlocks_ru.java index 97a1e51..71f6350 100644 --- a/src/main/java/ru/taximaxim/pgsqlblocks/l10n/PgSqlBlocks_ru.java +++ b/src/main/java/ru/taximaxim/pgsqlblocks/l10n/PgSqlBlocks_ru.java @@ -109,6 +109,8 @@ protected Object[][] getContents() { {"block_start_date", "Блокировка началась"}, {"block_end_date", "Блокировка завершена"}, {"duration", "Длительность"}, + {"wait_event_type", "Тип ожидаемого события"}, + {"wait_event", "Имя ожидавемого события"}, // settings dialog {"processes", "Процессы"}, diff --git a/src/main/java/ru/taximaxim/pgsqlblocks/utils/Columns.java b/src/main/java/ru/taximaxim/pgsqlblocks/utils/Columns.java index 1f7aabb..92ed567 100644 --- a/src/main/java/ru/taximaxim/pgsqlblocks/utils/Columns.java +++ b/src/main/java/ru/taximaxim/pgsqlblocks/utils/Columns.java @@ -36,7 +36,9 @@ public enum Columns { LOCK_TYPE("lock_type"), RELATION("relation"), SLOW_QUERY("slow_query"), - QUERY("query"); + QUERY("query"), + WAIT_EVENT_TYPE("wait_event_type"), + WAIT_EVENT_NAME("wait_event"); private final String columnName; diff --git a/src/main/java/ru/taximaxim/pgsqlblocks/xmlstore/DBBlocksXmlStore.java b/src/main/java/ru/taximaxim/pgsqlblocks/xmlstore/DBBlocksXmlStore.java index 4bc1306..3c30015 100644 --- a/src/main/java/ru/taximaxim/pgsqlblocks/xmlstore/DBBlocksXmlStore.java +++ b/src/main/java/ru/taximaxim/pgsqlblocks/xmlstore/DBBlocksXmlStore.java @@ -67,6 +67,8 @@ public class DBBlocksXmlStore extends XmlStore { private static final String USE_NAME = "usename"; private static final String CLIENT = "client"; private static final String PROCESS_STATUS = "processStatus"; + private static final String WAIT_EVENT_TYPE = "wait_event_type"; + private static final String WAIT_EVENT_NAME = "wait_event"; private final String fileName; @@ -96,7 +98,7 @@ private DBProcess parseProcess(Node node) { int pid = Integer.parseInt(rootElement.getElementsByTagName(PID).item(0).getTextContent()); String backendType = ""; - if (hasBackendType(rootElement)) { + if (hasElement(rootElement, BACKEND_TYPE)) { backendType = rootElement.getElementsByTagName(BACKEND_TYPE).item(0).getTextContent(); } String appName = rootElement.getElementsByTagName(APPLICATION_NAME).item(0).getTextContent(); @@ -110,13 +112,19 @@ private DBProcess parseProcess(Node node) { Date queryStart = DateUtils.dateFromString(rootElement.getElementsByTagName(QUERY_START).item(0).getTextContent()); Date xactStart = DateUtils.dateFromString(rootElement.getElementsByTagName(XACT_START).item(0).getTextContent()); String duration = ""; - if (hasDuration(rootElement)) { + if (hasElement(rootElement, DURATION)) { duration = rootElement.getElementsByTagName(DURATION).item(0).getTextContent(); } DBProcessQuery query = new DBProcessQuery(queryString, slowQuery, backendStart, queryStart, xactStart, duration); String state = rootElement.getElementsByTagName(STATE).item(0).getTextContent(); Date stateChange = DateUtils.dateFromString(rootElement.getElementsByTagName(STATE_CHANGE).item(0).getTextContent()); - DBProcess process = new DBProcess(pid, backendType, caller, state, stateChange, query); + String waitEventType = ""; + String waitEventName = ""; + if (hasElement(rootElement, WAIT_EVENT_TYPE)) { + waitEventType = rootElement.getElementsByTagName(WAIT_EVENT_TYPE).item(0).getTextContent(); + waitEventName = rootElement.getElementsByTagName(WAIT_EVENT_NAME).item(0).getTextContent(); + } + DBProcess process = new DBProcess(pid, backendType, caller, state, stateChange, query, waitEventType, waitEventName); Element childrenRootElement = (Element)rootElement.getElementsByTagName(CHILDREN_ELEMENT_TAG_NAME).item(0); NodeList childrenElements = childrenRootElement.getChildNodes(); for (int i = 0; i < childrenElements.getLength(); i++) { @@ -165,17 +173,15 @@ private void appendProcess(Document xml, Element root, DBProcess process) { createSubElement(xml, rootElement, USE_NAME, process.getQueryCaller().getUserName()); createSubElement(xml, rootElement, CLIENT, process.getQueryCaller().getClient()); createSubElement(xml, rootElement, PROCESS_STATUS, process.getStatus().getDescr()); + createSubElement(xml, rootElement, WAIT_EVENT_TYPE, process.getWaitEventType()); + createSubElement(xml, rootElement, WAIT_EVENT_NAME, process.getWaitEventName()); Element childrenElement = xml.createElement(CHILDREN_ELEMENT_TAG_NAME); rootElement.appendChild(childrenElement); process.getChildren().forEach(p -> appendProcess(xml, childrenElement, p)); } - private boolean hasBackendType(Element element) { - return element.getElementsByTagName(BACKEND_TYPE).getLength() > 0; - } - - private boolean hasDuration(Element element) { - return element.getElementsByTagName(DURATION).getLength() > 0; + private boolean hasElement(Element element, String elmentTagName) { + return 0 < element.getElementsByTagName(elmentTagName).getLength(); } public static DBProcess readFromResultSet(ResultSet resultSet) throws SQLException { @@ -197,8 +203,10 @@ public static DBProcess readFromResultSet(ResultSet resultSet) throws SQLExcepti String userName = resultSet.getString(USE_NAME); String client = resultSet.getString(CLIENT); DBProcessQueryCaller caller = new DBProcessQueryCaller(appName, databaseName, userName, client); + String waitEventType = null == resultSet.getString(WAIT_EVENT_TYPE) ? "" : resultSet.getString(WAIT_EVENT_TYPE); + String waitEventName = null == resultSet.getString(WAIT_EVENT_NAME) ? "" : resultSet.getString(WAIT_EVENT_NAME); - return new DBProcess(pid, backendType, caller, state, stateChangeDate, query); + return new DBProcess(pid, backendType, caller, state, stateChangeDate, query, waitEventType, waitEventName); } private static boolean hasBackendType(ResultSetMetaData metaData) { diff --git a/src/main/java/ru/taximaxim/treeviewer/tree/ExtendedTreeViewerComponent.java b/src/main/java/ru/taximaxim/treeviewer/tree/ExtendedTreeViewerComponent.java index 57a692e..2e95694 100644 --- a/src/main/java/ru/taximaxim/treeviewer/tree/ExtendedTreeViewerComponent.java +++ b/src/main/java/ru/taximaxim/treeviewer/tree/ExtendedTreeViewerComponent.java @@ -235,7 +235,9 @@ private String getColumnTooltip(Columns column) { case LOCK_TYPE: case RELATION: case SLOW_QUERY: - case QUERY: return column.name(); + case QUERY: + case WAIT_EVENT_TYPE: + case WAIT_EVENT_NAME: return column.name(); case DURATION: return "now - XACT_START"; default : return ""; } diff --git a/src/main/resources/query.sql b/src/main/resources/query.sql index 4c3cf84..80a47c0 100644 --- a/src/main/resources/query.sql +++ b/src/main/resources/query.sql @@ -28,6 +28,8 @@ SELECT datname, usename, backend_type, + wait_event_type, + wait_event, CASE WHEN client_port=-1 THEN 'local pipe' WHEN length(client_hostname)>0 THEN client_hostname||':'||client_port ELSE textin(inet_out(client_addr))||':'||client_port diff --git a/src/main/resources/query_with_idle.sql b/src/main/resources/query_with_idle.sql index 3b97ba2..7592825 100644 --- a/src/main/resources/query_with_idle.sql +++ b/src/main/resources/query_with_idle.sql @@ -28,6 +28,8 @@ SELECT datname, usename, backend_type, + wait_event_type, + wait_event, CASE WHEN client_port=-1 THEN 'local pipe' WHEN length(client_hostname)>0 THEN client_hostname||':'||client_port ELSE textin(inet_out(client_addr))||':'||client_port diff --git a/src/test/java/ru/taximaxim/pgsqlblocks/common/models/DBBlocksJournalTest.java b/src/test/java/ru/taximaxim/pgsqlblocks/common/models/DBBlocksJournalTest.java index dc9322f..6742732 100644 --- a/src/test/java/ru/taximaxim/pgsqlblocks/common/models/DBBlocksJournalTest.java +++ b/src/test/java/ru/taximaxim/pgsqlblocks/common/models/DBBlocksJournalTest.java @@ -144,6 +144,6 @@ private DBProcessQuery createDBProcessQuery() { private DBProcess createDBProcess(int pid, DBProcessQuery processQuery) { DBProcessQueryCaller c = new DBProcessQueryCaller("appName", "test", "user", "client"); - return new DBProcess(pid, "type", c, "state", new Date(), processQuery); + return new DBProcess(pid, "type", c, "state", new Date(), processQuery, "", ""); } } \ No newline at end of file From a9342109192d883a027f8351c2231ba0f042fc2f Mon Sep 17 00:00:00 2001 From: Elmir Shamsutdinov Date: Fri, 7 Aug 2026 12:05:10 +0300 Subject: [PATCH 2/4] updated changelogs --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 18525c1..ca1887d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ java-приложение для работы с блокировками в С * Исправлена уязвимость при чтении XML * Обновлены action-ы в gitHubActions * Прекращена поддержка PostgreSQL версий ниже 10, удалена настройка для отображения типа процесса +* Добавлены новые столбцы `Тип ожидаемого события` и `Имя ожидавемого события` 1.9.0 From ca60882ed06d47e9c63202a84cba128e187bd6ca Mon Sep 17 00:00:00 2001 From: Elmir Shamsutdinov Date: Fri, 7 Aug 2026 15:00:03 +0300 Subject: [PATCH 3/4] updated by feedback --- CHANGELOG.md | 2 +- .../ru/taximaxim/pgsqlblocks/l10n/PgSqlBlocks_ru.java | 2 +- .../pgsqlblocks/xmlstore/DBBlocksXmlStore.java | 11 ++++++++--- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ca1887d..044b417 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,7 @@ java-приложение для работы с блокировками в С * Исправлена уязвимость при чтении XML * Обновлены action-ы в gitHubActions * Прекращена поддержка PostgreSQL версий ниже 10, удалена настройка для отображения типа процесса -* Добавлены новые столбцы `Тип ожидаемого события` и `Имя ожидавемого события` +* Добавлены новые столбцы `Тип ожидаемого события` и `Имя ожидаемого события` 1.9.0 diff --git a/src/main/java/ru/taximaxim/pgsqlblocks/l10n/PgSqlBlocks_ru.java b/src/main/java/ru/taximaxim/pgsqlblocks/l10n/PgSqlBlocks_ru.java index 71f6350..0da6025 100644 --- a/src/main/java/ru/taximaxim/pgsqlblocks/l10n/PgSqlBlocks_ru.java +++ b/src/main/java/ru/taximaxim/pgsqlblocks/l10n/PgSqlBlocks_ru.java @@ -110,7 +110,7 @@ protected Object[][] getContents() { {"block_end_date", "Блокировка завершена"}, {"duration", "Длительность"}, {"wait_event_type", "Тип ожидаемого события"}, - {"wait_event", "Имя ожидавемого события"}, + {"wait_event", "Имя ожидаемого события"}, // settings dialog {"processes", "Процессы"}, diff --git a/src/main/java/ru/taximaxim/pgsqlblocks/xmlstore/DBBlocksXmlStore.java b/src/main/java/ru/taximaxim/pgsqlblocks/xmlstore/DBBlocksXmlStore.java index 3c30015..158bb65 100644 --- a/src/main/java/ru/taximaxim/pgsqlblocks/xmlstore/DBBlocksXmlStore.java +++ b/src/main/java/ru/taximaxim/pgsqlblocks/xmlstore/DBBlocksXmlStore.java @@ -187,7 +187,7 @@ private boolean hasElement(Element element, String elmentTagName) { public static DBProcess readFromResultSet(ResultSet resultSet) throws SQLException { int pid = resultSet.getInt(PID); String backendType = hasBackendType(resultSet.getMetaData()) ? resultSet.getString(BACKEND_TYPE) : ""; - String state = resultSet.getString(STATE) == null ? "" : resultSet.getString(STATE); + String state = getStringOrBlank(resultSet, STATE); Date stateChangeDate = DateUtils.dateFromString(resultSet.getString(STATE_CHANGE)); String queryString = resultSet.getString(QUERY_SQL); @@ -203,12 +203,17 @@ public static DBProcess readFromResultSet(ResultSet resultSet) throws SQLExcepti String userName = resultSet.getString(USE_NAME); String client = resultSet.getString(CLIENT); DBProcessQueryCaller caller = new DBProcessQueryCaller(appName, databaseName, userName, client); - String waitEventType = null == resultSet.getString(WAIT_EVENT_TYPE) ? "" : resultSet.getString(WAIT_EVENT_TYPE); - String waitEventName = null == resultSet.getString(WAIT_EVENT_NAME) ? "" : resultSet.getString(WAIT_EVENT_NAME); + String waitEventType = getStringOrBlank(resultSet, WAIT_EVENT_TYPE); + String waitEventName = getStringOrBlank(resultSet, WAIT_EVENT_NAME); return new DBProcess(pid, backendType, caller, state, stateChangeDate, query, waitEventType, waitEventName); } + private static String getStringOrBlank(ResultSet resultSet, String columnName) throws SQLException { + String columnValue = resultSet.getString(columnName); + return null == columnValue ? "" : columnValue; + } + private static boolean hasBackendType(ResultSetMetaData metaData) { try { int columns = metaData.getColumnCount(); From 383cacf49dbf80b671348ce38bf5462f20c0954c Mon Sep 17 00:00:00 2001 From: Elmir Shamsutdinov Date: Fri, 7 Aug 2026 15:05:52 +0300 Subject: [PATCH 4/4] updated by feedback --- .../pgsqlblocks/xmlstore/DBBlocksXmlStore.java | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/src/main/java/ru/taximaxim/pgsqlblocks/xmlstore/DBBlocksXmlStore.java b/src/main/java/ru/taximaxim/pgsqlblocks/xmlstore/DBBlocksXmlStore.java index 158bb65..34282af 100644 --- a/src/main/java/ru/taximaxim/pgsqlblocks/xmlstore/DBBlocksXmlStore.java +++ b/src/main/java/ru/taximaxim/pgsqlblocks/xmlstore/DBBlocksXmlStore.java @@ -186,7 +186,7 @@ private boolean hasElement(Element element, String elmentTagName) { public static DBProcess readFromResultSet(ResultSet resultSet) throws SQLException { int pid = resultSet.getInt(PID); - String backendType = hasBackendType(resultSet.getMetaData()) ? resultSet.getString(BACKEND_TYPE) : ""; + String backendType = getStringOrBlank(resultSet, BACKEND_TYPE); String state = getStringOrBlank(resultSet, STATE); Date stateChangeDate = DateUtils.dateFromString(resultSet.getString(STATE_CHANGE)); @@ -213,19 +213,4 @@ private static String getStringOrBlank(ResultSet resultSet, String columnName) t String columnValue = resultSet.getString(columnName); return null == columnValue ? "" : columnValue; } - - private static boolean hasBackendType(ResultSetMetaData metaData) { - try { - int columns = metaData.getColumnCount(); - for (int x = 1; x <= columns; x++) { - if (BACKEND_TYPE.equals(metaData.getColumnName(x))) { - return true; - } - } - } catch (SQLException e) { - LOG.error(e.getMessage()); - } - return false; - } - }