2 * This file is part of the LibreOffice project.
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 * This file incorporates work covered by the following license notice:
10 * Licensed to the Apache Software Foundation (ASF) under one or more
11 * contributor license agreements. See the NOTICE file distributed
12 * with this work for additional information regarding copyright
13 * ownership. The ASF licenses this file to you under the Apache
14 * License, Version 2.0 (the "License"); you may not use this file
15 * except in compliance with the License. You may obtain a copy of
16 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 import java
.sql
.Connection
;
21 import java
.sql
.DriverManager
;
22 import java
.sql
.ResultSet
;
23 import java
.sql
.ResultSetMetaData
;
24 import java
.sql
.Statement
;
25 import java
.util
.ArrayList
;
26 import java
.util
.HashMap
;
27 import java
.util
.Iterator
;
28 import java
.util
.StringTokenizer
;
33 public class SQLExecution
{
35 protected Connection mConnection
= null;
36 protected Statement mStatement
= null;
37 protected String mJdbcClass
= null;
38 protected String mDbURL
= null;
39 protected String mUser
= null;
40 protected String mPassword
= null;
41 protected boolean m_bConnectionOpen
= false;
42 protected boolean m_bDebug
= false;
45 /** Creates a new instance of SQLExecution
46 * @param jdbcClass The jdbc class for the connection.
47 * @param dbUrl The url of the database.
48 * @param user The user for connecting the database.
49 * @param password The password of throws user.
51 public SQLExecution(String jdbcClass
, String dbUrl
, String user
, String password
) {
52 mJdbcClass
= jdbcClass
;
58 /** Creates a new instance of SQLExecution with additional debug output.
59 * @param jdbcClass The jdbc class for the connection.
60 * @param dbUrl The url of the database.
61 * @param user The user for connecting the database.
62 * @param password The password of throws user.
63 * @param debug Write debug information, if true.
65 public SQLExecution(String jdbcClass
, String dbUrl
, String user
, String password
, boolean debug
) {
66 mJdbcClass
= jdbcClass
;
74 * Open a connection to the DataBase
75 * @return True, if no error occurred.
77 public boolean openConnection() {
78 if(m_bConnectionOpen
) return true;
80 Class
.forName(mJdbcClass
);
81 } catch (ClassNotFoundException e
) {
82 System
.err
.println("Couldn't find jdbc driver : " + e
.getMessage());
87 // establish database connection
88 mConnection
= DriverManager
.getConnection(
89 mDbURL
, mUser
, mPassword
);
90 mStatement
= mConnection
.createStatement();
92 catch(java
.sql
.SQLException e
) {
93 System
.err
.println("Couldn't establish a connection: " + e
.getMessage());
96 m_bConnectionOpen
= true;
101 * Close the connection to the DataBase
102 * @return True, if no error occurred.
104 public boolean closeConnection() {
105 if (!m_bConnectionOpen
) return true;
107 // close database connection
111 catch(java
.sql
.SQLException e
) {
112 System
.err
.println("Couldn't close the connection: " + e
.getMessage());
115 m_bConnectionOpen
= false;
120 * Execute an sql command.
121 * @param command The command to execute.
122 * @param sqlInput Input values for the command.
123 * @param sqlOutput The results of the command are put in this HashMap.
124 * @return True, if no error occurred.
126 public boolean executeSQLCommand(String command
, HashMap
<String
,Object
> sqlInput
, HashMap
<String
, String
[]> sqlOutput
)
127 throws IllegalArgumentException
{
128 return executeSQLCommand(command
, sqlInput
, sqlOutput
, false);
132 * Execute an sql command.
133 * @param command The command to execute.
134 * @param sqlInput Input values for the command.
135 * @param sqlOutput The results of the command are put in this HashMap.
136 * @param mergeOutputIntoInput The output of the result is put into the
138 * @return True, if no error occurred.
140 public boolean executeSQLCommand(String command
, HashMap
<String
,Object
> sqlInput
, HashMap
<String
, String
[]> sqlOutput
, boolean mergeOutputIntoInput
)
141 throws IllegalArgumentException
{
142 if (sqlOutput
== null) {
143 sqlOutput
= new HashMap
<String
, String
[]>();
144 // this has to be true, so the user of this method gets a return
145 mergeOutputIntoInput
= true;
146 if (sqlInput
== null) {
147 System
.out
.println("sqlInput and sqlOutput are null: cannot return the results of the sql command.");
151 ArrayList
<String
> sqlCommand
= new ArrayList
<String
>();
153 boolean update
= false;
154 // synchronize all "$varname" occurrences in the command string with
156 StringTokenizer token
= new StringTokenizer(command
, " ");
157 while (token
.hasMoreTokens()) {
158 String originalKey
= token
.nextToken();
159 // search for keys, beginning with "$"
160 int index
= originalKey
.indexOf('$');
164 pre
= originalKey
.substring(0,index
);
165 // generate key: remove "$"
166 String key
= originalKey
.substring(index
+1);
168 // remove any endings the key might have
169 while (key
.endsWith(",") || key
.endsWith("\'") ||
170 key
.endsWith(";") || key
.endsWith(")") ||
171 key
.endsWith("\"")) {
172 post
= key
.substring(key
.length()-1) + post
;
173 key
= key
.substring(0, key
.length()-1);
175 // look for key in the Hashtable
176 if (sqlInput
.containsKey(key
)) {
177 // is there a value for the key?
178 Object in
= sqlInput
.get(key
);
179 if (in
instanceof String
[]) {
180 // value is a String[]
181 String
[]vals
= (String
[])in
;
182 if (vals
.length
!= sqlCommand
.size() && sqlCommand
.size() > 1) {
183 // size of this array and previous array(s) does not match
184 throw new IllegalArgumentException("The key '" + key
+ "' in command \n'"
185 + command
+ "'\n has not the same value count as the keys before.");
187 // build up the commands
188 boolean addNewVals
= (sqlCommand
.size() == 1);
189 for (int i
=0; i
<vals
.length
; i
++) {
190 String value
= checkForQuotationMarks(vals
[i
]);
192 if (addNewVals
&& i
!=0) {
193 // all values until now were of type String, not String[], so now new values have to be added.
194 sqlCommand
.add(i
, sqlCommand
.get(0) + " " + pre
+ value
+ post
);
197 // we already have vals.length commands (or are at the first command), so just add.
198 sqlCommand
.set(i
, sqlCommand
.get(i
) + " " + pre
+ value
+ post
);
203 // value is a String: no other possibility
204 String value
= checkForQuotationMarks((String
)sqlInput
.get(key
));
205 for (int i
=0; i
<sqlCommand
.size(); i
++) {
206 sqlCommand
.set(i
, sqlCommand
.get(i
) + " " + pre
+ value
+ post
);
211 // no input value found
212 throw new IllegalArgumentException ("The key '" + key
+ "' in command \n'"
213 + command
+ "'\n does not exist in the input values.");
217 // token is not a key, just add it
218 for (int i
=0; i
<sqlCommand
.size(); i
++)
219 sqlCommand
.set(i
, sqlCommand
.get(i
) + " " + originalKey
);
220 if (originalKey
.equalsIgnoreCase("update") ||
221 originalKey
.equalsIgnoreCase("delete") ||
222 originalKey
.equalsIgnoreCase("insert")) {
228 for (int i
=0;i
<sqlCommand
.size(); i
++) {
229 execute(sqlCommand
.get(i
), sqlOutput
, update
);
230 // merge output with input
231 if (!update
&& mergeOutputIntoInput
) {
232 Iterator
<String
> keys
= sqlOutput
.keySet().iterator();
233 while(keys
.hasNext()) {
234 String key
= keys
.next();
235 String
[]val
= sqlOutput
.get(key
);
236 if (val
!= null && val
.length
!= 0) {
238 sqlInput
.put(key
, val
[0]);
240 sqlInput
.put(key
, val
);
245 if (!update
&& sqlOutput
== null)
251 * Execute any SQL command.
252 * @param command The command.
253 * @param update If true, it is a update/alter command instead of an select
255 * @param output A HashMap with the result.
257 private void execute(String command
, HashMap
<String
, String
[]> output
, boolean update
) {
259 System
.out
.println("Debug - SQLExecution - execute Command: " + command
);
263 mStatement
.executeUpdate(command
);
266 // make a select: collect the result
267 ResultSet sqlResult
= mStatement
.executeQuery(command
);
268 ResultSetMetaData sqlRSMeta
= sqlResult
.getMetaData();
269 int columnCount
= sqlRSMeta
.getColumnCount();
270 String
[] columnNames
= new String
[columnCount
];
272 boolean goThroughRowsTheFirstTime
= true;
273 for(int i
=1; i
<=columnCount
; i
++) {
274 columnNames
[i
-1] = sqlRSMeta
.getColumnName(i
);
276 ArrayList
<String
> v
= new ArrayList
<String
>();
278 sqlResult
.beforeFirst();
279 while (sqlResult
.next()) {
280 String value
= sqlResult
.getString(i
);
282 // the first time: count rows
283 if (goThroughRowsTheFirstTime
)
287 if (goThroughRowsTheFirstTime
)
288 goThroughRowsTheFirstTime
= false;
290 // put result in output HashMap
291 String
[]s
= new String
[countRows
];
293 output
.put(columnNames
[i
-1], s
);
296 System
.out
.print("Debug - SQLExecution - Command returns: ");
297 System
.out
.print("row: " + columnNames
[i
-1] + " vals: ");
299 for (int j
=0; j
<s
.length
; j
++)
300 System
.out
.print(s
[j
] + " ");
301 if (i
== columnCount
- 1)
302 System
.out
.println();
307 catch (java
.sql
.SQLException e
) {
313 * Replace <"> with <''> in the value Strings, or the command will fail.
314 * @param checkString The String that is checked: a part of the command
315 * @return The String, cleared of all quotation marks.
317 private String
checkForQuotationMarks(String checkString
) {
318 String returnString
= checkString
;
320 while ((quotIndex
= returnString
.indexOf('\"')) != -1) {
321 String firstHalf
= returnString
.substring(0, quotIndex
);
322 String secondHalf
= returnString
.substring(quotIndex
+1);
323 returnString
= firstHalf
+ "\'\'" + secondHalf
;