KickJava   Java API By Example, From Geeks To Geeks.

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


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 AmicoSoft, Inc. dba Emic Networks
6  * Copyright (C) 2005-2006 Continuent, Inc.
7  * Contact: sequoia@continuent.org
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  * http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  * Initial developer(s): Emmanuel Cecchet.
22  * Contributor(s): Julie Marguerite, Mathieu Peltier, Marc Herbert
23  */

24
25 package org.continuent.sequoia.controller.requests;
26
27 import java.io.Serializable JavaDoc;
28 import java.sql.SQLException JavaDoc;
29 import java.util.ArrayList JavaDoc;
30 import java.util.Iterator JavaDoc;
31 import java.util.List JavaDoc;
32 import java.util.SortedSet JavaDoc;
33
34 import org.continuent.sequoia.common.i18n.Translate;
35 import org.continuent.sequoia.common.util.TransactionIsolationLevelConverter;
36 import org.continuent.sequoia.controller.semantic.SemanticBehavior;
37 import org.continuent.sequoia.controller.semantic.SemanticManager;
38 import org.continuent.sequoia.controller.sql.schema.DatabaseSchema;
39 import org.continuent.sequoia.controller.sql.schema.DatabaseTable;
40
41 /**
42  * An <code>AbstractRequest</code> defines the skeleton of an SQL request.
43  * Requests have to be serializable (at least) for inter-controller
44  * communications.
45  *
46  * @author <a HREF="mailto:Emmanuel.Cecchet@inria.fr">Emmanuel Cecchet </a>
47  * @author <a HREF="mailto:Julie.Marguerite@inria.fr">Julie Marguerite </a>
48  * @author <a HREF="mailto:Mathieu.Peltier@inrialpes.fr">Mathieu Peltier </a>
49  * @author <a HREF="mailto:Marc.Herbert@emicnetworks.com">Marc Herbert </a>
50  * @version 1.0
51  */

52 public abstract class AbstractRequest implements Serializable JavaDoc
53 {
54   // Unneeded fields for controller-controller communication are all tagged
55
// as transient
56

57   /**
58    * Rationale is to avoid the performance cost of .instanceof(), at
59    * serialization time and elsewhere.
60    */

61   int requestType = RequestType.UNDEFINED;
62
63   /** Request unique id (set by the controller). */
64   protected long id;
65
66   /** Recovery log id (local to the controller, set by the controller) */
67   protected transient long logId;
68
69   /**
70    * SQL query (should be set in constructor) or query template if this is a
71    * PreparedStatement.
72    */

73   protected String JavaDoc sqlQueryOrTemplate;
74
75   /**
76    * Encoded PreparedStatement paremeters (null if this is a statement)
77    */

78   protected String JavaDoc preparedStatementParameters = null;
79
80   /**
81    * Unique key identifying the query. If the request is executed in a
82    * statement, the unique key is the same as sqlQuery else is it is a
83    * combination of the sqlSkeleton and the parameters contained in sqlQuery.
84    */

85   protected transient String JavaDoc uniqueKey = null;
86
87   /**
88    * Semantic behavior attached to the request (null if no specific semantic)
89    */

90   private transient SemanticBehavior semantic = null;
91
92   /** Virtual database semantic manager (to be set before parsing the query) */
93   private transient SemanticManager semanticManager = null;
94
95   /**
96    * Login used to issue this request (must be set by the
97    * VirtualDatabaseWorkerThread).
98    */

99   protected String JavaDoc login;
100
101   /** Whether this request is cacheable or not. */
102   protected transient int cacheable = RequestType.UNCACHEABLE;
103
104   /** Whether the SQL content has been parsed or not. */
105   protected transient boolean isParsed = false;
106
107   /** Where the macros in the SQL have been processed or not */
108   private boolean macrosAreProcessed = false;
109
110   /*
111    * ResultSet Parameters
112    */

113   protected int maxRows;
114   protected int fetchSize;
115   protected String JavaDoc cursorName;
116
117   //
118
// Connection related parameters
119
//
120

121   /** True if the connection has been set to read-only */
122   protected boolean isReadOnly = false;
123
124   /**
125    * Whether this request has been sent in <code>autocommit</code> mode or
126    * not.
127    */

128   protected boolean isAutoCommit;
129
130   /**
131    * Transaction identifier if this request belongs to a transaction. The value
132    * is set by the VirtualDatabaseWorkerThread.
133    */

134   protected long transactionId;
135
136   /**
137    * Transaction isolation level to use when executing the query inside a
138    * transaction. The value is set by the VirtualDatabaseWorkerThread.
139    */

140   protected int transactionIsolation;
141
142   /**
143    * Timeout for this request in seconds, value 0 means no timeout (should be
144    * set in constructor). This timeout is in seconds, reflecting the jdbc-spec,
145    * and is passed as-is to the backends jdbc-driver. Internally converted to ms
146    * via getTimeoutMs().
147    */

148   protected int timeoutInSeconds;
149
150   /**
151    * Should the backend driver do escape processing before sending to the
152    * database? Simply forwarded to backend driver. No setter for this member,
153    * should be set in constructor.
154    *
155    * @see java.sql.Statement#setEscapeProcessing(boolean)
156    */

157   protected boolean escapeProcessing = true;
158
159   /** @see #getLineSeparator() */
160   private String JavaDoc lineSeparator = null;
161
162   /**
163    * True if this request executes on a persistent connection
164    */

165   private boolean persistentConnection;
166
167   /**
168    * Persistent connection id if persistentConnection is true
169    */

170   private long persistentConnectionId;
171
172   /**
173    * True if the controller must retrieve SQL warnings
174    */

175   private boolean retrieveSQLWarnings = false;
176
177   //
178
// Controller internal logic
179
//
180

181   private transient boolean isLazyTransactionStart;
182
183   /**
184    * Ip addres of the client that sent the request
185    */

186   private String JavaDoc clientIpAddress;
187
188   /**
189    * True if the request requires all connections to be closed to take effect.
190    */

191   protected boolean requiresConnectionPoolFlush = false;
192
193   /**
194    * Time in ms at which the request execution started
195    */

196   protected transient long startTime;
197
198   /**
199    * Time in ms at which the request execution ended
200    */

201   protected transient long endTime;
202
203   /**
204    * Sorted list of table names that must be locked in write. This list may be
205    * null or empty if no table needs to be locked.
206    */

207   protected SortedSet JavaDoc writeLockedTables = null;
208
209   /**
210    * Default constructor Creates a new <code>AbstractRequest</code> object
211    *
212    * @param sqlQuery the SQL query
213    * @param escapeProcessing should the driver to escape processing before
214    * sending to the database ?
215    * @param timeout an <code>int</code> value
216    * @param lineSeparator the line separator used in the query
217    * @param requestType the request type as defined in RequestType class
218    * @see RequestType
219    */

220   public AbstractRequest(String JavaDoc sqlQuery, boolean escapeProcessing,
221       int timeout, String JavaDoc lineSeparator, int requestType)
222   {
223     this.sqlQueryOrTemplate = sqlQuery;
224     this.escapeProcessing = escapeProcessing;
225     this.timeoutInSeconds = timeout;
226     this.lineSeparator = lineSeparator;
227     this.requestType = requestType;
228   }
229
230   //
231
// Abstract methods
232
//
233

234   /**
235    * Returns true if this request invalidates somehow the Aggregate List.
236    *
237    * @return true if the aggregate list is altered.
238    * @deprecated use semantic information instead
239    */

240   public abstract boolean altersAggregateList();
241
242   /**
243    * Returns true if this request invalidates somehow the Database Catalog.
244    *
245    * @return true if the database catalog is altered.
246    * @deprecated use semantic information instead
247    */

248   public abstract boolean altersDatabaseCatalog();
249
250   /**
251    * Returns true if this request invalidates somehow the Database Schema.
252    *
253    * @return true if the database schema is altered.
254    * @deprecated use semantic information instead
255    */

256   public abstract boolean altersDatabaseSchema();
257
258   /**
259    * Returns true if this request invalidates somehow the Metadata Cache.
260    *
261    * @return true if the metadata cache is altered.
262    * @deprecated use semantic information instead
263    */

264   public abstract boolean altersMetadataCache();
265
266   /**
267    * Returns true if this request invalidates somehow the Query Result Cache.
268    *
269    * @return true if the query result cache is altered.
270    * @deprecated use semantic information instead
271    */

272   public abstract boolean altersQueryResultCache();
273
274   /**
275    * Returns true if this request invalidates somehow the Stored Procedure List.
276    *
277    * @return true if the stored procedure list is altered.
278    * @deprecated use semantic information instead
279    */

280   public abstract boolean altersStoredProcedureList();
281
282   /**
283    * Returns true if this request invalidates somehow the User Defined Types.
284    *
285    * @return true if the UDTs are altered.
286    * @deprecated use semantic information instead
287    */

288   public abstract boolean altersUserDefinedTypes();
289
290   /**
291    * Returns true if this request invalidates somehow the Users definition or
292    * rights.
293    *
294    * @return true if the users are altered.
295    * @deprecated use semantic information instead
296    */

297   public abstract boolean altersUsers();
298
299   /**
300    * Returns true if this request invalidates somehow any Sequoia internal
301    * structure or caches (true if any of the other abstract altersXXX methods
302    * returns true).
303    *
304    * @return true if the request alters anything that triggers an invalidation
305    * in Sequoia.
306    */

307   public abstract boolean altersSomething();
308
309   /**
310    * Clones the parsing of a request.
311    *
312    * @param request the parsed request to clone
313    */

314   public abstract void cloneParsing(AbstractRequest request);
315
316   /**
317    * Clone the parts of parsing that are common to all kind of requests.
318    *
319    * @param request the parsed request to clone
320    */

321   protected void cloneParsingCommons(AbstractRequest request)
322   {
323     cacheable = request.getCacheAbility();
324     semantic = request.getSemantic();
325   }
326
327   /**
328    * Returns the list of database table names that must be write locked by the
329    * execution of this request.
330    *
331    * @return SortedSet of String containing table names to be write locked by
332    * this request. This list may be null or empty if no table needs to
333    * be locked.
334    */

335   public SortedSet JavaDoc getWriteLockedDatabaseTables()
336   {
337     return writeLockedTables;
338   }
339
340   /**
341    * Returns <code>true</code> if this request requires macro (RAND(), NOW(),
342    * ...) processing.
343    *
344    * @return <code>true</code> if macro processing is required
345    * @see org.continuent.sequoia.controller.loadbalancer.AbstractLoadBalancer#handleMacros(AbstractRequest)
346    */

347   public abstract boolean needsMacroProcessing();
348
349   /**
350    * Parses the SQL request and extract the selected columns and tables given
351    * the <code>DatabaseSchema</code> of the database targeted by this request.
352    * <p>
353    * An exception is thrown when the parsing fails. Warning, this method does
354    * not check the validity of the request. In particular, invalid request could
355    * be parsed without throwing an exception. However, valid SQL request should
356    * never throw an exception.
357    *
358    * @param schema a <code>DatabaseSchema</code> value
359    * @param granularity parsing granularity as defined in
360    * <code>ParsingGranularities</code>
361    * @param isCaseSensitive true if parsing must be case sensitive
362    * @exception SQLException if the parsing fails
363    */

364   public abstract void parse(DatabaseSchema schema, int granularity,
365       boolean isCaseSensitive) throws SQLException JavaDoc;
366
367   //
368
// Request type related functions
369
//
370

371   /**
372    * Returns <code>true</code> if this request in a <code>ALTER</code>
373    * statement.
374    *
375    * @return a <code>boolean</code> value
376    */

377   public final boolean isAlter()
378   {
379     return RequestType.isAlter(this.requestType);
380   }
381
382   /**
383    * Returns <code>true</code> if this request in a <code>CREATE</code>
384    * statement.
385    *
386    * @return a <code>boolean</code> value
387    */

388   public final boolean isCreate()
389   {
390     return RequestType.isCreate(this.requestType);
391   }
392
393   /**
394    * Returns <code>true</code> if this request in a <code>DELETE</code>
395    * statement.
396    *
397    * @return a <code>boolean</code> value
398    */

399   public final boolean isDelete()
400   {
401     return RequestType.isDelete(this.requestType);
402   }
403
404   /**
405    * Returns <code>true</code> if this request in a <code>DROP</code>
406    * statement.
407    *
408    * @return a <code>boolean</code> value
409    */

410   public final boolean isDrop()
411   {
412     return RequestType.isDrop(this.requestType);
413   }
414
415   /**
416    * Returns <code>true</code> if this request in an <code>INSERT</code>
417    * statement.
418    *
419    * @return a <code>boolean</code> value
420    */

421   public final boolean isInsert()
422   {
423     return RequestType.isInsert(this.requestType);
424   }
425
426   /**
427    * Returns <code>true</code> if this request in a <code>SELECT</code>
428    * statement.
429    *
430    * @return a <code>boolean</code> value
431    */

432   public final boolean isSelect()
433   {
434     return RequestType.isSelect(this.requestType);
435   }
436
437   /**
438    * Returns <code>true</code> if this request in an <code>UPDATE</code>
439    * statement.
440    *
441    * @return a <code>boolean</code> value
442    */

443   public final boolean isUpdate()
444   {
445     return RequestType.isUpdate(this.requestType);
446   }
447
448   //
449
// Getter/Setters
450
//
451

452   /**
453    * Returns the cacheable status of this request. It can be:
454    * {@link org.continuent.sequoia.controller.requests.RequestType#CACHEABLE},
455    * {@link org.continuent.sequoia.controller.requests.RequestType#UNCACHEABLE}or
456    * {@link org.continuent.sequoia.controller.requests.RequestType#UNIQUE_CACHEABLE}
457    *
458    * @return a <code>int</code> value
459    */

460   public int getCacheAbility()
461   {
462     return cacheable;
463   }
464
465   /**
466    * Set the cacheable status of this request. It can be:
467    * {@link org.continuent.sequoia.controller.requests.RequestType#CACHEABLE},
468    * {@link org.continuent.sequoia.controller.requests.RequestType#UNCACHEABLE}or
469    * {@link org.continuent.sequoia.controller.requests.RequestType#UNIQUE_CACHEABLE}
470    *
471    * @param cacheAbility a <code>int</code> value
472    */

473   public void setCacheAbility(int cacheAbility)
474   {
475     this.cacheable = cacheAbility;
476   }
477
478   /**
479    * Returns the clientIpAddress value.
480    *
481    * @return Returns the clientIpAddress.
482    */

483   public String JavaDoc getClientIpAddress()
484   {
485     return clientIpAddress;
486   }
487
488   /**
489    * Sets the clientIpAddress value.
490    *
491    * @param clientIpAddress The clientIpAddress to set.
492    */

493   public void setClientIpAddress(String JavaDoc clientIpAddress)
494   {
495     this.clientIpAddress = clientIpAddress;
496   }
497
498   /**
499    * Returns the cursorName value.
500    *
501    * @return Returns the cursorName.
502    */

503   public String JavaDoc getCursorName()
504   {
505     return cursorName;
506   }
507
508   /**
509    * Sets the cursorName value.
510    *
511    * @param cursorName The cursorName to set.
512    */

513   public void setCursorName(String JavaDoc cursorName)
514   {
515     this.cursorName = cursorName;
516   }
517
518   /**
519    * Returns the endTime value.
520    *
521    * @return Returns the endTime.
522    */

523   public long getEndTime()
524   {
525     return endTime;
526   }
527
528   /**
529    * Sets the endTime value.
530    *
531    * @param endTime The endTime to set.
532    */

533   public void setEndTime(long endTime)
534   {
535     this.endTime = endTime;
536   }
537
538   /**
539    * Return the request execution time in milliseconds. If start time was not
540    * set, 0 is returned. If endTime is not set, the diff between start time and
541    * current time is returned. If start and end time are set, that elapsed time
542    * between start and end is returned.
543    *
544    * @return execution time in ms.
545    */

546   public long getExecTimeInMs()
547   {
548     long execTime = 0;
549     if (startTime != 0)
550     {
551       if (endTime != 0)
552         execTime = endTime - startTime;
553       else
554         execTime = System.currentTimeMillis() - startTime;
555       if (execTime < 0)
556         execTime = 0;
557     }
558     return execTime;
559   }
560
561   /**
562    * Returns <code>true</code> if the driver should escape processing before
563    * sending to the database?
564    *
565    * @return a <code>boolean</code> value
566    */

567   public boolean getEscapeProcessing()
568   {
569     return escapeProcessing;
570   }
571
572   /**
573    * Returns the fetchSize value.
574    *
575    * @return Returns the fetchSize.
576    */

577   public int getFetchSize()
578   {
579     return fetchSize;
580   }
581
582   /**
583    * Sets the fetchSize value.
584    *
585    * @param fetchSize The fetchSize to set.
586    * @see org.continuent.sequoia.driver.Statement
587    */

588   public void setFetchSize(int fetchSize)
589   {
590     this.fetchSize = fetchSize;
591   }
592
593   /**
594    * Returns the unique id of this request.
595    *
596    * @return the request id
597    */

598   public long getId()
599   {
600     return id;
601   }
602
603   /**
604    * Sets the unique id of this request.
605    *
606    * @param id the id to set
607    */

608   public void setId(long id)
609   {
610     this.id = id;
611   }
612
613   /**
614    * Returns true if this request triggers a lazy transaction start that
615    * requires a 'begin' to be logged into the reocvery log.
616    *
617    * @return Returns the isLazyTransactionStart.
618    */

619   public final boolean isLazyTransactionStart()
620   {
621     return isLazyTransactionStart;
622   }
623
624   /**
625    * Set a flag to tell whether this request triggers a lazy transaction start
626    * that requires a 'begin' to be logged into the reocvery log.
627    *
628    * @param isLazyStart true if a begin must be logged before this request
629    */

630   public void setIsLazyTransactionStart(boolean isLazyStart)
631   {
632     isLazyTransactionStart = isLazyStart;
633   }
634
635   /**
636    * Returns the logId value.
637    *
638    * @return Returns the logId.
639    */

640   public final long getLogId()
641   {
642     return logId;
643   }
644
645   /**
646    * Sets the logId value.
647    *
648    * @param logId The logId to set.
649    */

650   public final void setLogId(long logId)
651   {
652     this.logId = logId;
653   }
654
655   /**
656    * Returns the login used to issue this request.
657    *
658    * @return a <code>String</code> value
659    */

660   public String JavaDoc getLogin()
661   {
662     return login;
663   }
664
665   /**
666    * Returns the lineSeparator used in the request string (required to parse
667    * it). For practical reasons this is just
668    * System.getProperty("line.separator") on the client. Used to be defined
669    * per-request, now only once per-connection.
670    * <http://www.unicode.org/reports/tr13/tr13-9.html>
671    *
672    * @return the lineSeparator.
673    */

674   public String JavaDoc getLineSeparator()
675   {
676     return lineSeparator;
677   }
678
679   /**
680    * Sets the lineSeparator value. Unfortunately needed at deserialization time.
681    * Could be removed (and field made final) if lineSeparator was _always_
682    * passed as an argument to the factory (currently only half of the time).
683    *
684    * @param lineSeparator The lineSeparator to set.
685    */

686   public final void setLineSeparator(String JavaDoc lineSeparator)
687   {
688     this.lineSeparator = lineSeparator;
689   }
690
691   /**
692    * Sets the login to use to issue this request.
693    *
694    * @param login a <code>String</code> value
695    */

696   public void setLogin(String JavaDoc login)
697   {
698     this.login = login;
699   }
700
701   /**
702    * Returns true if macros have already been processed in the request.
703    *
704    * @return Returns the macrosAreProcessed value.
705    */

706   public boolean getMacrosAreProcessed()
707   {
708     return macrosAreProcessed;
709   }
710
711   /**
712    * Sets the macrosAreProcessed value.
713    *
714    * @param macrosAreProcessed The macrosAreProcessed to set.
715    */

716   public void setMacrosAreProcessed(boolean macrosAreProcessed)
717   {
718     this.macrosAreProcessed = macrosAreProcessed;
719   }
720
721   /**
722    * Get the maximum number of rows the ResultSet can contain.
723    *
724    * @return maximum number of rows
725    * @see java.sql.Statement#getMaxRows()
726    */

727   public int getMaxRows()
728   {
729     return maxRows;
730   }
731
732   /**
733    * Set the maximum number of rows in the ResultSet. Used only by Statement.
734    *
735    * @param rows maximum number of rows
736    * @see java.sql.Statement#setMaxRows(int)
737    */

738   public void setMaxRows(int rows)
739   {
740     maxRows = rows;
741   }
742
743   /**
744    * Returns the semantic value.
745    *
746    * @return Returns the semantic.
747    */

748   public final SemanticBehavior getSemantic()
749   {
750     return semantic;
751   }
752
753   /**
754    * Sets the semantic value. isParsed becomes true if the semantic is not null.
755    * Note that the semantic manager should be set before calling this method.
756    *
757    * @param semantic The semantic to set.
758    */

759   public final void setSemantic(SemanticBehavior semantic)
760   {
761     this.semantic = semantic;
762     if (semanticManager == null)
763       throw new RuntimeException JavaDoc("Semantic manager not set on request "
764           + toString());
765     writeLockedTables = semanticManager.getWriteLockedTables(semantic);
766     isParsed = semantic != null;
767   }
768
769   /**
770    * Returns the semanticManager value.
771    *
772    * @return Returns the semanticManager.
773    */

774   public final SemanticManager getSemanticManager()
775   {
776     return semanticManager;
777   }
778
779   /**
780    * Sets the semanticManager value.
781    *
782    * @param semanticManager The semanticManager to set.
783    */

784   public final void setSemanticManager(SemanticManager semanticManager)
785   {
786     this.semanticManager = semanticManager;
787   }
788
789   /**
790    * Gets the SQL code of this request if this is a statement or sql template
791    * (with ? as parameter placeholders) if this is a PreparedStatement.
792    *
793    * @return the SQL query or the PreparedStatement template
794    */

795   public String JavaDoc getSqlOrTemplate()
796   {
797     return sqlQueryOrTemplate;
798   }
799
800   /**
801    * Set the SQL statement or PreparedStatement template of this request.
802    * Warning! The request parsing validity is not checked. The caller has to
803    * recall {@link #parse(DatabaseSchema, int, boolean)} if needed.
804    *
805    * @param sql SQL statement or statment template if this is a
806    * PreparedStatement
807    * @see org.continuent.sequoia.controller.loadbalancer.AbstractLoadBalancer#handleMacros(AbstractRequest)
808    */

809   public void setSqlOrTemplate(String JavaDoc sql)
810   {
811     this.sqlQueryOrTemplate = sql;
812     // Reset the key (to make sure that getUniqueKey() is ok)
813
uniqueKey = null;
814   }
815
816   /**
817    * Get a short form of this request if the SQL statement exceeds
818    * nbOfCharacters.
819    *
820    * @param nbOfCharacters number of characters to include in the short form.
821    * @return the nbOfCharacters first characters of the SQL statement
822    */

823   public String JavaDoc getSqlShortForm(int nbOfCharacters)
824   {
825     String JavaDoc key = getUniqueKey();
826     if ((nbOfCharacters == 0) || (key.length() < nbOfCharacters))
827       return key;
828     else
829       return key.substring(0, nbOfCharacters) + "...";
830   }
831
832   /**
833    * Return the encoded parameters of the PreparedStatement (null if this is a
834    * Statement)
835    *
836    * @return encoded parameters
837    */

838   public String JavaDoc getPreparedStatementParameters()
839   {
840     return preparedStatementParameters;
841   }
842
843   /**
844    * Set the parameters of the PreparedStatement
845    *
846    * @param params parameters of the <code>PreparedStatement</code>.
847    */

848   public void setPreparedStatementParameters(String JavaDoc params)
849   {
850     preparedStatementParameters = params;
851   }
852
853   /**
854    * Returns the startTime value.
855    *
856    * @return Returns the startTime.
857    */

858   public long getStartTime()
859   {
860     return startTime;
861   }
862
863   /**
864    * Sets the startTime value.
865    *
866    * @param startTime The startTime to set.
867    */

868   public void setStartTime(long startTime)
869   {
870     this.startTime = startTime;
871   }
872
873   /**
874    * Gets the timeout for this request in seconds.
875    *
876    * @return timeout in seconds (0 means no timeout)
877    */

878   public int getTimeout()
879   {
880     return timeoutInSeconds;
881   }
882
883   /**
884    * Sets the new timeout in seconds for this request.
885    *
886    * @param timeout an <code>int</code> value
887    * @see org.continuent.sequoia.controller.scheduler
888    */

889   public void setTimeout(int timeout)
890   {
891     this.timeoutInSeconds = timeout;
892   }
893
894   /**
895    * Gets the identifier of the transaction if this request belongs to a
896    * transaction, or -1 if this request does not belong to a transaction.
897    *
898    * @return transaction identifier or -1
899    */

900   public long getTransactionId()
901   {
902     return transactionId;
903   }
904
905   /**
906    * Sets the transaction identifier this request belongs to.
907    *
908    * @param id transaction id
909    */

910   public void setTransactionId(long id)
911   {
912     transactionId = id;
913   }
914
915   /**
916    * Returns the transaction isolation level.
917    *
918    * @return Returns the transaction isolation.
919    */

920   public int getTransactionIsolation()
921   {
922     return transactionIsolation;
923   }
924
925   /**
926    * Sets the transaction isolation level that must be used to execute this
927    * request
928    *
929    * @param isolationLevel the transaction isolation level
930    */

931   public void setTransactionIsolation(int isolationLevel)
932   {
933     this.transactionIsolation = isolationLevel;
934   }
935
936   /**
937    * Get the type of the request as a String. <strong>This method is intended to
938    * be used for debug and log only. Do not use in other cases.</strong>
939    *
940    * @return the type of the request as a String.
941    * @see RequestType#getTypeAsString(AbstractRequest)
942    */

943   public String JavaDoc getType()
944   {
945     return RequestType.getTypeAsString(this);
946   }
947
948   /**
949    * Returns the unique key identifying this request.
950    *
951    * @return Returns the uniqueKey.
952    */

953   public String JavaDoc getUniqueKey()
954   {
955     if (uniqueKey == null)
956     {
957       if (preparedStatementParameters == null)
958         uniqueKey = sqlQueryOrTemplate;
959       else
960         uniqueKey = sqlQueryOrTemplate + "/" + preparedStatementParameters;
961     }
962     return uniqueKey;
963   }
964
965   /**
966    * Returns <code>true</code> if the request should be executed in
967    * <code>autocommit</code> mode.
968    *
969    * @return a <code>boolean</code> value
970    */

971   public boolean isAutoCommit()
972   {
973     return isAutoCommit;
974   }
975
976   /**
977    * Sets the autocommit mode for this request.
978    *
979    * @param isAutoCommit <code>true</code> if <code>autocommit</code> should
980    * be used
981    */

982   public void setIsAutoCommit(boolean isAutoCommit)
983   {
984     this.isAutoCommit = isAutoCommit;
985   }
986
987   /**
988    * Returns <code>true</code> if the request SQL content has been already
989    * parsed.
990    *
991    * @return a <code>boolean</code> value
992    */

993   public boolean isParsed()
994   {
995     return isParsed;
996   }
997
998   /**
999    * Returns the persistentConnection value.
1000   *
1001   * @return Returns the persistentConnection.
1002   */

1003  public final boolean isPersistentConnection()
1004  {
1005    return persistentConnection;
1006  }
1007
1008  /**
1009   * Sets the persistentConnection value.
1010   *
1011   * @param persistentConnection The persistentConnection to set.
1012   */

1013  public final void setPersistentConnection(boolean persistentConnection)
1014  {
1015    this.persistentConnection = persistentConnection;
1016  }
1017
1018  /**
1019   * Returns the persistentConnectionId value.
1020   *
1021   * @return Returns the persistentConnectionId.
1022   */

1023  public final long getPersistentConnectionId()
1024  {
1025    return persistentConnectionId;
1026  }
1027
1028  /**
1029   * Sets the persistentConnectionId value.
1030   *
1031   * @param persistentConnectionId The persistentConnectionId to set.
1032   */

1033  public final void setPersistentConnectionId(long persistentConnectionId)
1034  {
1035    this.persistentConnectionId = persistentConnectionId;
1036  }
1037
1038  /**
1039   * Returns <code>true</code> if the connection is set to read-only
1040   *
1041   * @return a <code>boolean</code> value
1042   */

1043  public boolean isReadOnly()
1044  {
1045    return isReadOnly;
1046  }
1047
1048  /**
1049   * Sets the read-only mode for this request.
1050   *
1051   * @param isReadOnly <code>true</code> if connection is read-only
1052   */

1053  public void setIsReadOnly(boolean isReadOnly)
1054  {
1055    this.isReadOnly = isReadOnly;
1056  }
1057
1058  /**
1059   * Returns the requiresConnectionPoolFlush value.
1060   *
1061   * @return Returns the requiresConnectionPoolFlush.
1062   */

1063  public boolean requiresConnectionPoolFlush()
1064  {
1065    return requiresConnectionPoolFlush;
1066  }
1067
1068  /**
1069   * Must the controller retrieve SQL warnings ?
1070   *
1071   * @return true if SQLWarnings have to be fetched
1072   */

1073  public boolean getRetrieveSQLWarnings()
1074  {
1075    return retrieveSQLWarnings;
1076  }
1077
1078  /**
1079   * Set the SQL Warnings retrieval property
1080   *
1081   * @param isRetrieveSQLWarnings true if the controller should get SQL warnings
1082   */

1083  public void setRetrieveSQLWarnings(boolean isRetrieveSQLWarnings)
1084  {
1085    retrieveSQLWarnings = isRetrieveSQLWarnings;
1086  }
1087
1088  //
1089
// Other methods and helpers
1090
//
1091

1092  /**
1093   * Add depending tables to the list of tables already contained in the
1094   * provided set. No recursivity here since this is primarily design for
1095   * foreign keys which cannot have circular references.
1096   *
1097   * @param schema the schema to use
1098   * @param lockedTables set of table names to add depending tables to
1099   */

1100  protected void addDependingTables(DatabaseSchema schema,
1101      SortedSet JavaDoc lockedTables)
1102  {
1103    if ((schema == null) || (lockedTables == null))
1104      return;
1105
1106    List JavaDoc tablesToAdd = null;
1107    for (Iterator JavaDoc iter = lockedTables.iterator(); iter.hasNext();)
1108    {
1109      String JavaDoc tableName = (String JavaDoc) iter.next();
1110
1111      // Find the depending tables for that table
1112
DatabaseTable table = schema.getTable(tableName, false);
1113      if (table == null)
1114        continue;
1115      ArrayList JavaDoc dependingTables = table.getDependingTables();
1116      if (dependingTables == null)
1117        continue;
1118
1119      // Add these tables to a temp list so that we don't have a concurrent
1120
// modification exception on writeLockedTables on which we iterate
1121
if (tablesToAdd == null)
1122        tablesToAdd = new ArrayList JavaDoc();
1123      tablesToAdd.addAll(dependingTables);
1124    }
1125    // Finally add all depending tables
1126
if (tablesToAdd != null)
1127      lockedTables.addAll(tablesToAdd);
1128  }
1129
1130  /**
1131   * Two requests are equal if they have the same unique id.
1132   *
1133   * @param other an object
1134   * @return a <code>boolean</code> value
1135   */

1136  public boolean equals(Object JavaDoc other)
1137  {
1138    if ((other == null) || !(other instanceof AbstractRequest))
1139      return false;
1140
1141    AbstractRequest r = (AbstractRequest) other;
1142    return id == r.getId();
1143  }
1144
1145  /**
1146   * @see java.lang.Object#hashCode()
1147   */

1148  public int hashCode()
1149  {
1150    return (int) id;
1151  }
1152
1153  /**
1154   * If the query has a skeleton defined, return the skeleton with all carriage
1155   * returns and tabs replaced with spaces. If no SQL skeleton is defined, we
1156   * perform the same processing on the instanciated SQL statement.
1157   * <p>
1158   * Note that if no modification has to be done, the original string is
1159   * returned else a new string is constructed with the replaced elements.
1160   *
1161   * @return statement with CR replaced by spaces
1162   */

1163  public String JavaDoc trimCarriageReturnAndTabs()
1164  {
1165    return replaceStringWithSpace(replaceStringWithSpace(sqlQueryOrTemplate,
1166        this.getLineSeparator()), "\t");
1167  }
1168
1169  /**
1170   * Replaces any given <code>String</code> by a space in a given
1171   * <code>String</code>.
1172   *
1173   * @param s the <code>String</code> to transform
1174   * @param toReplace the <code>String</code> to replace with spaces
1175   * @return the transformed <code>String</code>
1176   */

1177  private String JavaDoc replaceStringWithSpace(String JavaDoc s, String JavaDoc toReplace)
1178  {
1179    return s.replaceAll(toReplace, " ");
1180  }
1181
1182  /**
1183   * @see java.lang.Object#toString()
1184   */

1185  public String JavaDoc toString()
1186  {
1187    return getUniqueKey();
1188  }
1189
1190  /**
1191   * Same as toString but use a short form limited to the number of character
1192   * provided.
1193   *
1194   * @param nbOfCharacters maximum number of characters to display (does not
1195   * apply to the skeleton)
1196   * @return a String representation of the request
1197   * @see java.lang.Object#toString()
1198   */

1199  public String JavaDoc toStringShortForm(int nbOfCharacters)
1200  {
1201    return getSqlShortForm(nbOfCharacters);
1202  }
1203
1204  /**
1205   * Displays useful information for parsing debugging
1206   *
1207   * @return a string containing info about parsing results
1208   */

1209  public String JavaDoc getParsingResultsAsString()
1210  {
1211    StringBuffer JavaDoc sb = new StringBuffer JavaDoc(Translate.get("request.parsing.results"));
1212    sb.append(Translate.get("request.type", RequestType
1213        .getTypeAsString(requestType)));
1214    sb.append(Translate.get("request.unique.key", getUniqueKey()));
1215    if (writeLockedTables != null && writeLockedTables.size() > 0)
1216    {
1217      sb.append(Translate.get("request.locked.tables"));
1218      for (int i = 0; i < writeLockedTables.size(); i++)
1219      {
1220        sb.append(Translate.get("request.locked.table", writeLockedTables
1221            .toArray()[i]));
1222      }
1223    }
1224    return sb.toString();
1225  }
1226
1227  /**
1228   * Returns a <code>String</code> containing debug information about this
1229   * request.
1230   * <p>
1231   * Information displayed (one line per info): id, query, parameters (if any),
1232   * login, autocommit, transaction id, cacheable status, isolation level, start
1233   * time, end time, timeout in seconds, write locked tables, persistent
1234   * connection id, client ip address.
1235   *
1236   * @return a string containing:
1237   */

1238  public String JavaDoc toDebugString()
1239  {
1240    StringBuffer JavaDoc ret = new StringBuffer JavaDoc();
1241    ret.append("Request id: " + id);
1242    ret.append("\n query: " + sqlQueryOrTemplate);
1243    if (preparedStatementParameters != null)
1244      ret.append("\n parameters: " + preparedStatementParameters);
1245    ret.append("\n login: " + login);
1246    ret.append("\n autocommit: " + isAutoCommit);
1247    ret.append("\n transaction id: " + transactionId);
1248    ret.append("\n cacheable status: "
1249        + RequestType.getInformation(cacheable));
1250    ret.append("\n isolation level: "
1251        + TransactionIsolationLevelConverter.toString(transactionIsolation));
1252    ret.append("\n start time: " + startTime);
1253    ret.append("\n end time: " + endTime);
1254    ret.append("\n timeout in seconds: " + timeoutInSeconds);
1255    if (writeLockedTables != null && writeLockedTables.size() > 0)
1256    {
1257      ret.append("\n locked tables:");
1258      for (int i = 0; i < writeLockedTables.size(); i++)
1259      {
1260        ret.append("\n " + writeLockedTables.toArray()[i]);
1261      }
1262    }
1263    ret.append("\n persistent connection id: " + persistentConnectionId);
1264    ret.append("\n client ip address: " + clientIpAddress);
1265
1266    return ret.toString();
1267  }
1268
1269  /**
1270   * Displays some debugging information about this request.
1271   */

1272  public void debug()
1273  {
1274    System.out.println(toDebugString());
1275  }
1276
1277  /**
1278   * Returns a one line <code>String</code> containing debug information about
1279   * this request.
1280   * <p>
1281   * Information displayed: id, query, parameters (if any), transaction id,
1282   * persistent connection id.
1283   *
1284   * @return a string containing:
1285   */

1286  public String JavaDoc toShortDebugString()
1287  {
1288    StringBuffer JavaDoc ret = new StringBuffer JavaDoc();
1289    ret.append("Id=" + id);
1290    ret.append(", query=" + sqlQueryOrTemplate);
1291    if (preparedStatementParameters != null)
1292      ret.append(", params=" + preparedStatementParameters);
1293    ret.append(", transaction id=" + transactionId);
1294    ret.append(", persistent connection id=" + persistentConnectionId);
1295    return ret.toString();
1296  }
1297
1298}
1299
Popular Tags