KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > cjdbc > common > sql > AbstractRequest


1 /**
2  * C-JDBC: Clustered JDBC.
3  * Copyright (C) 2002-2005 French National Institute For Research In Computer
4  * Science And Control (INRIA).
5  * Contact: c-jdbc@objectweb.org
6  *
7  * This library is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU Lesser General Public License as published by the
9  * Free Software Foundation; either version 2.1 of the License, or any later
10  * version.
11  *
12  * This library is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
15  * for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public License
18  * along with this library; if not, write to the Free Software Foundation,
19  * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
20  *
21  * Initial developer(s): Emmanuel Cecchet.
22  * Contributor(s): Julie Marguerite, Mathieu Peltier, Marc Herbert
23  */

24
25 package org.objectweb.cjdbc.common.sql;
26
27 import java.io.IOException JavaDoc;
28 import java.io.Serializable JavaDoc;
29 import java.sql.SQLException JavaDoc;
30
31 import org.objectweb.cjdbc.common.sql.schema.DatabaseSchema;
32 import org.objectweb.cjdbc.common.stream.CJDBCInputStream;
33 import org.objectweb.cjdbc.common.stream.CJDBCOutputStream;
34
35 /**
36  * An <code>AbstractRequest</code> defines the skeleton of an SQL request.
37  * Requests have to be serializable (at least) for inter-controller
38  * communications.
39  *
40  * @author <a HREF="mailto:Emmanuel.Cecchet@inria.fr">Emmanuel Cecchet </a>
41  * @author <a HREF="mailto:Julie.Marguerite@inria.fr">Julie Marguerite </a>
42  * @author <a HREF="mailto:Mathieu.Peltier@inrialpes.fr">Mathieu Peltier </a>
43  * @author <a HREF="mailto:Marc.Herbert@emicnetworks.com">Marc Herbert </a>
44  * @version 1.0
45  */

46 public abstract class AbstractRequest implements Serializable JavaDoc
47 {
48   //
49
// This object is currently (de-)serialized in two different ways:
50
// - inter-controller commmunication uses java serialization (writeObject)
51
// since it is convenient, terse and reliable.
52
// - driver communication uses the manual serialization below, for
53
// compatibility with C
54
//
55
// Ideally:
56
// (1) unneeded fields for Java-Java communication are all tagged as
57
// "transient"
58
// (2) C-Java and Java-Java need to send the exact same fields.
59
// And so:
60
// (3) keeping up-to-date manual serialization methods below is easy: just
61
// check
62
// "transient" tags.
63

64   /*
65    * "In theory, practice and theory are the same, but in practice they are
66    * different" (Larry McVoy).
67    */

68   /*
69    * TODO: tag as "transient" fields that should be. And then TODO: if any, spot
70    * each exception to (3), that is: spot each non-transient field that we don't
71    * need for driver-controller com, and document why.
72    */

73
74   /** @see RequestType */
75   int requestType = RequestType.UNDEFINED;
76
77   /** Request unique id (set by the controller). */
78   protected transient long id;
79
80   /** SQL query (should be set in constructor). */
81   protected String JavaDoc sqlQuery;
82
83   /** SQL query skeleton as it appears in PreparedStatements. */
84   protected String JavaDoc sqlSkeleton = null;
85
86   /**
87    * Login used to issue this request (must be set by the
88    * VirtualDatabaseWorkerThread).
89    */

90   protected String JavaDoc login;
91
92   /** Whether this request is cacheable or not. */
93   protected int cacheable = RequestType.UNCACHEABLE;
94
95   /** Whether the SQL content has been parsed or not. */
96   protected boolean isParsed = false;
97
98   /*
99    * ResultSet Parameters
100    */

101   int maxRows;
102   int fetchSize;
103   String JavaDoc cursorName;
104
105   //
106
// Connection related parameters
107
//
108

109   /** True if the connection has been set to read-only */
110   protected boolean isReadOnly = false;
111
112   /**
113    * Whether this request has been sent in <code>autocommit</code> mode or
114    * not.
115    */

116   protected boolean isAutoCommit;
117
118   /**
119    * Transaction identifier if this request belongs to a transaction. The value
120    * is set by the VirtualDatabaseWorkerThread.
121    */

122   protected long transactionId;
123
124   /**
125    * Transaction isolation level to use when executing the query inside a
126    * transaction. The value is set by the VirtualDatabaseWorkerThread.
127    */

128   protected int transactionIsolation;
129
130   /**
131    * Timeout for this request in seconds, value 0 means no timeout (should be
132    * set in constructor). This timeout is in seconds, reflecting the jdbc-spec,
133    * and is passed as-is to the backends jdbc-driver. Internally converted to ms
134    * via getTimeoutMs().
135    */

136   protected int timeoutInSeconds;
137
138   /**
139    * Should the backend driver do escape processing before sending to the
140    * database? Simply forwarded to backend driver. No setter for this member,
141    * should be set in constructor.
142    *
143    * @see java.sql.Statement#setEscapeProcessing(boolean)
144    */

145   protected boolean escapeProcessing = true;
146
147   /**
148    * Set and sent by the driver to the controller. Required for parsing the
149    * request.
150    */

151   private String JavaDoc lineSeparator = null;
152
153   /**
154    * If set to true, this query is/was interpreted on the driver side, if false
155    * the various parameters are encoded and passed as is to the database native
156    * driver by the controller. Look for "proxy mode" in the documentation.
157    */

158   private boolean driverProcessed = true;
159
160   /**
161    * Default constructor Creates a new <code>AbstractRequest</code> object
162    *
163    * @param sqlQuery the SQL query
164    * @param escapeProcessing should the driver to escape processing before
165    * sending to the database ?
166    * @param timeout an <code>int</code> value
167    * @param lineSeparator the line separator used in the query
168    * @param requestType the request type as defined in RequestType class
169    * @see RequestType
170    */

171   public AbstractRequest(String JavaDoc sqlQuery, boolean escapeProcessing,
172       int timeout, String JavaDoc lineSeparator, int requestType)
173   {
174     this.sqlQuery = sqlQuery;
175     this.escapeProcessing = escapeProcessing;
176     this.timeoutInSeconds = timeout;
177     this.lineSeparator = lineSeparator;
178     this.requestType = requestType;
179   }
180
181   /**
182    * Creates a new <code>AbstractRequest</code> object, deserializing it from
183    * an input stream. Has to mirror the serialization method below.
184    *
185    * @param in the input stream to read from
186    * @param requestType the request type as defined in RequestType class
187    * @throws IOException if a network error occurs
188    * @see RequestType
189    */

190
191   public AbstractRequest(CJDBCInputStream in, int requestType)
192       throws IOException JavaDoc
193   {
194     this.sqlQuery = in.readUTF();
195     this.escapeProcessing = in.readBoolean();
196     this.lineSeparator = in.readUTF();
197     this.timeoutInSeconds = in.readInt();
198
199     this.isAutoCommit = in.readBoolean();
200     this.driverProcessed = in.readBoolean();
201
202     // Does this request has a template with question marks "?"
203
// true for PreparedStatements
204
// (AND did we ask for them at connection time?)
205
if (in.readBoolean())
206       this.sqlSkeleton = in.readUTF();
207     
208     // success, we received it all
209

210     this.requestType = requestType;
211   }
212
213   /**
214    * Serialize the request on the output stream by sending only the needed
215    * parameters to reconstruct it on the controller. Has to mirror the
216    * deserialization method above.
217    *
218    * @param out destination CJDBCOutputStream
219    * @param controllerWantsSqlSkeleton true if controller wants SQL templates
220    * @throws IOException if fails
221    */

222
223   public void sendToStream(CJDBCOutputStream out,
224       boolean controllerWantsSqlSkeleton) throws IOException JavaDoc
225   {
226     out.writeUTF(sqlQuery);
227     out.writeBoolean(escapeProcessing);
228     out.writeUTF(lineSeparator);
229     out.writeInt(timeoutInSeconds);
230
231     out.writeBoolean(isAutoCommit);
232     out.writeBoolean(driverProcessed);
233
234     // If Statements are not processed by the driver, the controller
235
// will need the skeleton.
236
if ((controllerWantsSqlSkeleton || !isDriverProcessed())
237         && sqlSkeleton != null)
238     {
239       out.writeBoolean(true);
240       out.writeUTF(sqlSkeleton);
241     }
242     else
243       out.writeBoolean(false);
244
245   }
246
247   /**
248    * Also fetch ResultSet parameters from the stream. Optionally used by
249    * deserializers of those derived requests that expect a ResultSet.
250    *
251    * @param in input stream
252    * @throws IOException stream error
253    */

254   void receiveResultSetParams(CJDBCInputStream in) throws IOException JavaDoc
255   {
256     this.maxRows = in.readInt();
257     this.fetchSize = in.readInt();
258
259     if (in.readBoolean()) // do we have a cursor name ?
260
this.cursorName = in.readUTF();
261   }
262
263   /**
264    * Also serialize ResultSet parameters to the stream. Optionally used by
265    * serializers of those derived requests that expect a ResultSet.
266    *
267    * @param out output stream
268    * @throws IOException stream error
269    */

270   void sendResultSetParams(CJDBCOutputStream out) throws IOException JavaDoc
271   {
272     out.writeInt(maxRows);
273     out.writeInt(fetchSize);
274
275     if (this.cursorName != null) // do we have a cursor name ?
276
{
277       out.writeBoolean(true);
278       out.writeUTF(cursorName);
279     }
280     else
281       out.writeBoolean(false);
282   }
283
284   /**
285    * Returns <code>true</code> if this request requires macro (RAND(), NOW(),
286    * ...) processing.
287    *
288    * @return <code>true</code> if macro processing is required
289    * @see org.objectweb.cjdbc.controller.loadbalancer.AbstractLoadBalancer#handleMacros(AbstractRequest)
290    */

291   public abstract boolean needsMacroProcessing();
292
293   /**
294    * Does this request returns a ResultSet?
295    *
296    * @return true is this request will return a ResultSet
297    */

298   public abstract boolean returnsResultSet();
299
300   /**
301    * Returns <code>true</code> if this request in a <code>ALTER</code>
302    * statement.
303    *
304    * @return a <code>boolean</code> value
305    */

306   public final boolean isAlter()
307   {
308     return RequestType.isAlter(this.requestType);
309   }
310
311   /**
312    * Returns <code>true</code> if this request in a <code>CREATE</code>
313    * statement.
314    *
315    * @return a <code>boolean</code> value
316    */

317   public final boolean isCreate()
318   {
319     return RequestType.isCreate(this.requestType);
320   }
321
322   /**
323    * Returns <code>true</code> if this request in a <code>DELETE</code>
324    * statement.
325    *
326    * @return a <code>boolean</code> value
327    */

328   public final boolean isDelete()
329   {
330     return RequestType.isDelete(this.requestType);
331   }
332
333   /**
334    * Returns <code>true</code> if this request is a DDL (Data Definition
335    * Language) statement such as CREATE, ALTER or DROP. Not supported yet are:
336    * TRUNCATE, COMMENT, GRANT and REVOKE (see
337    * http://www.orafaq.com/faq/Server_Utilities/SQL/faq53.htm)
338    * <p>
339    * Note that stored procedures are both considered as DDL and DML as they can
340    * include both.
341    *
342    * @return true if this request is a DDL
343    */

344   public final boolean isDDL()
345   {
346     return RequestType.isDDL(this.requestType);
347   }
348
349   /**
350    * Returns <code>true</code> if this request is a DML (Data Manipulation
351    * Language) statement such SELECT, INSERT, UPDATE or DELETE (see
352    * http://www.orafaq.com/faq/Server_Utilities/SQL/faq53.htm)
353    * <p>
354    * Note that stored procedures are both considered as DDL and DML as they can
355    * include both.
356    *
357    * @return true if this request is a DDL
358    */

359   public final boolean isDML()
360   {
361     return RequestType.isDML(this.requestType);
362   }
363
364   /**
365    * Returns <code>true</code> if this request in a <code>DROP</code>
366    * statement.
367    *
368    * @return a <code>boolean</code> value
369    */

370   public final boolean isDrop()
371   {
372     return RequestType.isDrop(this.requestType);
373   }
374
375   /**
376    * Returns <code>true</code> if this request in an <code>INSERT</code>
377    * statement.
378    *
379    * @return a <code>boolean</code> value
380    */

381   public final boolean isInsert()
382   {
383     return RequestType.isInsert(this.requestType);
384   }
385
386   /**
387    * Returns <code>true</code> if the request SQL content has been already
388    * parsed.
389    *
390    * @return a <code>boolean</code> value
391    */

392   public boolean isParsed()
393   {
394     return isParsed;
395   }
396
397   /**
398    * Returns <code>true</code> if the connection is set to read-only
399    *
400    * @return a <code>boolean</code> value
401    */

402   public boolean isReadOnly()
403   {
404     return isReadOnly;
405   }
406
407   /**
408    * Returns <code>true</code> if this request in a <code>SELECT</code>
409    * statement.
410    *
411    * @return a <code>boolean</code> value
412    */

413   public final boolean isSelect()
414   {
415     return RequestType.isSelect(this.requestType);
416   }
417
418   /**
419    * Returns <code>true</code> if this request in an <code>UPDATE</code>
420    * statement.
421    *
422    * @return a <code>boolean</code> value
423    */

424   public final boolean isUpdate()
425   {
426     return RequestType.isUpdate(this.requestType);
427   }
428
429   /**
430    * Sets the read-only mode for this request.
431    *
432    * @param isReadOnly <code>true</code> if connection is read-only
433    */

434   public void setIsReadOnly(boolean isReadOnly)
435   {
436     this.isReadOnly = isReadOnly;
437   }
438
439   /**
440    * Returns the cacheable status of this request. It can be:
441    * {@link org.objectweb.cjdbc.common.sql.RequestType#CACHEABLE},
442    * {@link org.objectweb.cjdbc.common.sql.RequestType#UNCACHEABLE}or
443    * {@link org.objectweb.cjdbc.common.sql.RequestType#UNIQUE_CACHEABLE}
444    *
445    * @return a <code>int</code> value
446    */

447   public int getCacheAbility()
448   {
449     return cacheable;
450   }
451
452   /**
453    * Set the cacheable status of this request. It can be:
454    * {@link org.objectweb.cjdbc.common.sql.RequestType#CACHEABLE},
455    * {@link org.objectweb.cjdbc.common.sql.RequestType#UNCACHEABLE}or
456    * {@link org.objectweb.cjdbc.common.sql.RequestType#UNIQUE_CACHEABLE}
457    *
458    * @param cacheAbility a <code>int</code> value
459    */

460   public void setCacheAbility(int cacheAbility)
461   {
462     this.cacheable = cacheAbility;
463   }
464
465   /**
466    * Returns <code>true</code> if the driver should escape processing before
467    * sending to the database?
468    *
469    * @return a <code>boolean</code> value
470    */

471   public boolean getEscapeProcessing()
472   {
473     return escapeProcessing;
474   }
475
476   /**
477    * Returns the unique id of this request.
478    *
479    * @return the request id
480    */

481   public long getId()
482   {
483     return id;
484   }
485
486   /**
487    * Sets the unique id of this request.
488    *
489    * @param id the id to set
490    */

491   public void setId(long id)
492   {
493     this.id = id;
494   }
495
496   /**
497    * Returns <code>true</code> if the request should be executed in
498    * <code>autocommit</code> mode.
499    *
500    * @return a <code>boolean</code> value
501    */

502   public boolean isAutoCommit()
503   {
504     return isAutoCommit;
505   }
506
507   /**
508    * Sets the autocommit mode for this request.
509    *
510    * @param isAutoCommit <code>true</code> if <code>autocommit</code> should
511    * be used
512    */

513   public void setIsAutoCommit(boolean isAutoCommit)
514   {
515     this.isAutoCommit = isAutoCommit;
516   }
517
518   /**
519    * Returns the login used to issue this request.
520    *
521    * @return a <code>String</code> value
522    */

523   public String JavaDoc getLogin()
524   {
525     return login;
526   }
527
528   /**
529    * Returns the lineSeparator value.
530    *
531    * @return Returns the lineSeparator.
532    */

533   public String JavaDoc getLineSeparator()
534   {
535     return lineSeparator;
536   }
537
538   /**
539    * Sets the login to use to issue this request.
540    *
541    * @param login a <code>String</code> value
542    */

543   public void setLogin(String JavaDoc login)
544   {
545     this.login = login;
546   }
547
548   /**
549    * Gets the SQL code of this request.
550    *
551    * @return the SQL query
552    */

553   public String JavaDoc getSQL()
554   {
555     return sqlQuery;
556   }
557
558   /**
559    * Get a short form of this request if the SQL statement exceeds
560    * nbOfCharacters.
561    *
562    * @param nbOfCharacters number of characters to include in the short form.
563    * @return the nbOfCharacters first characters of the SQL statement
564    */

565   public String JavaDoc getSQLShortForm(int nbOfCharacters)
566   {
567     if ((nbOfCharacters == 0) || (sqlQuery.length() < nbOfCharacters))
568       return sqlQuery;
569     else
570       return sqlQuery.substring(0, nbOfCharacters) + "...";
571   }
572
573   /**
574    * Get the maximum number of rows the ResultSet can contain.
575    *
576    * @return maximum number of rows
577    * @see java.sql.Statement#getMaxRows()
578    */

579   public int getMaxRows()
580   {
581     return maxRows;
582   }
583
584   /**
585    * Set the maximum number of rows in the ResultSet. Used only by Statement.
586    *
587    * @param rows maximum number of rows
588    * @see java.sql.Statement#setMaxRows(int)
589    */

590   public void setMaxRows(int rows)
591   {
592     maxRows = rows;
593   }
594
595   /**
596    * Set the SQL code of this request. Warning! The request parsing validity is
597    * not checked. The caller has to recall
598    * {@link #parse(DatabaseSchema, int, boolean)}if needed.
599    *
600    * @param sql SQL statement
601    * @see org.objectweb.cjdbc.controller.loadbalancer.AbstractLoadBalancer#handleMacros(AbstractRequest)
602    */

603   public void setSQL(String JavaDoc sql)
604   {
605     this.sqlQuery = sql;
606   }
607
608   /**
609    * Gets the timeout for this request in seconds.
610    *
611    * @return timeout in seconds (0 means no timeout)
612    */

613   public int getTimeout()
614   {
615     return timeoutInSeconds;
616   }
617
618   /**
619    * Sets the new timeout in seconds for this request.
620    *
621    * @param timeout an <code>int</code> value
622    * @see org.objectweb.cjdbc.controller.scheduler
623    */

624   public void setTimeout(int timeout)
625   {
626     this.timeoutInSeconds = timeout;
627   }
628
629   /**
630    * Gets the identifier of the transaction if this request belongs to a
631    * transaction, or -1 if this request does not belong to a transaction.
632    *
633    * @return transaction identifier or -1
634    */

635   public long getTransactionId()
636   {
637     return transactionId;
638   }
639
640   /**
641    * Sets the transaction identifier this request belongs to.
642    *
643    * @param id transaction id
644    */

645   public void setTransactionId(long id)
646   {
647     transactionId = id;
648   }
649
650   /**
651    * Two requests are equal if they have the same SQL statement, transaction id
652    * and login.
653    *
654    * @param other an object
655    * @return a <code>boolean</code> value
656    */

657   public boolean equals(Object JavaDoc other)
658   {
659     if ((other == null) || !(other instanceof AbstractRequest))
660       return false;
661
662     AbstractRequest r = (AbstractRequest) other;
663     return id == r.getId();
664   }
665
666   /**
667    * Parses the SQL request and extract the selected columns and tables given
668    * the <code>DatabaseSchema</code> of the database targeted by this request.
669    * <p>
670    * An exception is thrown when the parsing fails. Warning, this method does
671    * not check the validity of the request. In particular, invalid request could
672    * be parsed without throwing an exception. However, valid SQL request should
673    * never throw an exception.
674    *
675    * @param schema a <code>DatabaseSchema</code> value
676    * @param granularity parsing granularity as defined in
677    * <code>ParsingGranularities</code>
678    * @param isCaseSensitive true if parsing must be case sensitive
679    * @exception SQLException if the parsing fails
680    */

681   public abstract void parse(DatabaseSchema schema, int granularity,
682       boolean isCaseSensitive) throws SQLException JavaDoc;
683
684   /**
685    * Clones the parsing of a request.
686    *
687    * @param request the parsed request to clone
688    */

689   public abstract void cloneParsing(AbstractRequest request);
690
691   /**
692    * If the query has a skeleton defined, return the skeleton with all carriage
693    * returns and tabs replaced with spaces. If no SQL skeleton is defined, we
694    * perform the same processing on the instanciated SQL statement.
695    * <p>
696    * Note that if no modification has to be done, the original string is
697    * returned else a new string is constructed with the replaced elements.
698    *
699    * @return statement with CR replaced by spaces
700    */

701   public String JavaDoc trimCarriageReturnAndTabs()
702   {
703     if (sqlSkeleton != null)
704       return replaceStringWithSpace(replaceStringWithSpace(sqlSkeleton,
705           lineSeparator), "\t");
706     else
707       return replaceStringWithSpace(replaceStringWithSpace(sqlQuery,
708           lineSeparator), "\t");
709   }
710
711   /**
712    * Replaces any given <code>String</code> by a space in a given
713    * <code>String</code>.
714    *
715    * @param s the <code>String</code> to transform
716    * @param toReplace the <code>String</code> to replace with spaces
717    * @return the transformed <code>String</code>
718    */

719   private String JavaDoc replaceStringWithSpace(String JavaDoc s, String JavaDoc toReplace)
720   {
721     int toReplaceLength = toReplace.length();
722     int idx = s.indexOf(toReplace);
723     if (idx == -1)
724       return s;
725     else
726     {
727       if (idx == 0)
728         // is the first character
729
return replaceStringWithSpace(s.substring(toReplaceLength), toReplace);
730       else if (idx == (s.length() - toReplaceLength))
731         // is the last character
732
return s.substring(0, s.length() - toReplaceLength);
733       else
734         // is somewhere in the string
735
return s.substring(0, idx)
736             + " "
737             + replaceStringWithSpace(s.substring(idx + toReplaceLength),
738                 toReplace);
739     }
740   }
741
742   /**
743    * @return the SQL query skeleton given in a <code>PreparedStatement</code>.
744    */

745   public String JavaDoc getSqlSkeleton()
746   {
747     return sqlSkeleton;
748   }
749
750   /**
751    * @param skel set the SQL query skeleton given in a
752    * <code>PreparedStatement</code>.
753    */

754   public void setSqlSkeleton(String JavaDoc skel)
755   {
756     sqlSkeleton = skel;
757   }
758
759   /**
760    * Returns the driverProcessed value.
761    *
762    * @return Returns the driverProcessed.
763    */

764   public boolean isDriverProcessed()
765   {
766     return driverProcessed;
767   }
768
769   /**
770    * Sets the driverProcessed value.
771    *
772    * @param driverProcessed The driverProcessed to set.
773    */

774   public void setDriverProcessed(boolean driverProcessed)
775   {
776     this.driverProcessed = driverProcessed;
777   }
778
779   /**
780    * Sets the fetchSize value.
781    *
782    * @param fetchSize The fetchSize to set.
783    * @see org.objectweb.cjdbc.driver.Statement
784    */

785   public void setFetchSize(int fetchSize)
786   {
787     this.fetchSize = fetchSize;
788   }
789
790   /**
791    * Returns the fetchSize value.
792    *
793    * @return Returns the fetchSize.
794    */

795   public int getFetchSize()
796   {
797     return fetchSize;
798   }
799
800   /**
801    * Returns the transaction isolation level.
802    *
803    * @return Returns the transaction isolation.
804    */

805   public int getTransactionIsolation()
806   {
807     return transactionIsolation;
808   }
809
810   /**
811    * Sets the transaction isolation level that must be used to execute this
812    * request
813    *
814    * @param isolationLevel the transaction isolation level
815    */

816   public void setTransactionIsolation(int isolationLevel)
817   {
818     this.transactionIsolation = isolationLevel;
819   }
820
821   /**
822    * Returns the cursorName value.
823    *
824    * @return Returns the cursorName.
825    */

826   public String JavaDoc getCursorName()
827   {
828     return cursorName;
829   }
830
831   /**
832    * Sets the cursorName value.
833    *
834    * @param cursorName The cursorName to set.
835    */

836   public void setCursorName(String JavaDoc cursorName)
837   {
838     this.cursorName = cursorName;
839   }
840
841   /**
842    * Displays some debugging information about this request.
843    */

844   public void debug()
845   {
846     System.out.println("Request: " + sqlQuery);
847     System.out.print("Cacheable status: ");
848     System.out.println(RequestType.getInformation(cacheable));
849   }
850
851 }
852
Popular Tags