xref: /AOO41X/main/qadevOOo/runner/stats/SQLExecution.java (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1*cdf0e10cSrcweir /*************************************************************************
2*cdf0e10cSrcweir  *
3*cdf0e10cSrcweir  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir  *
5*cdf0e10cSrcweir  * Copyright 2000, 2010 Oracle and/or its affiliates.
6*cdf0e10cSrcweir  *
7*cdf0e10cSrcweir  * OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir  *
9*cdf0e10cSrcweir  * This file is part of OpenOffice.org.
10*cdf0e10cSrcweir  *
11*cdf0e10cSrcweir  * OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir  * it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir  * only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir  *
15*cdf0e10cSrcweir  * OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir  * GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir  * (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir  *
21*cdf0e10cSrcweir  * You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir  * version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir  * <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir  * for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir  *
26*cdf0e10cSrcweir  ************************************************************************/
27*cdf0e10cSrcweir package stats;
28*cdf0e10cSrcweir 
29*cdf0e10cSrcweir import java.sql.Connection;
30*cdf0e10cSrcweir import java.sql.DriverManager;
31*cdf0e10cSrcweir import java.sql.ResultSet;
32*cdf0e10cSrcweir import java.sql.ResultSetMetaData;
33*cdf0e10cSrcweir import java.sql.Statement;
34*cdf0e10cSrcweir import java.util.Enumeration;
35*cdf0e10cSrcweir import java.util.Hashtable;
36*cdf0e10cSrcweir import java.util.StringTokenizer;
37*cdf0e10cSrcweir import java.util.Vector;
38*cdf0e10cSrcweir 
39*cdf0e10cSrcweir /**
40*cdf0e10cSrcweir  *
41*cdf0e10cSrcweir  */
42*cdf0e10cSrcweir public class SQLExecution {
43*cdf0e10cSrcweir 
44*cdf0e10cSrcweir     protected Connection mConnection = null;
45*cdf0e10cSrcweir     protected Statement mStatement = null;
46*cdf0e10cSrcweir     protected String mJdbcClass = null;
47*cdf0e10cSrcweir     protected String mDbURL = null;
48*cdf0e10cSrcweir     protected String mUser = null;
49*cdf0e10cSrcweir     protected String mPassword = null;
50*cdf0e10cSrcweir     protected boolean m_bConnectionOpen = false;
51*cdf0e10cSrcweir     protected boolean m_bDebug = false;
52*cdf0e10cSrcweir 
53*cdf0e10cSrcweir 
54*cdf0e10cSrcweir     /** Creates a new instance of SQLExecution
55*cdf0e10cSrcweir      * @param jdbcClass The jdbc class for the connection.
56*cdf0e10cSrcweir      * @param dbUrl The url of the database.
57*cdf0e10cSrcweir      * @param user The user for connecting the database.
58*cdf0e10cSrcweir      * @param password The password of throws user.
59*cdf0e10cSrcweir      */
60*cdf0e10cSrcweir     public SQLExecution(String jdbcClass, String dbUrl, String user, String password) {
61*cdf0e10cSrcweir         mJdbcClass = jdbcClass;
62*cdf0e10cSrcweir         mUser = user;
63*cdf0e10cSrcweir         mPassword = password;
64*cdf0e10cSrcweir         mDbURL = dbUrl;
65*cdf0e10cSrcweir     }
66*cdf0e10cSrcweir 
67*cdf0e10cSrcweir     /** Creates a new instance of SQLExecution with additional debug output.
68*cdf0e10cSrcweir      * @param jdbcClass The jdbc class for the connection.
69*cdf0e10cSrcweir      * @param dbUrl The url of the database.
70*cdf0e10cSrcweir      * @param user The user for connecting the database.
71*cdf0e10cSrcweir      * @param password The password of throws user.
72*cdf0e10cSrcweir      * @param debug Write debug information, if true.
73*cdf0e10cSrcweir      */
74*cdf0e10cSrcweir     public SQLExecution(String jdbcClass, String dbUrl, String user, String password, boolean debug) {
75*cdf0e10cSrcweir         mJdbcClass = jdbcClass;
76*cdf0e10cSrcweir         mUser = user;
77*cdf0e10cSrcweir         mPassword = password;
78*cdf0e10cSrcweir         mDbURL = dbUrl;
79*cdf0e10cSrcweir         m_bDebug = debug;
80*cdf0e10cSrcweir     }
81*cdf0e10cSrcweir 
82*cdf0e10cSrcweir     /**
83*cdf0e10cSrcweir      * Open a connection to the DataBase
84*cdf0e10cSrcweir      * @return True, if no error occured.
85*cdf0e10cSrcweir      */
86*cdf0e10cSrcweir     public boolean openConnection() {
87*cdf0e10cSrcweir         if(m_bConnectionOpen) return true;
88*cdf0e10cSrcweir         try {
89*cdf0e10cSrcweir             Class.forName(mJdbcClass);
90*cdf0e10cSrcweir         } catch (ClassNotFoundException e) {
91*cdf0e10cSrcweir             System.err.println("Couldn't find jdbc driver : " + e.getMessage());
92*cdf0e10cSrcweir             return false;
93*cdf0e10cSrcweir         }
94*cdf0e10cSrcweir 
95*cdf0e10cSrcweir         try {
96*cdf0e10cSrcweir             // establish database connection
97*cdf0e10cSrcweir             mConnection = DriverManager.getConnection(
98*cdf0e10cSrcweir                                                 mDbURL, mUser, mPassword);
99*cdf0e10cSrcweir             mStatement = mConnection.createStatement();
100*cdf0e10cSrcweir         }
101*cdf0e10cSrcweir         catch(java.sql.SQLException e) {
102*cdf0e10cSrcweir             System.err.println("Couldn't establish a connection: " + e.getMessage());
103*cdf0e10cSrcweir             return false;
104*cdf0e10cSrcweir         }
105*cdf0e10cSrcweir         m_bConnectionOpen = true;
106*cdf0e10cSrcweir         return true;
107*cdf0e10cSrcweir     }
108*cdf0e10cSrcweir 
109*cdf0e10cSrcweir     /**
110*cdf0e10cSrcweir      * Close the connection to the DataBase
111*cdf0e10cSrcweir      * @return True, if no error occured.
112*cdf0e10cSrcweir      */
113*cdf0e10cSrcweir     public boolean closeConnection() {
114*cdf0e10cSrcweir         if (!m_bConnectionOpen) return true;
115*cdf0e10cSrcweir         try {
116*cdf0e10cSrcweir             // close database connection
117*cdf0e10cSrcweir             mStatement.close();
118*cdf0e10cSrcweir             mConnection.close();
119*cdf0e10cSrcweir         }
120*cdf0e10cSrcweir         catch(java.sql.SQLException e) {
121*cdf0e10cSrcweir             System.err.println("Couldn't close the connection: " + e.getMessage());
122*cdf0e10cSrcweir             return false;
123*cdf0e10cSrcweir         }
124*cdf0e10cSrcweir         m_bConnectionOpen = false;
125*cdf0e10cSrcweir         return true;
126*cdf0e10cSrcweir     }
127*cdf0e10cSrcweir 
128*cdf0e10cSrcweir     /**
129*cdf0e10cSrcweir      * Execute an sql command.
130*cdf0e10cSrcweir      * @param command The command to execute.
131*cdf0e10cSrcweir      * @param sqlInput Input values for the command.
132*cdf0e10cSrcweir      * @param sqlOutput The results of the command are put in this Hashtable.
133*cdf0e10cSrcweir      * @return True, if no error occured.
134*cdf0e10cSrcweir      */
135*cdf0e10cSrcweir     public boolean executeSQLCommand(String command, Hashtable sqlInput, Hashtable sqlOutput)
136*cdf0e10cSrcweir                                         throws IllegalArgumentException {
137*cdf0e10cSrcweir         return executeSQLCommand(command, sqlInput, sqlOutput, false);
138*cdf0e10cSrcweir     }
139*cdf0e10cSrcweir 
140*cdf0e10cSrcweir     /**
141*cdf0e10cSrcweir      * Execute an sql command.
142*cdf0e10cSrcweir      * @param command The command to execute.
143*cdf0e10cSrcweir      * @param sqlInput Input values for the command.
144*cdf0e10cSrcweir      * @param sqlOutput The results of the command are put in this Hashtable.
145*cdf0e10cSrcweir      * @param mergeOutputIntoInput The output of the result is put into the
146*cdf0e10cSrcweir      * sqlInput Hashtable.
147*cdf0e10cSrcweir      * @return True, if no error occured.
148*cdf0e10cSrcweir      */
149*cdf0e10cSrcweir     public boolean executeSQLCommand(String command, Hashtable sqlInput, Hashtable sqlOutput, boolean mergeOutputIntoInput)
150*cdf0e10cSrcweir                                         throws IllegalArgumentException {
151*cdf0e10cSrcweir         if (sqlOutput == null) {
152*cdf0e10cSrcweir             sqlOutput = new Hashtable();
153*cdf0e10cSrcweir             // this has to be true, so the user of this method gets a return
154*cdf0e10cSrcweir             mergeOutputIntoInput = true;
155*cdf0e10cSrcweir             if (sqlInput == null) {
156*cdf0e10cSrcweir                 System.out.println("sqlInput and sqlOutput are null: cannot return the results of the sql command.");
157*cdf0e10cSrcweir                 return false;
158*cdf0e10cSrcweir             }
159*cdf0e10cSrcweir         }
160*cdf0e10cSrcweir         Vector sqlCommand = new Vector();
161*cdf0e10cSrcweir         sqlCommand.add("");
162*cdf0e10cSrcweir         boolean update = false;
163*cdf0e10cSrcweir         // synchronize all "$varname" occurences in the command string with
164*cdf0e10cSrcweir         // values from input
165*cdf0e10cSrcweir         StringTokenizer token = new StringTokenizer(command, " ");
166*cdf0e10cSrcweir         while (token.hasMoreTokens()) {
167*cdf0e10cSrcweir             String originalKey = token.nextToken();
168*cdf0e10cSrcweir             // search for keys, beginning with "$"
169*cdf0e10cSrcweir             int index = originalKey.indexOf('$');
170*cdf0e10cSrcweir             if (index != -1) {
171*cdf0e10cSrcweir                 // found key
172*cdf0e10cSrcweir                 String pre = "";
173*cdf0e10cSrcweir                 pre = originalKey.substring(0,index);
174*cdf0e10cSrcweir                 // generate key: remove "$"
175*cdf0e10cSrcweir                 String key = originalKey.substring(index+1);
176*cdf0e10cSrcweir                 String post = "";
177*cdf0e10cSrcweir                 // remove any endings the key might have
178*cdf0e10cSrcweir                 while (key.endsWith(",") || key.endsWith("\'") ||
179*cdf0e10cSrcweir                        key.endsWith(";") || key.endsWith(")") ||
180*cdf0e10cSrcweir                        key.endsWith("\"")) {
181*cdf0e10cSrcweir                     post = key.substring(key.length()-1) + post;
182*cdf0e10cSrcweir                     key = key.substring(0, key.length()-1);
183*cdf0e10cSrcweir                 }
184*cdf0e10cSrcweir                 // look for key in the Hashtable
185*cdf0e10cSrcweir                 if (sqlInput.containsKey(key)) {
186*cdf0e10cSrcweir                     // is there a value for the key?
187*cdf0e10cSrcweir                     Object in = sqlInput.get(key);
188*cdf0e10cSrcweir                     if (in instanceof String[]) {
189*cdf0e10cSrcweir                         // value is a String[]
190*cdf0e10cSrcweir                         String[]vals = (String[])in;
191*cdf0e10cSrcweir                         if (vals.length != sqlCommand.size() && sqlCommand.size() > 1) {
192*cdf0e10cSrcweir                             // size of this array and previous array(s) does not match
193*cdf0e10cSrcweir                             throw new IllegalArgumentException("The key '" + key + "' in command \n'"
194*cdf0e10cSrcweir                                     + command + "'\n has not the same value count as the keys before.");
195*cdf0e10cSrcweir                         }
196*cdf0e10cSrcweir                         // build up the commands
197*cdf0e10cSrcweir                         boolean addNewVals = (sqlCommand.size() == 1);
198*cdf0e10cSrcweir                         for (int i=0; i<vals.length; i++) {
199*cdf0e10cSrcweir                             String value = checkForQuotationMarks(vals[i]);
200*cdf0e10cSrcweir                             // add the values
201*cdf0e10cSrcweir                             if (addNewVals && i!=0) {
202*cdf0e10cSrcweir                                 // all values until now were of type String, not String[], so now new values have to be added.
203*cdf0e10cSrcweir                                 sqlCommand.add(i, (String)sqlCommand.get(0) + " " + pre + value + post);
204*cdf0e10cSrcweir                             }
205*cdf0e10cSrcweir                             else {
206*cdf0e10cSrcweir                                 // we already have vals.length commands (or are at the first command), so just add.
207*cdf0e10cSrcweir                                 sqlCommand.set(i, (String)sqlCommand.get(i) + " " + pre + value + post);
208*cdf0e10cSrcweir                             }
209*cdf0e10cSrcweir                         }
210*cdf0e10cSrcweir                     }
211*cdf0e10cSrcweir                     else {
212*cdf0e10cSrcweir                         // value is a String: no other possibility
213*cdf0e10cSrcweir                         String value = checkForQuotationMarks((String)sqlInput.get(key));
214*cdf0e10cSrcweir                         for (int i=0; i<sqlCommand.size(); i++) {
215*cdf0e10cSrcweir                             sqlCommand.set(i, (String)sqlCommand.get(i) + " " + pre + value + post);
216*cdf0e10cSrcweir                         }
217*cdf0e10cSrcweir                     }
218*cdf0e10cSrcweir                 }
219*cdf0e10cSrcweir                 else {
220*cdf0e10cSrcweir                     // no input value found
221*cdf0e10cSrcweir                     throw new IllegalArgumentException ("The key '" + key + "' in command \n'"
222*cdf0e10cSrcweir                     + command + "'\n does not exist in the input values.");
223*cdf0e10cSrcweir                 }
224*cdf0e10cSrcweir             }
225*cdf0e10cSrcweir             else {
226*cdf0e10cSrcweir                 // token is not a key, just add it
227*cdf0e10cSrcweir                 for (int i=0; i<sqlCommand.size(); i++)
228*cdf0e10cSrcweir                     sqlCommand.set(i, (String)sqlCommand.get(i) + " " + originalKey);
229*cdf0e10cSrcweir                 if (originalKey.equalsIgnoreCase("update") ||
230*cdf0e10cSrcweir                                     originalKey.equalsIgnoreCase("delete") ||
231*cdf0e10cSrcweir                                     originalKey.equalsIgnoreCase("insert")) {
232*cdf0e10cSrcweir                     update = true;
233*cdf0e10cSrcweir                 }
234*cdf0e10cSrcweir 
235*cdf0e10cSrcweir             }
236*cdf0e10cSrcweir         }
237*cdf0e10cSrcweir         for (int i=0;i<sqlCommand.size(); i++) {
238*cdf0e10cSrcweir             execute((String)sqlCommand.get(i), sqlOutput, update);
239*cdf0e10cSrcweir             // merge output with input
240*cdf0e10cSrcweir             if (!update && mergeOutputIntoInput) {
241*cdf0e10cSrcweir                 Enumeration keys = sqlOutput.keys();
242*cdf0e10cSrcweir                 while(keys.hasMoreElements()) {
243*cdf0e10cSrcweir                     String key = (String)keys.nextElement();
244*cdf0e10cSrcweir                     String[]val = (String[])sqlOutput.get(key);
245*cdf0e10cSrcweir                     if (val != null && val.length != 0) {
246*cdf0e10cSrcweir                         if (val.length == 1)
247*cdf0e10cSrcweir                             sqlInput.put(key, val[0]);
248*cdf0e10cSrcweir                         else
249*cdf0e10cSrcweir                             sqlInput.put(key, val);
250*cdf0e10cSrcweir                     }
251*cdf0e10cSrcweir                 }
252*cdf0e10cSrcweir             }
253*cdf0e10cSrcweir         }
254*cdf0e10cSrcweir         if (!update && sqlOutput == null)
255*cdf0e10cSrcweir             return false;
256*cdf0e10cSrcweir         return true;
257*cdf0e10cSrcweir     }
258*cdf0e10cSrcweir 
259*cdf0e10cSrcweir     /**
260*cdf0e10cSrcweir      * Execute any SQL command.
261*cdf0e10cSrcweir      * @param command The command.
262*cdf0e10cSrcweir      * @param update If true, it is a update/alter command instead of an select
263*cdf0e10cSrcweir      *          command
264*cdf0e10cSrcweir      * @return A Hashtable with the result.
265*cdf0e10cSrcweir      */
266*cdf0e10cSrcweir     private void execute(String command, Hashtable output, boolean update) {
267*cdf0e10cSrcweir         if (m_bDebug)
268*cdf0e10cSrcweir             System.out.println("Debug - SQLExecution - execute Command: " + command);
269*cdf0e10cSrcweir         try {
270*cdf0e10cSrcweir             if (update) {
271*cdf0e10cSrcweir                 // make an update
272*cdf0e10cSrcweir                 mStatement.executeUpdate(command);
273*cdf0e10cSrcweir             }
274*cdf0e10cSrcweir             else {
275*cdf0e10cSrcweir                 // make a select: collect the result
276*cdf0e10cSrcweir                 ResultSet sqlResult = mStatement.executeQuery(command);
277*cdf0e10cSrcweir                 ResultSetMetaData sqlRSMeta = sqlResult.getMetaData();
278*cdf0e10cSrcweir                 int columnCount = sqlRSMeta.getColumnCount();
279*cdf0e10cSrcweir                 String[] columnNames = new String[columnCount];
280*cdf0e10cSrcweir                 int countRows = 0;
281*cdf0e10cSrcweir                 boolean goThroughRowsTheFirstTime = true;
282*cdf0e10cSrcweir                 for(int i=1; i<=columnCount; i++) {
283*cdf0e10cSrcweir                     columnNames[i-1] = sqlRSMeta.getColumnName(i);
284*cdf0e10cSrcweir                     // initialize output
285*cdf0e10cSrcweir                     Vector v = new Vector();
286*cdf0e10cSrcweir 
287*cdf0e10cSrcweir                     sqlResult.beforeFirst();
288*cdf0e10cSrcweir                     while (sqlResult.next()) {
289*cdf0e10cSrcweir                         String value = sqlResult.getString(i);
290*cdf0e10cSrcweir                         v.add(value);
291*cdf0e10cSrcweir                         // the first time: count rows
292*cdf0e10cSrcweir                         if (goThroughRowsTheFirstTime)
293*cdf0e10cSrcweir                             countRows++;
294*cdf0e10cSrcweir                     }
295*cdf0e10cSrcweir                     // rows are counted
296*cdf0e10cSrcweir                     if (goThroughRowsTheFirstTime)
297*cdf0e10cSrcweir                         goThroughRowsTheFirstTime = false;
298*cdf0e10cSrcweir 
299*cdf0e10cSrcweir                     // put result in output Hashtable
300*cdf0e10cSrcweir                     String[]s = new String[countRows];
301*cdf0e10cSrcweir                     s = (String[])v.toArray(s);
302*cdf0e10cSrcweir                     output.put(columnNames[i-1], s);
303*cdf0e10cSrcweir                     if (m_bDebug) {
304*cdf0e10cSrcweir                         if (i == 1) {
305*cdf0e10cSrcweir                             System.out.print("Debug - SQLExecution - Command returns: ");
306*cdf0e10cSrcweir                             System.out.print("row: " + columnNames[i-1] + "   vals: ");
307*cdf0e10cSrcweir                         }
308*cdf0e10cSrcweir                         for (int j=0; j<s.length; j++)
309*cdf0e10cSrcweir                             System.out.print(s[j] + " ");
310*cdf0e10cSrcweir                         if (i == columnCount - 1)
311*cdf0e10cSrcweir                             System.out.println();
312*cdf0e10cSrcweir                     }
313*cdf0e10cSrcweir                 }
314*cdf0e10cSrcweir             }
315*cdf0e10cSrcweir         }
316*cdf0e10cSrcweir         catch (java.sql.SQLException e) {
317*cdf0e10cSrcweir             e.printStackTrace();
318*cdf0e10cSrcweir         }
319*cdf0e10cSrcweir     }
320*cdf0e10cSrcweir 
321*cdf0e10cSrcweir     /**
322*cdf0e10cSrcweir      * Replace <"> with <''> in the value Strings, or the command will fail.
323*cdf0e10cSrcweir      * @param checkString The String that is checked: a part of the command
324*cdf0e10cSrcweir      * @return The String, cleared of all quotation marks.
325*cdf0e10cSrcweir      */
326*cdf0e10cSrcweir     private String checkForQuotationMarks(String checkString) {
327*cdf0e10cSrcweir         String returnString = checkString;
328*cdf0e10cSrcweir         int quotIndex = 0;
329*cdf0e10cSrcweir         while ((quotIndex = returnString.indexOf('\"')) != -1) {
330*cdf0e10cSrcweir             String firstHalf = returnString.substring(0, quotIndex);
331*cdf0e10cSrcweir             String secondHalf = returnString.substring(quotIndex+1);
332*cdf0e10cSrcweir             returnString = firstHalf + "\'\'" + secondHalf;
333*cdf0e10cSrcweir         }
334*cdf0e10cSrcweir         return returnString;
335*cdf0e10cSrcweir     }
336*cdf0e10cSrcweir 
337*cdf0e10cSrcweir }
338