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 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_TO = "FEEDBACK_EMAIL_TO";
|
||||
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 HTML_REPORT_MINIFY = "HTML_REPORT_MINIFY";
|
||||
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_MFA_REGISTER = 200017;
|
||||
public final static int FORM_SQL_PROCESS = 111;
|
||||
public final static int FORM_SQL_QUERY = 200018;
|
||||
|
||||
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