KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > derby > impl > sql > execute > NoPutResultSetImpl


1 /*
2
3    Derby - Class org.apache.derby.impl.sql.execute.NoPutResultSetImpl
4
5    Licensed to the Apache Software Foundation (ASF) under one or more
6    contributor license agreements. See the NOTICE file distributed with
7    this work for additional information regarding copyright ownership.
8    The ASF licenses this file to you under the Apache License, Version 2.0
9    (the "License"); you may not use this file except in compliance with
10    the License. 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  */

21
22 package org.apache.derby.impl.sql.execute;
23
24 import org.apache.derby.iapi.reference.SQLState;
25
26 import org.apache.derby.iapi.services.io.FormatableBitSet;
27 import org.apache.derby.iapi.services.i18n.MessageService;
28
29 import org.apache.derby.iapi.services.loader.GeneratedMethod;
30
31 import org.apache.derby.iapi.services.sanity.SanityManager;
32
33 import org.apache.derby.iapi.error.StandardException;
34
35 import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
36 import org.apache.derby.iapi.sql.conn.StatementContext;
37
38 import org.apache.derby.iapi.sql.depend.DependencyManager;
39
40 import org.apache.derby.iapi.sql.execute.ExecPreparedStatement;
41 import org.apache.derby.iapi.sql.execute.ExecRow;
42 import org.apache.derby.iapi.sql.execute.ExecIndexRow;
43 import org.apache.derby.iapi.sql.execute.ExecutionContext;
44 import org.apache.derby.iapi.sql.execute.NoPutResultSet;
45 import org.apache.derby.iapi.sql.execute.ResultSetStatisticsFactory;
46 import org.apache.derby.iapi.sql.execute.TargetResultSet;
47
48 import org.apache.derby.iapi.sql.Activation;
49 import org.apache.derby.iapi.sql.ResultDescription;
50
51 import org.apache.derby.iapi.store.access.Qualifier;
52 import org.apache.derby.iapi.store.access.RowLocationRetRowSource;
53 import org.apache.derby.iapi.store.access.RowSource;
54
55 import org.apache.derby.iapi.types.DataValueDescriptor;
56
57 import org.apache.derby.iapi.types.Orderable;
58 import org.apache.derby.iapi.types.RowLocation;
59
60 import java.sql.Timestamp JavaDoc;
61
62
63 /**
64  * Abstract ResultSet with built in Activation support for operations that
65  * return rows but do not allow the caller to put data on output pipes. This
66  * implementation of ResultSet is meant to be overridden by subtypes in the
67  * execution engine. Its primary users will be DML operations that do not put
68  * data on output pipes, but simply return it due to being result sets
69  * themselves.
70  * <p>
71  * This abstract class does not define the entire ResultSet
72  * interface, but leaves the 'get' half of the interface
73  * for subtypes to implement. It is package-visible only,
74  * with its methods being public for exposure by its subtypes.
75  * <p>
76  */

77 abstract class NoPutResultSetImpl
78 extends BasicNoPutResultSetImpl
79 {
80     /* Set in constructor and not modified */
81     public final int resultSetNumber;
82
83     /* fields used for formating run time statistics output */
84     protected String JavaDoc indent;
85     protected String JavaDoc subIndent;
86     protected int sourceDepth;
87
88     // fields used when being called as a RowSource
89
private boolean needsRowLocation;
90     protected ExecRow clonedExecRow;
91     GeneratedMethod checkGM;
92     long heapConglomerate;
93     protected TargetResultSet targetResultSet;
94
95     /* beetle 4464. compact flags into array of key column positions that we do check/skip nulls,
96      * so that we burn less cycles for each row, column.
97      */

98     protected int[] checkNullCols;
99     protected int cncLen;
100
101     /**
102      * Constructor
103      *
104      * @param activation The activation
105      * @param resultSetNumber The resultSetNumber
106      * @param optimizerEstimatedRowCount The optimizer's estimated number
107      * of rows.
108      * @param optimizerEstimatedCost The optimizer's estimated cost
109      */

110     NoPutResultSetImpl(Activation activation,
111                         int resultSetNumber,
112                         double optimizerEstimatedRowCount,
113                         double optimizerEstimatedCost)
114     {
115         super(null,
116                 activation,
117                 optimizerEstimatedRowCount,
118                 optimizerEstimatedCost);
119
120         if (SanityManager.DEBUG) {
121             SanityManager.ASSERT(activation!=null, "activation expected to be non-null");
122             SanityManager.ASSERT(resultSetNumber >= 0, "resultSetNumber expected to be >= 0");
123         }
124         this.resultSetNumber = resultSetNumber;
125     }
126
127     // NoPutResultSet interface
128

129     /**
130      * Returns the description of the table's rows
131      */

132     public ResultDescription getResultDescription() {
133         return activation.getResultDescription();
134     }
135
136     /**
137         Return my cursor name for JDBC. Can be null.
138     */

139     public String JavaDoc getCursorName() {
140
141         String JavaDoc cursorName = activation.getCursorName();
142         if ((cursorName == null) && isForUpdate()) {
143
144             activation.setCursorName(activation.getLanguageConnectionContext().getUniqueCursorName());
145
146             cursorName = activation.getCursorName();
147         }
148
149         return cursorName;
150     }
151
152     /** @see NoPutResultSet#resultSetNumber() */
153     public int resultSetNumber() {
154         return resultSetNumber;
155     }
156
157     /**
158         Close needs to invalidate any dependent statements, if this is a cursor.
159         Must be called by any subclasses that override close().
160         @exception StandardException on error
161     */

162     public void close() throws StandardException
163     {
164         if (!isOpen)
165             return;
166
167         /* If this is the top ResultSet then we must
168          * close all of the open subqueries for the
169          * entire query.
170          */

171         if (isTopResultSet)
172         {
173             int staLength = (subqueryTrackingArray == null) ? 0 :
174                                 subqueryTrackingArray.length;
175
176             for (int index = 0; index < staLength; index++)
177             {
178                 if (subqueryTrackingArray[index] == null)
179                 {
180                     continue;
181                 }
182                 if (subqueryTrackingArray[index].isClosed())
183                 {
184                     continue;
185                 }
186                 subqueryTrackingArray[index].close();
187             }
188         }
189
190         /*
191         ** If we are the activation's top result set, make it forget about
192         ** us, because we're closed now.
193         */

194         if (activation.getResultSet() == this)
195         {
196             activation.clearResultSet();
197         }
198
199         isOpen = false;
200
201     }
202
203     /** @see NoPutResultSet#setTargetResultSet */
204     public void setTargetResultSet(TargetResultSet trs)
205     {
206         targetResultSet = trs;
207     }
208
209     /** @see NoPutResultSet#setNeedsRowLocation */
210     public void setNeedsRowLocation(boolean needsRowLocation)
211     {
212         this.needsRowLocation = needsRowLocation;
213     }
214
215     // RowSource interface
216

217     /**
218      * @see RowSource#getValidColumns
219      */

220     public FormatableBitSet getValidColumns()
221     {
222         // All columns are valid
223
return null;
224     }
225     
226     /**
227      * @see RowSource#getNextRowFromRowSource
228      * @exception StandardException on error
229      */

230     public DataValueDescriptor[] getNextRowFromRowSource()
231         throws StandardException
232     {
233         ExecRow execRow = getNextRowCore();
234         if (execRow != null)
235         {
236             /* Let the target preprocess the row. For now, this
237              * means doing an in place clone on any indexed columns
238              * to optimize cloning and so that we don't try to drain
239              * a stream multiple times. This is where we also
240              * enforce any check constraints.
241              */

242             clonedExecRow = targetResultSet.preprocessSourceRow(execRow);
243
244             return execRow.getRowArray();
245         }
246
247         return null;
248     }
249
250     /**
251      * @see RowSource#needsToClone
252      */

253     public boolean needsToClone()
254     {
255         return(true);
256     }
257
258     /**
259      * @see RowSource#closeRowSource
260      */

261     public void closeRowSource()
262     {
263         // Do nothing here - actual work will be done in close()
264
}
265
266
267     // RowLocationRetRowSource interface
268

269     /**
270      * @see RowLocationRetRowSource#needsRowLocation
271      */

272     public boolean needsRowLocation()
273     {
274         return needsRowLocation;
275     }
276
277     /**
278      * @see RowLocationRetRowSource#rowLocation
279      * @exception StandardException on error
280      */

281     public void rowLocation(RowLocation rl)
282         throws StandardException
283     {
284         targetResultSet.changedRow(clonedExecRow, rl);
285     }
286
287
288     // class implementation
289

290     /**
291      * Clear the Orderable cache for each qualifier.
292      * (This should be done each time a scan/conglomerate with
293      * qualifiers is reopened.)
294      *
295      * @param qualifiers The Qualifiers to clear
296      */

297     protected void clearOrderableCache(Qualifier[][] qualifiers) throws StandardException
298     {
299         // Clear the Qualifiers's Orderable cache
300
if (qualifiers != null)
301         {
302             Qualifier qual;
303             for (int term = 0; term < qualifiers.length; term++)
304             {
305                 for (int index = 0; index < qualifiers[term].length; index++)
306                 {
307                     qual = qualifiers[term][index];
308                     qual.clearOrderableCache();
309                     /* beetle 4880 performance enhancement and avoid deadlock while pushing
310                      * down method call to store: pre-evaluate.
311                      */

312                     if (((GenericQualifier) qual).variantType != Qualifier.VARIANT)
313                         qual.getOrderable(); // ignore return value
314
}
315             }
316         }
317     }
318
319     /* Support methods for RowSource interface.
320      * These methods are used for enabling check constraint enforcement and
321      * replication logging for published tables when we are a RowSource.
322      */

323
324     /**
325      * Set the GeneratedMethod for enforcing check constraints
326      *
327      * @param checkGM The GeneratedMethod for enforcing any check constraints.
328      */

329     protected void setCheckConstraints(GeneratedMethod checkGM)
330     {
331         this.checkGM = checkGM;
332     }
333
334     /**
335      * Set the heap conglomerate number (used in enforcing check constraints)
336      *
337      * @param heapConglomerate The heap conglomerate number.
338      */

339     protected void setHeapConglomerate(long heapConglomerate)
340     {
341         this.heapConglomerate = heapConglomerate;
342     }
343
344     /**
345      * Set the current row to the row passed in.
346      *
347      * @param row the new current row
348      *
349      */

350     public final void setCurrentRow(ExecRow row)
351     {
352         activation.setCurrentRow(row, resultSetNumber);
353         currentRow = row;
354     }
355
356     /**
357      * Clear the current row
358      *
359      */

360     public final void clearCurrentRow()
361     {
362         currentRow = null;
363         activation.clearCurrentRow(resultSetNumber);
364     }
365
366     /**
367      * Is this ResultSet or it's source result set for update
368      * This method will be overriden in the inherited Classes
369      * if it is true
370      * @return Whether or not the result set is for update.
371      */

372     public boolean isForUpdate()
373     {
374         return false;
375     }
376
377     /**
378      * Return true if we should skip the scan due to nulls in the start
379      * or stop position when the predicate on the column(s) in question
380      * do not implement ordered null semantics. beetle 4464, we also compact
381      * the areNullsOrdered flags into checkNullCols here.
382      *
383      * @param startPosition An index row for the start position
384      * @param stopPosition An index row for the stop position
385      *
386      * @return true means not to do the scan
387      */

388     protected boolean skipScan(ExecIndexRow startPosition, ExecIndexRow stopPosition)
389         throws StandardException
390     {
391         int nStartCols = (startPosition == null) ? 0 : startPosition.nColumns();
392         int nStopCols = (stopPosition == null) ? 0 : stopPosition.nColumns();
393
394         /* Two facts 1) for start and stop key column positions, one has to be the prefix
395          * of the other, 2) startPosition.areNullsOrdered(i) can't be different from
396          * stopPosition.areNullsOrdered(i) unless the case "c > null and c < 5", (where c is
397          * non-nullable), in which we skip the scan anyway.
398          * So we can just use the longer one to get checkNullCols.
399          */

400         boolean startKeyLonger = false;
401         int size = nStopCols;
402         if (nStartCols > nStopCols)
403         {
404             startKeyLonger = true;
405             size = nStartCols;
406         }
407         if (size == 0)
408             return false;
409         if ((checkNullCols == null) || (checkNullCols.length < size))
410             checkNullCols = new int[size];
411         cncLen = 0;
412
413         boolean returnValue = false;
414         for (int position = 0; position < nStartCols; position++)
415         {
416             if ( ! startPosition.areNullsOrdered(position))
417             {
418                 if (startKeyLonger)
419                     checkNullCols[cncLen++] = position + 1;
420                 if (startPosition.getColumn(position + 1).isNull())
421                 {
422                     returnValue = true;
423                     if (! startKeyLonger)
424                         break;
425                 }
426             }
427         }
428         if (startKeyLonger && returnValue)
429             return true;
430         for (int position = 0; position < nStopCols; position++)
431         {
432             if ( ! stopPosition.areNullsOrdered(position))
433             {
434                 if (! startKeyLonger)
435                     checkNullCols[cncLen++] = position + 1;
436                 if (returnValue)
437                     continue;
438                 if (stopPosition.getColumn(position + 1).isNull())
439                 {
440                     returnValue = true;
441                     if (startKeyLonger)
442                         break;
443                 }
444             }
445         }
446
447         return returnValue;
448     }
449
450     /**
451      * Return true if we should skip the scan due to nulls in the row
452      * when the start or stop positioners on the columns containing
453      * null do not implement ordered null semantics.
454      *
455      * @param row An index row
456      *
457      * @return true means skip the row because it has null
458      */

459     protected boolean skipRow(ExecRow row) throws StandardException
460     {
461         for (int i = 0; i < cncLen; i++)
462         {
463             if (row.getColumn(checkNullCols[i]).isNull())
464                 return true;
465         }
466
467         return false;
468     }
469
470     /**
471      * Return a 2-d array of Qualifiers as a String
472      */

473     public static String JavaDoc printQualifiers(Qualifier[][] qualifiers)
474     {
475         String JavaDoc idt = "";
476
477         String JavaDoc output = "";
478         if (qualifiers == null)
479         {
480             return idt + MessageService.getTextMessage(SQLState.LANG_NONE);
481         }
482
483         for (int term = 0; term < qualifiers.length; term++)
484         {
485             for (int i = 0; i < qualifiers[term].length; i++)
486             {
487                 Qualifier qual = qualifiers[term][i];
488
489                 output = idt + output +
490                     MessageService.getTextMessage(
491                         SQLState.LANG_COLUMN_ID_ARRAY,
492                             String.valueOf(term), String.valueOf(i)) +
493                         ": " + qual.getColumnId() + "\n";
494                     
495                 int operator = qual.getOperator();
496                 String JavaDoc opString = null;
497                 switch (operator)
498                 {
499                   case Orderable.ORDER_OP_EQUALS:
500                     opString = "=";
501                     break;
502
503                   case Orderable.ORDER_OP_LESSOREQUALS:
504                     opString = "<=";
505                     break;
506
507                   case Orderable.ORDER_OP_LESSTHAN:
508                     opString = "<";
509                     break;
510
511                   default:
512                     if (SanityManager.DEBUG)
513                     {
514                         SanityManager.THROWASSERT("Unknown operator " + operator);
515                     }
516
517                     // NOTE: This does not have to be internationalized, because
518
// this code should never be reached.
519
opString = "unknown value (" + operator + ")";
520                     break;
521                 }
522                 output = output +
523                     idt + MessageService.getTextMessage(SQLState.LANG_OPERATOR) +
524                             ": " + opString + "\n" +
525                     idt +
526                         MessageService.getTextMessage(
527                             SQLState.LANG_ORDERED_NULLS) +
528                         ": " + qual.getOrderedNulls() + "\n" +
529                     idt +
530                         MessageService.getTextMessage(
531                             SQLState.LANG_UNKNOWN_RETURN_VALUE) +
532                         ": " + qual.getUnknownRV() + "\n" +
533                     idt +
534                         MessageService.getTextMessage(
535                             SQLState.LANG_NEGATE_COMPARISON_RESULT) +
536                         ": " + qual.negateCompareResult() + "\n";
537             }
538         }
539
540         return output;
541     }
542
543     /**
544      * @see NoPutResultSet#updateRow
545      *
546      * This method is result sets used for scroll insensitive updatable
547      * result sets for other result set it is a no-op.
548      */

549     public void updateRow(ExecRow row) throws StandardException {
550         // Only ResultSets of type Scroll Insensitive implement
551
// detectability, so for other result sets this method
552
// is a no-op
553
}
554
555     /**
556      * @see NoPutResultSet#markRowAsDeleted
557      *
558      * This method is result sets used for scroll insensitive updatable
559      * result sets for other result set it is a no-op.
560      */

561     public void markRowAsDeleted() throws StandardException {
562         // Only ResultSets of type Scroll Insensitive implement
563
// detectability, so for other result sets this method
564
// is a no-op
565
}
566
567     /**
568      * @see NoPutResultSet#positionScanAtRowLocation
569      *
570      * This method is result sets used for scroll insensitive updatable
571      * result sets for other result set it is a no-op.
572      */

573     public void positionScanAtRowLocation(RowLocation rl)
574         throws StandardException
575     {
576         // Only ResultSets of type Scroll Insensitive implement
577
// detectability, so for other result sets this method
578
// is a no-op
579
}
580
581
582 }
583
Popular Tags