IDEMPIERE-5451 Create a form SQL Query - similar to SQL process to execute queries (FHCA-3849) (#1533)
* IDEMPIERE-5451 Create a form SQL Query - similar to SQL process to execute queries (FHCA-3849) * - fix wrong default in SysConfig * - remove unnecessary annotation * - process the query in a read-only transaction * - commit not needed since this is readonly
This commit is contained in:
parent
9b46986596
commit
67c9cb7abc
|
@ -0,0 +1,82 @@
|
||||||
|
-- IDEMPIERE-5451 Create a form SQL Query - similar to SQL process to execute queries (FHCA-3849)
|
||||||
|
SELECT register_migration_script('202210131930_IDEMPIERE-5451.sql') FROM dual;
|
||||||
|
|
||||||
|
SET SQLBLANKLINES ON
|
||||||
|
SET DEFINE OFF
|
||||||
|
|
||||||
|
-- Oct 13, 2022, 7:30:19 PM CEST
|
||||||
|
INSERT INTO AD_Form (AD_Form_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,Name,Description,Help,Classname,AccessLevel,EntityType,IsBetaFunctionality,AD_Form_UU) VALUES (200018,0,0,'Y',TO_TIMESTAMP('2022-10-13 19:30:19','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2022-10-13 19:30:19','YYYY-MM-DD HH24:MI:SS'),100,'SQL Process','Process SQL Queries','Process SQL Queries','org.adempiere.webui.apps.form.WSQLQuery','4','D','N','c14e305d-8d88-4ee5-9cf6-b2e5ce1213b6')
|
||||||
|
;
|
||||||
|
|
||||||
|
-- Oct 13, 2022, 7:30:35 PM CEST
|
||||||
|
UPDATE AD_Form SET Name='SQL Query',Updated=TO_TIMESTAMP('2022-10-13 19:30:35','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Form_ID=200018
|
||||||
|
;
|
||||||
|
|
||||||
|
-- Oct 13, 2022, 7:31:00 PM CEST
|
||||||
|
INSERT INTO AD_Menu (AD_Menu_ID,Name,Description,Action,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,IsSummary,IsSOTrx,AD_Form_ID,IsReadOnly,EntityType,IsCentrallyMaintained,AD_Menu_UU) VALUES (200218,'SQL Query','Process SQL Queries','X',0,0,'Y',TO_TIMESTAMP('2022-10-13 19:31:00','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2022-10-13 19:31:00','YYYY-MM-DD HH24:MI:SS'),100,'N','N',200018,'N','D','Y','08ed5ba3-ade5-41af-8abc-a10066e072e3')
|
||||||
|
;
|
||||||
|
|
||||||
|
-- Oct 13, 2022, 7:31:00 PM CEST
|
||||||
|
INSERT INTO AD_TreeNodeMM (AD_Client_ID,AD_Org_ID, IsActive,Created,CreatedBy,Updated,UpdatedBy, AD_Tree_ID, Node_ID, Parent_ID, SeqNo, AD_TreeNodeMM_UU) SELECT t.AD_Client_ID, 0, 'Y', getDate(), 100, getDate(), 100,t.AD_Tree_ID, 200218, 0, 999, Generate_UUID() FROM AD_Tree t WHERE t.AD_Client_ID=0 AND t.IsActive='Y' AND t.IsAllNodes='Y' AND t.TreeType='MM' AND NOT EXISTS (SELECT * FROM AD_TreeNodeMM e WHERE e.AD_Tree_ID=t.AD_Tree_ID AND Node_ID=200218)
|
||||||
|
;
|
||||||
|
|
||||||
|
-- Oct 13, 2022, 7:31:15 PM CEST
|
||||||
|
UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=12,Updated=TO_TIMESTAMP('2022-10-13 19:31:15','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Tree_ID=10 AND Node_ID=200218
|
||||||
|
;
|
||||||
|
|
||||||
|
-- Oct 13, 2022, 7:31:15 PM CEST
|
||||||
|
UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=13,Updated=TO_TIMESTAMP('2022-10-13 19:31:15','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Tree_ID=10 AND Node_ID=289
|
||||||
|
;
|
||||||
|
|
||||||
|
-- Oct 13, 2022, 7:31:15 PM CEST
|
||||||
|
UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=14,Updated=TO_TIMESTAMP('2022-10-13 19:31:15','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Tree_ID=10 AND Node_ID=302
|
||||||
|
;
|
||||||
|
|
||||||
|
-- Oct 13, 2022, 7:31:15 PM CEST
|
||||||
|
UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=15,Updated=TO_TIMESTAMP('2022-10-13 19:31:15','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Tree_ID=10 AND Node_ID=200168
|
||||||
|
;
|
||||||
|
|
||||||
|
-- Oct 13, 2022, 7:31:15 PM CEST
|
||||||
|
UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=16,Updated=TO_TIMESTAMP('2022-10-13 19:31:15','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Tree_ID=10 AND Node_ID=200169
|
||||||
|
;
|
||||||
|
|
||||||
|
-- Oct 13, 2022, 7:31:15 PM CEST
|
||||||
|
UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=17,Updated=TO_TIMESTAMP('2022-10-13 19:31:15','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Tree_ID=10 AND Node_ID=303
|
||||||
|
;
|
||||||
|
|
||||||
|
-- Oct 13, 2022, 7:31:15 PM CEST
|
||||||
|
UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=18,Updated=TO_TIMESTAMP('2022-10-13 19:31:15','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Tree_ID=10 AND Node_ID=200047
|
||||||
|
;
|
||||||
|
|
||||||
|
-- Oct 13, 2022, 7:31:15 PM CEST
|
||||||
|
UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=19,Updated=TO_TIMESTAMP('2022-10-13 19:31:15','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Tree_ID=10 AND Node_ID=200048
|
||||||
|
;
|
||||||
|
|
||||||
|
-- Oct 13, 2022, 7:31:15 PM CEST
|
||||||
|
UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=20,Updated=TO_TIMESTAMP('2022-10-13 19:31:15','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Tree_ID=10 AND Node_ID=321
|
||||||
|
;
|
||||||
|
|
||||||
|
-- Oct 13, 2022, 7:31:15 PM CEST
|
||||||
|
UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=21,Updated=TO_TIMESTAMP('2022-10-13 19:31:15','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Tree_ID=10 AND Node_ID=461
|
||||||
|
;
|
||||||
|
|
||||||
|
-- Oct 13, 2022, 7:31:15 PM CEST
|
||||||
|
UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=22,Updated=TO_TIMESTAMP('2022-10-13 19:31:15','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Tree_ID=10 AND Node_ID=53193
|
||||||
|
;
|
||||||
|
|
||||||
|
-- Oct 13, 2022, 7:31:15 PM CEST
|
||||||
|
UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=23,Updated=TO_TIMESTAMP('2022-10-13 19:31:15','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Tree_ID=10 AND Node_ID=200161
|
||||||
|
;
|
||||||
|
|
||||||
|
-- Oct 13, 2022, 7:31:15 PM CEST
|
||||||
|
UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=24,Updated=TO_TIMESTAMP('2022-10-13 19:31:15','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Tree_ID=10 AND Node_ID=53322
|
||||||
|
;
|
||||||
|
|
||||||
|
-- Oct 13, 2022, 7:31:15 PM CEST
|
||||||
|
UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=25,Updated=TO_TIMESTAMP('2022-10-13 19:31:15','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Tree_ID=10 AND Node_ID=383
|
||||||
|
;
|
||||||
|
|
||||||
|
-- Oct 13, 2022, 7:31:15 PM CEST
|
||||||
|
UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=26,Updated=TO_TIMESTAMP('2022-10-13 19:31:15','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Tree_ID=10 AND Node_ID=200177
|
||||||
|
;
|
||||||
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
-- IDEMPIERE-5451 Create a form SQL Query - similar to SQL process to execute queries (FHCA-3849)
|
||||||
|
SELECT register_migration_script('202210131930_IDEMPIERE-5451.sql') FROM dual;
|
||||||
|
|
||||||
|
-- Oct 13, 2022, 7:30:19 PM CEST
|
||||||
|
INSERT INTO AD_Form (AD_Form_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,Name,Description,Help,Classname,AccessLevel,EntityType,IsBetaFunctionality,AD_Form_UU) VALUES (200018,0,0,'Y',TO_TIMESTAMP('2022-10-13 19:30:19','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2022-10-13 19:30:19','YYYY-MM-DD HH24:MI:SS'),100,'SQL Process','Process SQL Queries','Process SQL Queries','org.adempiere.webui.apps.form.WSQLQuery','4','D','N','c14e305d-8d88-4ee5-9cf6-b2e5ce1213b6')
|
||||||
|
;
|
||||||
|
|
||||||
|
-- Oct 13, 2022, 7:30:35 PM CEST
|
||||||
|
UPDATE AD_Form SET Name='SQL Query',Updated=TO_TIMESTAMP('2022-10-13 19:30:35','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Form_ID=200018
|
||||||
|
;
|
||||||
|
|
||||||
|
-- Oct 13, 2022, 7:31:00 PM CEST
|
||||||
|
INSERT INTO AD_Menu (AD_Menu_ID,Name,Description,"action",AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,IsSummary,IsSOTrx,AD_Form_ID,IsReadOnly,EntityType,IsCentrallyMaintained,AD_Menu_UU) VALUES (200218,'SQL Query','Process SQL Queries','X',0,0,'Y',TO_TIMESTAMP('2022-10-13 19:31:00','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2022-10-13 19:31:00','YYYY-MM-DD HH24:MI:SS'),100,'N','N',200018,'N','D','Y','08ed5ba3-ade5-41af-8abc-a10066e072e3')
|
||||||
|
;
|
||||||
|
|
||||||
|
-- Oct 13, 2022, 7:31:00 PM CEST
|
||||||
|
INSERT INTO AD_TreeNodeMM (AD_Client_ID,AD_Org_ID, IsActive,Created,CreatedBy,Updated,UpdatedBy, AD_Tree_ID, Node_ID, Parent_ID, SeqNo, AD_TreeNodeMM_UU) SELECT t.AD_Client_ID, 0, 'Y', statement_timestamp(), 100, statement_timestamp(), 100,t.AD_Tree_ID, 200218, 0, 999, Generate_UUID() FROM AD_Tree t WHERE t.AD_Client_ID=0 AND t.IsActive='Y' AND t.IsAllNodes='Y' AND t.TreeType='MM' AND NOT EXISTS (SELECT * FROM AD_TreeNodeMM e WHERE e.AD_Tree_ID=t.AD_Tree_ID AND Node_ID=200218)
|
||||||
|
;
|
||||||
|
|
||||||
|
-- Oct 13, 2022, 7:31:15 PM CEST
|
||||||
|
UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=12,Updated=TO_TIMESTAMP('2022-10-13 19:31:15','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Tree_ID=10 AND Node_ID=200218
|
||||||
|
;
|
||||||
|
|
||||||
|
-- Oct 13, 2022, 7:31:15 PM CEST
|
||||||
|
UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=13,Updated=TO_TIMESTAMP('2022-10-13 19:31:15','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Tree_ID=10 AND Node_ID=289
|
||||||
|
;
|
||||||
|
|
||||||
|
-- Oct 13, 2022, 7:31:15 PM CEST
|
||||||
|
UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=14,Updated=TO_TIMESTAMP('2022-10-13 19:31:15','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Tree_ID=10 AND Node_ID=302
|
||||||
|
;
|
||||||
|
|
||||||
|
-- Oct 13, 2022, 7:31:15 PM CEST
|
||||||
|
UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=15,Updated=TO_TIMESTAMP('2022-10-13 19:31:15','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Tree_ID=10 AND Node_ID=200168
|
||||||
|
;
|
||||||
|
|
||||||
|
-- Oct 13, 2022, 7:31:15 PM CEST
|
||||||
|
UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=16,Updated=TO_TIMESTAMP('2022-10-13 19:31:15','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Tree_ID=10 AND Node_ID=200169
|
||||||
|
;
|
||||||
|
|
||||||
|
-- Oct 13, 2022, 7:31:15 PM CEST
|
||||||
|
UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=17,Updated=TO_TIMESTAMP('2022-10-13 19:31:15','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Tree_ID=10 AND Node_ID=303
|
||||||
|
;
|
||||||
|
|
||||||
|
-- Oct 13, 2022, 7:31:15 PM CEST
|
||||||
|
UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=18,Updated=TO_TIMESTAMP('2022-10-13 19:31:15','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Tree_ID=10 AND Node_ID=200047
|
||||||
|
;
|
||||||
|
|
||||||
|
-- Oct 13, 2022, 7:31:15 PM CEST
|
||||||
|
UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=19,Updated=TO_TIMESTAMP('2022-10-13 19:31:15','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Tree_ID=10 AND Node_ID=200048
|
||||||
|
;
|
||||||
|
|
||||||
|
-- Oct 13, 2022, 7:31:15 PM CEST
|
||||||
|
UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=20,Updated=TO_TIMESTAMP('2022-10-13 19:31:15','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Tree_ID=10 AND Node_ID=321
|
||||||
|
;
|
||||||
|
|
||||||
|
-- Oct 13, 2022, 7:31:15 PM CEST
|
||||||
|
UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=21,Updated=TO_TIMESTAMP('2022-10-13 19:31:15','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Tree_ID=10 AND Node_ID=461
|
||||||
|
;
|
||||||
|
|
||||||
|
-- Oct 13, 2022, 7:31:15 PM CEST
|
||||||
|
UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=22,Updated=TO_TIMESTAMP('2022-10-13 19:31:15','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Tree_ID=10 AND Node_ID=53193
|
||||||
|
;
|
||||||
|
|
||||||
|
-- Oct 13, 2022, 7:31:15 PM CEST
|
||||||
|
UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=23,Updated=TO_TIMESTAMP('2022-10-13 19:31:15','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Tree_ID=10 AND Node_ID=200161
|
||||||
|
;
|
||||||
|
|
||||||
|
-- Oct 13, 2022, 7:31:15 PM CEST
|
||||||
|
UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=24,Updated=TO_TIMESTAMP('2022-10-13 19:31:15','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Tree_ID=10 AND Node_ID=53322
|
||||||
|
;
|
||||||
|
|
||||||
|
-- Oct 13, 2022, 7:31:15 PM CEST
|
||||||
|
UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=25,Updated=TO_TIMESTAMP('2022-10-13 19:31:15','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Tree_ID=10 AND Node_ID=383
|
||||||
|
;
|
||||||
|
|
||||||
|
-- Oct 13, 2022, 7:31:15 PM CEST
|
||||||
|
UPDATE AD_TreeNodeMM SET Parent_ID=155, SeqNo=26,Updated=TO_TIMESTAMP('2022-10-13 19:31:15','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Tree_ID=10 AND Node_ID=200177
|
||||||
|
;
|
||||||
|
|
|
@ -44,7 +44,7 @@ public class MSysConfig extends X_AD_SysConfig
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
private static final long serialVersionUID = 9018760438155531804L;
|
private static final long serialVersionUID = -1225938049955333281L;
|
||||||
|
|
||||||
public static final String ADDRESS_VALIDATION = "ADDRESS_VALIDATION";
|
public static final String ADDRESS_VALIDATION = "ADDRESS_VALIDATION";
|
||||||
public static final String ALERT_SEND_ATTACHMENT_AS_XLS = "ALERT_SEND_ATTACHMENT_AS_XLS";
|
public static final String ALERT_SEND_ATTACHMENT_AS_XLS = "ALERT_SEND_ATTACHMENT_AS_XLS";
|
||||||
|
@ -103,6 +103,10 @@ public class MSysConfig extends X_AD_SysConfig
|
||||||
public static final String FEEDBACK_EMAIL_CC = "FEEDBACK_EMAIL_CC";
|
public static final String FEEDBACK_EMAIL_CC = "FEEDBACK_EMAIL_CC";
|
||||||
public static final String FEEDBACK_EMAIL_TO = "FEEDBACK_EMAIL_TO";
|
public static final String FEEDBACK_EMAIL_TO = "FEEDBACK_EMAIL_TO";
|
||||||
public static final String FORM_SQL_PROCESS_ALLOWED_KEYWORDS = "FORM_SQL_PROCESS_ALLOWED_KEYWORDS";
|
public static final String FORM_SQL_PROCESS_ALLOWED_KEYWORDS = "FORM_SQL_PROCESS_ALLOWED_KEYWORDS";
|
||||||
|
public static final String FORM_SQL_QUERY_ALLOWED_KEYWORDS = "FORM_SQL_QUERY_ALLOWED_KEYWORDS";
|
||||||
|
public static final String FORM_SQL_QUERY_LOG_ISSUE = "FORM_SQL_QUERY_LOG_ISSUE";
|
||||||
|
public static final String FORM_SQL_QUERY_MAX_RECORDS = "FORM_SQL_QUERY_MAX_RECORDS";
|
||||||
|
public static final String FORM_SQL_QUERY_TIMEOUT_IN_SECONDS = "FORM_SQL_QUERY_TIMEOUT_IN_SECONDS";
|
||||||
public static final String GRIDTABLE_LOAD_TIMEOUT_IN_SECONDS = "GRIDTABLE_LOAD_TIMEOUT_IN_SECONDS";
|
public static final String GRIDTABLE_LOAD_TIMEOUT_IN_SECONDS = "GRIDTABLE_LOAD_TIMEOUT_IN_SECONDS";
|
||||||
public static final String HTML_REPORT_MINIFY = "HTML_REPORT_MINIFY";
|
public static final String HTML_REPORT_MINIFY = "HTML_REPORT_MINIFY";
|
||||||
public static final String HTML_REPORT_THEME = "HTML_REPORT_THEME";
|
public static final String HTML_REPORT_THEME = "HTML_REPORT_THEME";
|
||||||
|
|
|
@ -67,6 +67,7 @@ public class SystemIDs
|
||||||
public final static int FORM_ADD_AUTHORIZATION = 200016;
|
public final static int FORM_ADD_AUTHORIZATION = 200016;
|
||||||
public final static int FORM_MFA_REGISTER = 200017;
|
public final static int FORM_MFA_REGISTER = 200017;
|
||||||
public final static int FORM_SQL_PROCESS = 111;
|
public final static int FORM_SQL_PROCESS = 111;
|
||||||
|
public final static int FORM_SQL_QUERY = 200018;
|
||||||
|
|
||||||
public final static int MENU_NOTICE = 233;
|
public final static int MENU_NOTICE = 233;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,335 @@
|
||||||
|
/***********************************************************************
|
||||||
|
* This file is part of iDempiere ERP Open Source *
|
||||||
|
* http://www.idempiere.org *
|
||||||
|
* *
|
||||||
|
* Copyright (C) Contributors *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or *
|
||||||
|
* modify it under the terms of the GNU General Public License *
|
||||||
|
* as published by the Free Software Foundation; either version 2 *
|
||||||
|
* of the License, or (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the Free Software *
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, *
|
||||||
|
* MA 02110-1301, USA. *
|
||||||
|
* *
|
||||||
|
* Contributors: *
|
||||||
|
* - Carlos Ruiz - globalqss - bxservice *
|
||||||
|
**********************************************************************/
|
||||||
|
|
||||||
|
package org.adempiere.webui.apps.form;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.ResultSetMetaData;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
import org.adempiere.exceptions.DBException;
|
||||||
|
import org.adempiere.webui.component.Button;
|
||||||
|
import org.adempiere.webui.component.Label;
|
||||||
|
import org.adempiere.webui.component.ListModelTable;
|
||||||
|
import org.adempiere.webui.component.Textbox;
|
||||||
|
import org.adempiere.webui.component.WListItemRenderer;
|
||||||
|
import org.adempiere.webui.component.WListbox;
|
||||||
|
import org.adempiere.webui.panel.ADForm;
|
||||||
|
import org.adempiere.webui.theme.ThemeManager;
|
||||||
|
import org.adempiere.webui.util.ZKUpdateUtil;
|
||||||
|
import org.compiere.model.MIssue;
|
||||||
|
import org.compiere.model.MSysConfig;
|
||||||
|
import org.compiere.model.SystemIDs;
|
||||||
|
import org.compiere.util.CLogger;
|
||||||
|
import org.compiere.util.DB;
|
||||||
|
import org.compiere.util.Env;
|
||||||
|
import org.compiere.util.Msg;
|
||||||
|
import org.compiere.util.Trx;
|
||||||
|
import org.zkoss.zk.ui.event.Event;
|
||||||
|
import org.zkoss.zk.ui.event.EventListener;
|
||||||
|
import org.zkoss.zk.ui.event.Events;
|
||||||
|
import org.zkoss.zul.Borderlayout;
|
||||||
|
import org.zkoss.zul.Center;
|
||||||
|
import org.zkoss.zul.Div;
|
||||||
|
import org.zkoss.zul.Frozen;
|
||||||
|
import org.zkoss.zul.North;
|
||||||
|
import org.zkoss.zul.South;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Custom Form to process SQL queries.
|
||||||
|
*
|
||||||
|
* The statement to be executed can be restricted using SysConfig
|
||||||
|
*/
|
||||||
|
public class WSQLQuery extends ADForm implements EventListener<Event>
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private static final long serialVersionUID = -6641250848300700313L;
|
||||||
|
|
||||||
|
/** Log. */
|
||||||
|
private static final CLogger log = CLogger.getCLogger(WSQLQuery.class);
|
||||||
|
|
||||||
|
/** Grid used to layout components. */
|
||||||
|
private Borderlayout layout = new Borderlayout();
|
||||||
|
/** SQL label. */
|
||||||
|
private Label m_lblSql = new Label("SQL");
|
||||||
|
/** SQL statement field. */
|
||||||
|
private Textbox m_txbSqlField = new Textbox();
|
||||||
|
/** Process button. */
|
||||||
|
private Button m_btnSql = createProcessButton();
|
||||||
|
/** Field to hold result of SQL statement execution. */
|
||||||
|
private Textbox m_txbResultField = new Textbox();
|
||||||
|
/** Grid to show the result data. */
|
||||||
|
private ListModelTable model = null;
|
||||||
|
private WListbox listbox = new WListbox();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* REGEX_REMOVE_COMMENTS
|
||||||
|
*/
|
||||||
|
private static final String REGEX_REMOVE_COMMENTS = "/\\*(?:.|[\\n\\r])*?\\*/";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* REGEX_REMOVE_QUOTED_STRINGS
|
||||||
|
*/
|
||||||
|
private static final String REGEX_REMOVE_QUOTED_STRINGS = "'(?:.|[\\n\\r])*?'";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* REGEX_REMOVE_LEADING_SPACES
|
||||||
|
*/
|
||||||
|
private static final String REGEX_REMOVE_LEADING_SPACES = "^\\s+";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default constructor.
|
||||||
|
*/
|
||||||
|
public WSQLQuery() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void initForm() {
|
||||||
|
North north = new North();
|
||||||
|
Center center = new Center();
|
||||||
|
South south = new South();
|
||||||
|
final int maxStatementLength = 10000;
|
||||||
|
final int noStatementRows = 3;
|
||||||
|
final int noResultRows = 2;
|
||||||
|
|
||||||
|
ZKUpdateUtil.setWidth(layout, "100%");
|
||||||
|
ZKUpdateUtil.setHeight(layout, "100%");
|
||||||
|
layout.setStyle("background-color: transparent; position: relative;");
|
||||||
|
|
||||||
|
Div div = new Div();
|
||||||
|
// create the top row of components
|
||||||
|
m_txbSqlField.setMultiline(true);
|
||||||
|
m_txbSqlField.setMaxlength(maxStatementLength);
|
||||||
|
m_txbSqlField.setRows(noStatementRows);
|
||||||
|
ZKUpdateUtil.setHflex(m_txbSqlField, "1");
|
||||||
|
m_txbSqlField.setReadonly(false);
|
||||||
|
|
||||||
|
m_btnSql.addEventListener(Events.ON_CLICK, this);
|
||||||
|
|
||||||
|
div.appendChild(m_lblSql);
|
||||||
|
div.appendChild(m_txbSqlField);
|
||||||
|
div.appendChild(m_btnSql);
|
||||||
|
north.appendChild(div);
|
||||||
|
layout.appendChild(north);
|
||||||
|
|
||||||
|
// create the bottom row of components
|
||||||
|
m_txbResultField.setRows(noResultRows);
|
||||||
|
ZKUpdateUtil.setHflex(m_txbResultField, "1");
|
||||||
|
m_txbResultField.setReadonly(true);
|
||||||
|
|
||||||
|
center.appendChild(listbox);
|
||||||
|
ZKUpdateUtil.setVflex(listbox, "1");
|
||||||
|
ZKUpdateUtil.setHflex(listbox, "1");
|
||||||
|
|
||||||
|
layout.appendChild(center);
|
||||||
|
|
||||||
|
south.appendChild(m_txbResultField);
|
||||||
|
layout.appendChild(south);
|
||||||
|
|
||||||
|
this.appendChild(layout);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create Process Button.
|
||||||
|
* @return button
|
||||||
|
*/
|
||||||
|
public static final Button createProcessButton() {
|
||||||
|
Button btnProcess = new Button();
|
||||||
|
if(ThemeManager.isUseFontIconForImage())
|
||||||
|
btnProcess.setIconSclass("z-icon-Process");
|
||||||
|
else
|
||||||
|
btnProcess.setImage(ThemeManager.getThemeResource("images/Process24.png"));
|
||||||
|
btnProcess.setName(Msg.getMsg(Env.getCtx(), "Process"));
|
||||||
|
|
||||||
|
return btnProcess;
|
||||||
|
} // createProcessButton
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process SQL Statements.
|
||||||
|
*
|
||||||
|
* @param sqlStatement a single SQL statement
|
||||||
|
* @param allowDML whether to allow DML statements
|
||||||
|
* @return a string summarizing the results
|
||||||
|
*/
|
||||||
|
public String processStatement (String sqlStatement) {
|
||||||
|
m_txbResultField.setText(null);
|
||||||
|
listbox.clear();
|
||||||
|
|
||||||
|
if (sqlStatement == null || sqlStatement.length() == 0)
|
||||||
|
return "";
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
char[] chars = sqlStatement.toCharArray();
|
||||||
|
for (int i = 0; i < chars.length; i++) {
|
||||||
|
char c = chars[i];
|
||||||
|
if (Character.isWhitespace(c))
|
||||||
|
sb.append(' ');
|
||||||
|
else
|
||||||
|
sb.append(c);
|
||||||
|
}
|
||||||
|
String sql = sb.toString().trim();
|
||||||
|
if (sql.length() == 0)
|
||||||
|
return "";
|
||||||
|
//
|
||||||
|
StringBuilder result = new StringBuilder();
|
||||||
|
String SQL = sql.toUpperCase();
|
||||||
|
String cleanSQL = SQL
|
||||||
|
.replaceAll(REGEX_REMOVE_COMMENTS, "")
|
||||||
|
.replaceAll(REGEX_REMOVE_QUOTED_STRINGS, "")
|
||||||
|
.replaceFirst(REGEX_REMOVE_LEADING_SPACES, "");
|
||||||
|
|
||||||
|
if (cleanSQL.contains(";")) {
|
||||||
|
result.append("ERROR: Multiple Commands Not Allowed");
|
||||||
|
return result.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
int timeout = MSysConfig.getIntValue(MSysConfig.FORM_SQL_QUERY_TIMEOUT_IN_SECONDS, 120);
|
||||||
|
int maxRecords = MSysConfig.getIntValue(MSysConfig.FORM_SQL_QUERY_MAX_RECORDS, 500);
|
||||||
|
|
||||||
|
String[] allowedKeywords = MSysConfig.getValue(MSysConfig.FORM_SQL_QUERY_ALLOWED_KEYWORDS, "SELECT ,WITH ,SHOW ").split(",");
|
||||||
|
boolean isError = true;
|
||||||
|
for (int i = 0; i < allowedKeywords.length; i++) {
|
||||||
|
if (cleanSQL.startsWith(allowedKeywords[i])) {
|
||||||
|
isError = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isError) {
|
||||||
|
result.append("ERROR: Not Allowed Command");
|
||||||
|
return result.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> header = new ArrayList<String>();
|
||||||
|
header.add("#");
|
||||||
|
model = new ListModelTable();
|
||||||
|
Frozen frozen = new Frozen();
|
||||||
|
frozen.setColumns(1);
|
||||||
|
listbox.appendChild(frozen);
|
||||||
|
|
||||||
|
Trx trx = null;
|
||||||
|
PreparedStatement pstmt = null;
|
||||||
|
ResultSet rs = null;
|
||||||
|
try {
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
|
|
||||||
|
String trxName = Trx.createTrxName("WSQLQuery");
|
||||||
|
trx = Trx.get(trxName, false);
|
||||||
|
trx.setDisplayName(getClass().getName()+"_processStatement");
|
||||||
|
trx.getConnection().setReadOnly(true);
|
||||||
|
|
||||||
|
pstmt = DB.prepareNormalReadReplicaStatement(sql, trxName);
|
||||||
|
pstmt.setQueryTimeout(timeout);
|
||||||
|
rs = pstmt.executeQuery();
|
||||||
|
|
||||||
|
ResultSetMetaData meta = rs.getMetaData();
|
||||||
|
int count = 0;
|
||||||
|
for (int col = 1; col <= meta.getColumnCount(); col++) {
|
||||||
|
String columnName = meta.getColumnLabel(col);
|
||||||
|
header.add(columnName);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (rs.next ()) {
|
||||||
|
if (count >= maxRecords) {
|
||||||
|
result.append("Maximum of " + maxRecords + " records reached. ");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
List<Object> row = new ArrayList<Object>();
|
||||||
|
row.add(++count);
|
||||||
|
for (int col = 1; col <= meta.getColumnCount(); col++) {
|
||||||
|
String colName = header.get(col).toLowerCase();
|
||||||
|
if (rs.getObject(col) instanceof BigDecimal
|
||||||
|
&& (colName.endsWith("_id") || colName.equals("createdby") || colName.equals("updatedby")))
|
||||||
|
row.add(rs.getInt(col));
|
||||||
|
else
|
||||||
|
row.add(rs.getObject(col));
|
||||||
|
} // for all columns
|
||||||
|
model.add(row);
|
||||||
|
}
|
||||||
|
long end = System.currentTimeMillis();
|
||||||
|
BigDecimal durationSeconds = BigDecimal.valueOf(end).subtract(BigDecimal.valueOf(start)).divide(BigDecimal.valueOf(1000.0));
|
||||||
|
result.append("Count = ").append(count);
|
||||||
|
if (MSysConfig.getBooleanValue(MSysConfig.FORM_SQL_QUERY_LOG_ISSUE, true)) {
|
||||||
|
MIssue issue = new MIssue(Env.getCtx(), 0, null);
|
||||||
|
issue.setIssueSummary("SQL executed on SQL Query form");
|
||||||
|
issue.setStackTrace(sql);
|
||||||
|
issue.setResponseText(result.toString());
|
||||||
|
issue.setIssueSource(MIssue.ISSUESOURCE_Form);
|
||||||
|
issue.setUserName(Env.getContext(Env.getCtx(), Env.AD_USER_NAME));
|
||||||
|
issue.setAD_Form_ID(SystemIDs.FORM_SQL_QUERY);
|
||||||
|
issue.setProcessed(true);
|
||||||
|
issue.setComments("Duration : " + durationSeconds + " seconds");
|
||||||
|
issue.saveEx();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show the result in WListbox
|
||||||
|
WListItemRenderer renderer = new WListItemRenderer(header);
|
||||||
|
model.setNoColumns(header.size());
|
||||||
|
listbox.setModel(model);
|
||||||
|
listbox.setItemRenderer(renderer);
|
||||||
|
listbox.initialiseHeader();
|
||||||
|
listbox.setSizedByContent(true);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (trx != null) {
|
||||||
|
trx.rollback();
|
||||||
|
}
|
||||||
|
if (DBException.isTimeout(e)) {
|
||||||
|
result.append("Maximum of " + timeout + " seconds reached, query cancelled.");
|
||||||
|
} else {
|
||||||
|
e.printStackTrace();
|
||||||
|
String exception = e.toString();
|
||||||
|
log.log(Level.SEVERE, "process statement: " + sql + " - " + exception);
|
||||||
|
result.append("Exception => ").append(exception);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
DB.close(rs, pstmt);
|
||||||
|
rs = null; pstmt = null;
|
||||||
|
if (trx != null) {
|
||||||
|
trx.close();
|
||||||
|
trx = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process the events for this form
|
||||||
|
* @param event
|
||||||
|
*/
|
||||||
|
public void onEvent(Event event) throws Exception {
|
||||||
|
if (event.getTarget() == m_btnSql)
|
||||||
|
m_txbResultField.setText(processStatement(m_txbSqlField.getText()));
|
||||||
|
super.onEvent(event);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue