KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > continuent > sequoia > controller > requests > StoredProcedure


1 /**
2  * Sequoia: Database clustering technology.
3  * Copyright (C) 2002-2004 French National Institute For Research In Computer
4  * Science And Control (INRIA).
5  * Copyright (C) 2005-2006 Continuent, Inc.
6  * Contact: sequoia@continuent.org
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  * Initial developer(s): Emmanuel Cecchet.
21  * Contributor(s): ______________________.
22  */

23
24 package org.continuent.sequoia.controller.requests;
25
26 import java.sql.SQLException JavaDoc;
27 import java.util.ArrayList JavaDoc;
28 import java.util.HashMap JavaDoc;
29 import java.util.List JavaDoc;
30 import java.util.SortedMap JavaDoc;
31 import java.util.TreeMap JavaDoc;
32 import java.util.regex.Matcher JavaDoc;
33 import java.util.regex.Pattern JavaDoc;
34
35 import org.continuent.sequoia.common.i18n.Translate;
36 import org.continuent.sequoia.controller.semantic.SemanticBehavior;
37 import org.continuent.sequoia.controller.sql.schema.DatabaseProcedure;
38 import org.continuent.sequoia.controller.sql.schema.DatabaseSchema;
39
40 /**
41  * <code>StoredProcedure</code> is encodes a stored procedure call.
42  * <p>
43  * It can have the following syntax:
44  *
45  * <pre>
46  * {call &lt;procedure-name&gt;[&lt;arg1&gt;,&lt;arg2&gt;, ...]}
47  * {?=call &lt;procedure-name&gt;[&lt;arg1&gt;,&lt;arg2&gt;, ...]}
48  * </pre>
49  *
50  * For more information
51  *
52  * @see org.continuent.sequoia.driver.CallableStatement
53  * @author <a HREF="mailto:Emmanuel.Cecchet@inria.fr">Emmanuel Cecchet </a>
54  * @version 1.0
55  */

56 public class StoredProcedure extends AbstractRequest
57 {
58   private static final long serialVersionUID = 5360592917986126504L;
59
60   /** <code>true</code> if this request might block. */
61   private transient boolean blocking = true;
62
63   /** Number of parameters of the stored procedure */
64   protected int nbOfParameters;
65
66   /**
67    * Map of named parameter values <String(name),String(type)>
68    */

69   private HashMap JavaDoc namedParameterValues = null;
70
71   /**
72    * List of named parameters names
73    */

74   private List JavaDoc namedParameterNames = null;
75
76   /**
77    * Map of out parameter values (parameter index corresponds to index in list)
78    */

79   private SortedMap JavaDoc outParameterValues = null;
80
81   /**
82    * List of out parameter types (parameter index corresponds to index in list)
83    */

84   private List JavaDoc outParameterIndexes = null;
85
86   protected String JavaDoc procedureKey = null;
87
88   private String JavaDoc procedureName = "";
89
90   // Be conservative, if we cannot parse the query, assumes it invalidates
91
// everything
92
protected boolean altersAggregateList = true;
93   protected boolean altersDatabaseCatalog = true;
94   protected boolean altersDatabaseSchema = true;
95   protected boolean altersMetadataCache = true;
96   protected boolean altersQueryResultCache = true;
97   protected boolean altersSomething = true;
98   protected boolean altersStoredProcedureList = true;
99   protected boolean altersUserDefinedTypes = true;
100   protected boolean altersUsers = true;
101
102   // Regular expression for parsing {call ...} statements
103
private static final String JavaDoc STORED_PROCEDURE_PATTERN_STRING = "^((execute\\s+([^(\\s|\\()]+)(.*)?)|(\\{(\\s*\\?\\s*=)?\\s*call\\s+([^(\\s|\\()]+)(.*)?\\})|(\\s*call\\s+([^(\\s|\\()]+)(.*)?))";
104
105   private static final Pattern JavaDoc STORED_PROCEDURE_PATTERN = Pattern
106                                                                    .compile(
107                                                                        STORED_PROCEDURE_PATTERN_STRING,
108                                                                        Pattern.CASE_INSENSITIVE
109                                                                            | Pattern.DOTALL);
110
111   private static int posSyntax1 = 2;
112   private static int posSyntax2 = 5;
113   private static int posSyntax3 = 10;
114
115   /**
116    * Creates a new <code>StoredProcedure</code> instance.
117    *
118    * @param sqlQuery the SQL request
119    * @param escapeProcessing should the driver to escape processing before
120    * sending to the database ?
121    * @param timeout an <code>int</code> value
122    * @param lineSeparator the line separator used in the query
123    */

124   public StoredProcedure(String JavaDoc sqlQuery, boolean escapeProcessing,
125       int timeout, String JavaDoc lineSeparator)
126   {
127     super(sqlQuery, escapeProcessing, timeout, lineSeparator,
128         RequestType.STORED_PROCEDURE);
129   }
130
131   /**
132    * @see org.continuent.sequoia.controller.requests.AbstractRequest#altersAggregateList()
133    */

134   public boolean altersAggregateList()
135   {
136     return altersAggregateList;
137   }
138
139   /**
140    * @see org.continuent.sequoia.controller.requests.AbstractRequest#altersDatabaseCatalog()
141    */

142   public boolean altersDatabaseCatalog()
143   {
144     return altersDatabaseCatalog;
145   }
146
147   /**
148    * @see org.continuent.sequoia.controller.requests.AbstractRequest#altersDatabaseSchema()
149    */

150   public boolean altersDatabaseSchema()
151   {
152     return (getSemantic() == null ? altersDatabaseSchema : getSemantic()
153         .altersDatabaseSchema());
154   }
155
156   /**
157    * @see org.continuent.sequoia.controller.requests.AbstractRequest#altersMetadataCache()
158    */

159   public boolean altersMetadataCache()
160   {
161     return (getSemantic() == null ? altersMetadataCache : getSemantic()
162         .altersMetadataCache());
163   }
164
165   /**
166    * @see org.continuent.sequoia.controller.requests.AbstractRequest#altersQueryResultCache()
167    */

168   public boolean altersQueryResultCache()
169   {
170     return (getSemantic() == null ? altersQueryResultCache : getSemantic()
171         .altersQueryResultCache());
172   }
173
174   /**
175    * @see org.continuent.sequoia.controller.requests.AbstractRequest#altersSomething()
176    */

177   public boolean altersSomething()
178   {
179     return altersSomething;
180   }
181
182   /**
183    * @see org.continuent.sequoia.controller.requests.AbstractRequest#altersStoredProcedureList()
184    */

185   public boolean altersStoredProcedureList()
186   {
187     return altersStoredProcedureList;
188   }
189
190   /**
191    * @see org.continuent.sequoia.controller.requests.AbstractRequest#altersUserDefinedTypes()
192    */

193   public boolean altersUserDefinedTypes()
194   {
195     return altersUserDefinedTypes;
196   }
197
198   /**
199    * @see org.continuent.sequoia.controller.requests.AbstractRequest#altersUsers()
200    */

201   public boolean altersUsers()
202   {
203     return (getSemantic() == null ? altersUsers : getSemantic().altersUsers());
204   }
205
206   /**
207    * @return <code>false</code>
208    * @see org.continuent.sequoia.controller.requests.AbstractRequest#needsMacroProcessing()
209    */

210   public boolean needsMacroProcessing()
211   {
212     return (getSemantic() == null ? true : getSemantic().needsMacroProcessing());
213   }
214
215   /**
216    * Returns the the value of a named parameter.
217    *
218    * @param name parameter name
219    * @return Returns the named parameter value.
220    */

221   public Object JavaDoc getNamedParameterValue(String JavaDoc name)
222   {
223     return namedParameterValues.get(name);
224   }
225
226   /**
227    * Returns the named parameter names or none if this stored procedure call has
228    * no named parameter.
229    *
230    * @return Returns the namedParameterNames.
231    */

232   public List JavaDoc getNamedParameterNames()
233   {
234     return namedParameterNames;
235   }
236
237   /**
238    * Returns the nbOfParameters value.
239    *
240    * @return Returns the nbOfParameters.
241    */

242   public final int getNbOfParameters()
243   {
244     return nbOfParameters;
245   }
246
247   /**
248    * Returns the the value of an out parameter.
249    *
250    * @param idx parameter index
251    * @return Returns the out parameter value.
252    */

253   public Object JavaDoc getOutParameterValue(Object JavaDoc idx)
254   {
255     return outParameterValues.get(idx);
256   }
257
258   /**
259    * Returns the list of out parameter indexes (null if none).
260    *
261    * @return Returns the outParameterIndexes.
262    */

263   public List JavaDoc getOutParameterIndexes()
264   {
265     return outParameterIndexes;
266   }
267
268   /**
269    * Get the stored procedure key
270    *
271    * @return the stored procedure key
272    * @see DatabaseProcedure#buildKey(String, int)
273    */

274   public String JavaDoc getProcedureKey()
275   {
276     if (procedureKey == null)
277       try
278       {
279         parse(null, 0, true);
280       }
281       catch (SQLException JavaDoc e)
282       {
283         return null;
284       }
285     return procedureKey;
286   }
287
288   /**
289    * Returns the stored procedure name.
290    *
291    * @return the stored procedure name
292    */

293   public String JavaDoc getProcedureName()
294   {
295     return procedureName;
296   }
297
298   /**
299    * Tests if this request might block.
300    *
301    * @return <code>true</code> if this request might block
302    */

303   public boolean mightBlock()
304   {
305     return blocking;
306   }
307
308   /**
309    * Sets if this request might block.
310    *
311    * @param blocking a <code>boolean</code> value
312    */

313   public void setBlocking(boolean blocking)
314   {
315     this.blocking = blocking;
316   }
317
318   /**
319    * Set a named parameter on this stored procedure call.
320    *
321    * @param paramName name of the parameter
322    * @param val named parameter value
323    */

324   public synchronized void setNamedParameterValue(String JavaDoc paramName, Object JavaDoc val)
325   {
326     if (namedParameterValues == null)
327       namedParameterValues = new HashMap JavaDoc();
328     namedParameterValues.put(paramName, val);
329   }
330
331   /**
332    * Set a named parameter name on this stored procedure call.
333    *
334    * @param paramName name of the parameter
335    */

336   public synchronized void setNamedParameterName(String JavaDoc paramName)
337   {
338     if (namedParameterNames == null)
339       namedParameterNames = new ArrayList JavaDoc();
340     namedParameterNames.add(paramName);
341   }
342
343   /**
344    * Set an out parameter value on this stored procedure call.
345    *
346    * @param paramIdx index of the parameter
347    * @param val value of the parameter
348    */

349   public synchronized void setOutParameterValue(Object JavaDoc paramIdx, Object JavaDoc val)
350   {
351     if (outParameterValues == null)
352       outParameterValues = new TreeMap JavaDoc();
353     outParameterValues.put(paramIdx, val);
354   }
355
356   /**
357    * Set an out parameter index on this stored procedure call.
358    *
359    * @param paramIdx index of the parameter
360    */

361   public synchronized void setOutParameterIndex(int paramIdx)
362   {
363     if (outParameterIndexes == null)
364       outParameterIndexes = new ArrayList JavaDoc();
365     outParameterIndexes.add(new Integer JavaDoc(paramIdx));
366   }
367
368   /**
369    * Just get the stored procedure name.
370    *
371    * @see org.continuent.sequoia.controller.requests.AbstractRequest#parse(org.continuent.sequoia.controller.sql.schema.DatabaseSchema,
372    * int, boolean)
373    */

374   public void parse(DatabaseSchema schema, int granularity,
375       boolean isCaseSensitive) throws SQLException JavaDoc
376   {
377     Matcher JavaDoc matcher;
378     sqlQueryOrTemplate = sqlQueryOrTemplate.trim();
379
380     matcher = STORED_PROCEDURE_PATTERN.matcher(sqlQueryOrTemplate);
381     if (!matcher.matches())
382       return;
383
384     String JavaDoc parameterList = null;
385
386     if (matcher.group(posSyntax1) != null)
387     {
388       procedureName = matcher.group(posSyntax1 + 1);
389       parameterList = matcher.group(posSyntax1 + 2);
390     }
391     else if (matcher.group(posSyntax2) != null)
392     {
393       procedureName = matcher.group(posSyntax2 + 2);
394       parameterList = matcher.group(posSyntax2 + 3);
395     }
396     else
397     {
398       procedureName = matcher.group(posSyntax3);
399       parameterList = matcher.group(posSyntax3 + 1);
400     }
401
402     int parenthesis = parameterList.indexOf('(');
403
404     if (parenthesis == -1)
405     {
406       // sometimes, parameters are not inside ()
407
// we will check if we find ',' after the name of the stored procedure
408
// to check for parameters
409
int commaIdx = parameterList.indexOf(',');
410       if (commaIdx == -1)
411       {
412         if (parameterList.trim().length() != 0)
413           nbOfParameters = 1;
414         else
415           nbOfParameters = 0;
416       }
417       else
418       {
419         nbOfParameters = 1;
420         while (commaIdx != -1)
421         {
422           nbOfParameters++;
423           commaIdx = parameterList.indexOf(',', commaIdx + 1);
424         }
425       }
426     }
427     else
428     {
429       // Note that indexOf is tolerant and accept values greater than the String
430
// size so there is no need to check for the limit.
431
int commaIdx = parameterList.indexOf(',', parenthesis + 1);
432
433       // Here we just count the number of commas to find the number of
434
// parameters (which is equal to nb of commas plus one if there is at
435
// least one comma).
436

437       if (commaIdx == -1)
438       { // Check if we have 0 or 1 parameter
439
int closingParenthesis = parameterList.indexOf(')', parenthesis + 1);
440         try
441         {
442           if (parameterList.substring(parenthesis + 1, closingParenthesis)
443               .trim().length() == 0)
444             nbOfParameters = 0;
445           else
446             nbOfParameters = 1;
447         }
448         catch (RuntimeException JavaDoc e)
449         { // Malformed query, just use -1 as the number of parameters
450
nbOfParameters = -1;
451         }
452       }
453       else
454       {
455         nbOfParameters = 1;
456         while (commaIdx != -1)
457         {
458           nbOfParameters++;
459           commaIdx = parameterList.indexOf(',', commaIdx + 1);
460         }
461       }
462     }
463
464     // Build the key and retrieve the associated semantic
465
procedureKey = DatabaseProcedure.buildKey(procedureName, nbOfParameters);
466
467     SemanticBehavior spSemantic = getSemanticManager()
468         .getStoredProcedureSemantic(procedureKey);
469     if (spSemantic != null)
470       setSemantic(spSemantic);
471
472     isParsed = true;
473   }
474
475   /**
476    * @see org.continuent.sequoia.controller.requests.AbstractRequest#cloneParsing(org.continuent.sequoia.controller.requests.AbstractRequest)
477    */

478   public void cloneParsing(AbstractRequest request)
479   {
480     if (!request.isParsed)
481       return;
482     cloneParsingCommons(request);
483     StoredProcedure other = (StoredProcedure) request;
484     procedureKey = other.getProcedureKey();
485     nbOfParameters = other.getNbOfParameters();
486     writeLockedTables = other.writeLockedTables;
487   }
488
489   /**
490    * Copy (simple assignment, no object cloning so be sure to not modify the
491    * original object else you expose yourself to nasty side effects) named
492    * parameter values and names ; and out parameter values and indexes of this
493    * stored procedure call.
494    *
495    * @param otherProc the other stored procedure that has the result to copy
496    * into this object
497    */

498   public void copyNamedAndOutParameters(StoredProcedure otherProc)
499   {
500     this.outParameterValues = otherProc.outParameterValues;
501     this.outParameterIndexes = otherProc.outParameterIndexes;
502     this.namedParameterValues = otherProc.namedParameterValues;
503     this.namedParameterNames = otherProc.namedParameterNames;
504   }
505
506   /**
507    * @see org.continuent.sequoia.controller.requests.AbstractRequest#getParsingResultsAsString()
508    */

509   public String JavaDoc getParsingResultsAsString()
510   {
511     StringBuffer JavaDoc sb = new StringBuffer JavaDoc(super.getParsingResultsAsString());
512     sb.append(Translate.get("request.storedproc.name", procedureName));
513     sb.append(Translate.get("request.blocking", blocking));
514     sb.append(Translate.get("request.storedproc.parameters.number",
515         nbOfParameters));
516     if (namedParameterNames != null && namedParameterNames.size() > 0)
517     {
518       sb.append(Translate.get("request.storedproc.named.parameters.names"));
519       for (int i = 0; i < namedParameterNames.size(); i++)
520       {
521         sb.append(Translate.get("request.storedproc.named.parameters.names",
522             namedParameterNames.get(i)));
523       }
524     }
525     if (namedParameterValues != null && namedParameterValues.size() > 0)
526     {
527       sb.append(Translate.get("request.storedproc.named.parameters.values"));
528       for (int i = 0; i < namedParameterValues.size(); i++)
529       {
530         sb.append(Translate.get("request.storedproc.named.parameters.value",
531             new String JavaDoc[]{
532                 namedParameterValues.keySet().toArray()[i].toString(),
533                 namedParameterValues.get(
534                     namedParameterValues.keySet().toArray()[i]).toString()}));
535       }
536     }
537     if (outParameterIndexes != null && outParameterIndexes.size() > 0)
538     {
539       sb.append(Translate.get("request.storedproc.out.parameters.indexes"));
540       for (int i = 0; i < outParameterIndexes.size(); i++)
541       {
542         sb.append(Translate.get("request.storedproc.out.parameters.index",
543             outParameterIndexes.get(i)));
544       }
545     }
546     if (outParameterValues != null && outParameterValues.size() > 0)
547     {
548       sb.append(Translate.get("request.storedproc.out.parameters.values"));
549       for (int i = 0; i < outParameterValues.size(); i++)
550       {
551         sb
552             .append(Translate.get("request.storedproc.out.parameters.value",
553                 new String JavaDoc[]{
554                     outParameterValues.keySet().toArray()[i].toString(),
555                     outParameterValues.get(
556                         outParameterValues.keySet().toArray()[i]).toString()}));
557       }
558     }
559     sb.append(Translate.get("request.alters",
560         new String JavaDoc[]{String.valueOf(altersAggregateList()),
561             String.valueOf(altersDatabaseCatalog()),
562             String.valueOf(altersDatabaseSchema()),
563             String.valueOf(altersMetadataCache()),
564             String.valueOf(altersQueryResultCache()),
565             String.valueOf(altersSomething()),
566             String.valueOf(altersStoredProcedureList()),
567             String.valueOf(altersUserDefinedTypes()),
568             String.valueOf(altersUsers())}));
569     return sb.toString();
570   }
571
572 }
Popular Tags