001: /*
002:
003: Derby - Class org.apache.derby.impl.sql.execute.RealResultSetStatisticsFactory
004:
005: Licensed to the Apache Software Foundation (ASF) under one or more
006: contributor license agreements. See the NOTICE file distributed with
007: this work for additional information regarding copyright ownership.
008: The ASF licenses this file to you under the Apache License, Version 2.0
009: (the "License"); you may not use this file except in compliance with
010: the License. You may obtain a copy of the License at
011:
012: http://www.apache.org/licenses/LICENSE-2.0
013:
014: Unless required by applicable law or agreed to in writing, software
015: distributed under the License is distributed on an "AS IS" BASIS,
016: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: See the License for the specific language governing permissions and
018: limitations under the License.
019:
020: */
021:
022: package org.apache.derby.impl.sql.execute;
023:
024: import org.apache.derby.iapi.services.sanity.SanityManager;
025:
026: import org.apache.derby.iapi.services.io.FormatIdUtil;
027:
028: import org.apache.derby.iapi.error.StandardException;
029: import org.apache.derby.iapi.services.i18n.MessageService;
030:
031: import org.apache.derby.iapi.sql.Activation;
032: import org.apache.derby.iapi.sql.ResultSet;
033: import org.apache.derby.iapi.sql.PreparedStatement;
034:
035: import org.apache.derby.iapi.sql.execute.NoPutResultSet;
036: import org.apache.derby.iapi.sql.execute.ResultSetFactory;
037: import org.apache.derby.iapi.sql.execute.ResultSetStatisticsFactory;
038:
039: import org.apache.derby.iapi.store.access.TransactionController;
040:
041: import org.apache.derby.impl.sql.execute.AnyResultSet;
042: import org.apache.derby.impl.sql.execute.CurrentOfResultSet;
043: import org.apache.derby.impl.sql.execute.DeleteResultSet;
044: import org.apache.derby.impl.sql.execute.DeleteCascadeResultSet;
045: import org.apache.derby.impl.sql.execute.DeleteVTIResultSet;
046: import org.apache.derby.impl.sql.execute.DistinctScalarAggregateResultSet;
047: import org.apache.derby.impl.sql.execute.DistinctScanResultSet;
048: import org.apache.derby.impl.sql.execute.GroupedAggregateResultSet;
049: import org.apache.derby.impl.sql.execute.HashJoinResultSet;
050: import org.apache.derby.impl.sql.execute.HashLeftOuterJoinResultSet;
051: import org.apache.derby.impl.sql.execute.HashScanResultSet;
052: import org.apache.derby.impl.sql.execute.HashTableResultSet;
053: import org.apache.derby.impl.sql.execute.IndexRowToBaseRowResultSet;
054: import org.apache.derby.impl.sql.execute.InsertResultSet;
055: import org.apache.derby.impl.sql.execute.InsertVTIResultSet;
056: import org.apache.derby.impl.sql.execute.LastIndexKeyResultSet;
057: import org.apache.derby.impl.sql.execute.MaterializedResultSet;
058: import org.apache.derby.impl.sql.execute.NestedLoopJoinResultSet;
059: import org.apache.derby.impl.sql.execute.NestedLoopLeftOuterJoinResultSet;
060: import org.apache.derby.impl.sql.execute.NormalizeResultSet;
061: import org.apache.derby.impl.sql.execute.OnceResultSet;
062: import org.apache.derby.impl.sql.execute.ProjectRestrictResultSet;
063: import org.apache.derby.impl.sql.execute.RowResultSet;
064: import org.apache.derby.impl.sql.execute.ScalarAggregateResultSet;
065: import org.apache.derby.impl.sql.execute.ScrollInsensitiveResultSet;
066: import org.apache.derby.impl.sql.execute.SetOpResultSet;
067: import org.apache.derby.impl.sql.execute.SortResultSet;
068: import org.apache.derby.impl.sql.execute.TableScanResultSet;
069: import org.apache.derby.impl.sql.execute.UnionResultSet;
070: import org.apache.derby.impl.sql.execute.UpdateResultSet;
071: import org.apache.derby.impl.sql.execute.VTIResultSet;
072: import org.apache.derby.impl.sql.execute.DependentResultSet;
073:
074: import org.apache.derby.iapi.sql.execute.RunTimeStatistics;
075: import org.apache.derby.impl.sql.execute.rts.RealAnyResultSetStatistics;
076: import org.apache.derby.impl.sql.execute.rts.RealCurrentOfStatistics;
077: import org.apache.derby.impl.sql.execute.rts.RealDeleteResultSetStatistics;
078: import org.apache.derby.impl.sql.execute.rts.RealDeleteCascadeResultSetStatistics;
079: import org.apache.derby.impl.sql.execute.rts.RealDeleteVTIResultSetStatistics;
080: import org.apache.derby.impl.sql.execute.rts.RealDistinctScalarAggregateStatistics;
081: import org.apache.derby.impl.sql.execute.rts.RealDistinctScanStatistics;
082: import org.apache.derby.impl.sql.execute.rts.RealGroupedAggregateStatistics;
083: import org.apache.derby.impl.sql.execute.rts.RealHashJoinStatistics;
084: import org.apache.derby.impl.sql.execute.rts.RealHashLeftOuterJoinStatistics;
085: import org.apache.derby.impl.sql.execute.rts.RealHashScanStatistics;
086: import org.apache.derby.impl.sql.execute.rts.RealHashTableStatistics;
087: import org.apache.derby.impl.sql.execute.rts.RealIndexRowToBaseRowStatistics;
088: import org.apache.derby.impl.sql.execute.rts.RealInsertResultSetStatistics;
089: import org.apache.derby.impl.sql.execute.rts.RealInsertVTIResultSetStatistics;
090: import org.apache.derby.impl.sql.execute.rts.RealJoinResultSetStatistics;
091: import org.apache.derby.impl.sql.execute.rts.RealLastIndexKeyScanStatistics;
092: import org.apache.derby.impl.sql.execute.rts.RealMaterializedResultSetStatistics;
093: import org.apache.derby.impl.sql.execute.rts.RealNestedLoopJoinStatistics;
094: import org.apache.derby.impl.sql.execute.rts.RealNestedLoopLeftOuterJoinStatistics;
095: import org.apache.derby.impl.sql.execute.rts.RealNormalizeResultSetStatistics;
096: import org.apache.derby.impl.sql.execute.rts.RealOnceResultSetStatistics;
097: import org.apache.derby.impl.sql.execute.rts.RealProjectRestrictStatistics;
098: import org.apache.derby.impl.sql.execute.rts.RealRowResultSetStatistics;
099: import org.apache.derby.impl.sql.execute.rts.RealScalarAggregateStatistics;
100: import org.apache.derby.impl.sql.execute.rts.RealScrollInsensitiveResultSetStatistics;
101: import org.apache.derby.impl.sql.execute.rts.RealSetOpResultSetStatistics;
102: import org.apache.derby.impl.sql.execute.rts.RealSortStatistics;
103: import org.apache.derby.impl.sql.execute.rts.RealTableScanStatistics;
104: import org.apache.derby.impl.sql.execute.rts.RealUnionResultSetStatistics;
105: import org.apache.derby.impl.sql.execute.rts.RealUpdateResultSetStatistics;
106: import org.apache.derby.impl.sql.execute.rts.RealVTIStatistics;
107: import org.apache.derby.impl.sql.execute.rts.ResultSetStatistics;
108: import org.apache.derby.impl.sql.execute.rts.RunTimeStatisticsImpl;
109:
110: import org.apache.derby.iapi.reference.SQLState;
111:
112: import java.util.Properties;
113:
114: /**
115: * ResultSetStatisticsFactory provides a wrapper around all of
116: * objects associated with run time statistics.
117: * <p>
118: * This implementation of the protocol is for returning the "real"
119: * run time statistics. We have modularized this so that we could
120: * have an implementation that just returns null for each of the
121: * objects should we decided to provide a configuration without
122: * the run time statistics feature.
123: *
124: * @author jerry
125: */
126: public class RealResultSetStatisticsFactory implements
127: ResultSetStatisticsFactory {
128:
129: //
130: // ExecutionFactory interface
131: //
132: //
133: // ResultSetStatisticsFactory interface
134: //
135:
136: /**
137: @see ResultSetStatisticsFactory#getRunTimeStatistics
138: */
139: public RunTimeStatistics getRunTimeStatistics(
140: Activation activation, ResultSet rs,
141: NoPutResultSet[] subqueryTrackingArray)
142: throws StandardException {
143: PreparedStatement preStmt = activation.getPreparedStatement();
144:
145: // If the prepared statement is null then the result set is being
146: // finished as a result of a activation being closed during a recompile.
147: // In this case statistics should not be generated.
148: if (preStmt == null)
149: return null;
150:
151: ResultSetStatistics topResultSetStatistics;
152:
153: if (rs instanceof NoPutResultSet) {
154: topResultSetStatistics = getResultSetStatistics((NoPutResultSet) rs);
155: } else {
156: topResultSetStatistics = getResultSetStatistics(rs);
157: }
158:
159: /* Build up the info on the materialized subqueries */
160: int subqueryTrackingArrayLength = (subqueryTrackingArray == null) ? 0
161: : subqueryTrackingArray.length;
162: ResultSetStatistics[] subqueryRSS = new ResultSetStatistics[subqueryTrackingArrayLength];
163: boolean anyAttached = false;
164: for (int index = 0; index < subqueryTrackingArrayLength; index++) {
165: if (subqueryTrackingArray[index] != null
166: && subqueryTrackingArray[index]
167: .getPointOfAttachment() == -1) {
168: subqueryRSS[index] = getResultSetStatistics(subqueryTrackingArray[index]);
169: anyAttached = true;
170: }
171: }
172: if (anyAttached == false) {
173: subqueryRSS = null;
174: }
175:
176: // Get the info on all of the materialized subqueries (attachment point = -1)
177: return new RunTimeStatisticsImpl(preStmt.getSPSName(),
178: activation.getCursorName(), preStmt.getSource(),
179: preStmt.getCompileTimeInMillis(), preStmt
180: .getParseTimeInMillis(), preStmt
181: .getBindTimeInMillis(), preStmt
182: .getOptimizeTimeInMillis(), preStmt
183: .getGenerateTimeInMillis(),
184: rs.getExecuteTime(),
185: preStmt.getBeginCompileTimestamp(), preStmt
186: .getEndCompileTimestamp(), rs
187: .getBeginExecutionTimestamp(), rs
188: .getEndExecutionTimestamp(), subqueryRSS,
189: topResultSetStatistics);
190: }
191:
192: /**
193: @see ResultSetStatisticsFactory#getResultSetStatistics
194: */
195: public ResultSetStatistics getResultSetStatistics(ResultSet rs) {
196: if (!rs.returnsRows()) {
197: return getNoRowsResultSetStatistics(rs);
198: } else if (rs instanceof NoPutResultSet) {
199: return getResultSetStatistics((NoPutResultSet) rs);
200: } else {
201: return null;
202: }
203: }
204:
205: public ResultSetStatistics getNoRowsResultSetStatistics(ResultSet rs) {
206: ResultSetStatistics retval = null;
207:
208: /* We need to differentiate based on instanceof in order
209: * to find the right constructor to call. This is ugly,
210: * but if we don't do instanceof then rs is always seen as an
211: * interface instead of a class when we try to overload
212: * a method with both.
213: */
214: if (rs instanceof InsertResultSet) {
215: InsertResultSet irs = (InsertResultSet) rs;
216:
217: retval = new RealInsertResultSetStatistics(
218: irs.rowCount,
219: irs.constants.deferred,
220: irs.constants.irgs.length,
221: irs.userSpecifiedBulkInsert,
222: irs.bulkInsertPerformed,
223: irs.constants.lockMode == TransactionController.MODE_TABLE,
224: irs.getExecuteTime(),
225: getResultSetStatistics(irs.savedSource));
226:
227: irs.savedSource = null;
228: } else if (rs instanceof InsertVTIResultSet) {
229: InsertVTIResultSet iVTIrs = (InsertVTIResultSet) rs;
230:
231: retval = new RealInsertVTIResultSetStatistics(
232: iVTIrs.rowCount, iVTIrs.constants.deferred, iVTIrs
233: .getExecuteTime(),
234: getResultSetStatistics(iVTIrs.savedSource));
235:
236: iVTIrs.savedSource = null;
237: } else if (rs instanceof UpdateResultSet) {
238: UpdateResultSet urs = (UpdateResultSet) rs;
239:
240: retval = new RealUpdateResultSetStatistics(
241: urs.rowCount,
242: urs.constants.deferred,
243: urs.constants.irgs.length,
244: urs.constants.lockMode == TransactionController.MODE_TABLE,
245: urs.getExecuteTime(),
246: getResultSetStatistics(urs.savedSource));
247:
248: urs.savedSource = null;
249: } else if (rs instanceof DeleteCascadeResultSet) {
250: DeleteCascadeResultSet dcrs = (DeleteCascadeResultSet) rs;
251: int dependentTrackingArrayLength = (dcrs.dependentResultSets == null) ? 0
252: : dcrs.dependentResultSets.length;
253: ResultSetStatistics[] dependentTrackingArray = new ResultSetStatistics[dependentTrackingArrayLength];
254: boolean anyAttached = false;
255: for (int index = 0; index < dependentTrackingArrayLength; index++) {
256: if (dcrs.dependentResultSets[index] != null) {
257: dependentTrackingArray[index] = getResultSetStatistics(dcrs.dependentResultSets[index]);
258: anyAttached = true;
259: }
260: }
261: if (!anyAttached) {
262: dependentTrackingArray = null;
263: }
264:
265: retval = new RealDeleteCascadeResultSetStatistics(
266: dcrs.rowCount,
267: dcrs.constants.deferred,
268: dcrs.constants.irgs.length,
269: dcrs.constants.lockMode == TransactionController.MODE_TABLE,
270: dcrs.getExecuteTime(),
271: getResultSetStatistics(dcrs.savedSource),
272: dependentTrackingArray);
273:
274: dcrs.savedSource = null;
275: } else if (rs instanceof DeleteResultSet) {
276: DeleteResultSet drs = (DeleteResultSet) rs;
277:
278: retval = new RealDeleteResultSetStatistics(
279: drs.rowCount,
280: drs.constants.deferred,
281: drs.constants.irgs.length,
282: drs.constants.lockMode == TransactionController.MODE_TABLE,
283: drs.getExecuteTime(),
284: getResultSetStatistics(drs.savedSource));
285:
286: drs.savedSource = null;
287: } else if (rs instanceof DeleteVTIResultSet) {
288: DeleteVTIResultSet dVTIrs = (DeleteVTIResultSet) rs;
289:
290: retval = new RealDeleteVTIResultSetStatistics(
291: dVTIrs.rowCount, dVTIrs.getExecuteTime(),
292: getResultSetStatistics(dVTIrs.savedSource));
293:
294: dVTIrs.savedSource = null;
295: }
296:
297: return retval;
298: }
299:
300: public ResultSetStatistics getResultSetStatistics(NoPutResultSet rs) {
301: /* We need to differentiate based on instanceof in order
302: * to find the right constructor to call. This is ugly,
303: * but if we don't do instanceof then rs is always seen as an
304: * interface instead of a class when we try to overload
305: * a method with both.
306: */
307: if (rs instanceof ProjectRestrictResultSet) {
308: ProjectRestrictResultSet prrs = (ProjectRestrictResultSet) rs;
309: int subqueryTrackingArrayLength = (prrs.subqueryTrackingArray == null) ? 0
310: : prrs.subqueryTrackingArray.length;
311: ResultSetStatistics[] subqueryTrackingArray = new ResultSetStatistics[subqueryTrackingArrayLength];
312: boolean anyAttached = false;
313: for (int index = 0; index < subqueryTrackingArrayLength; index++) {
314: if (prrs.subqueryTrackingArray[index] != null
315: && prrs.subqueryTrackingArray[index]
316: .getPointOfAttachment() == prrs.resultSetNumber) {
317: subqueryTrackingArray[index] = getResultSetStatistics(prrs.subqueryTrackingArray[index]);
318: anyAttached = true;
319: }
320: }
321: if (!anyAttached) {
322: subqueryTrackingArray = null;
323: }
324:
325: return new RealProjectRestrictStatistics(prrs.numOpens,
326: prrs.rowsSeen, prrs.rowsFiltered,
327: prrs.constructorTime, prrs.openTime, prrs.nextTime,
328: prrs.closeTime, prrs.resultSetNumber,
329: prrs.restrictionTime, prrs.projectionTime,
330: subqueryTrackingArray, (prrs.restriction != null),
331: prrs.doesProjection,
332: prrs.optimizerEstimatedRowCount,
333: prrs.optimizerEstimatedCost,
334: getResultSetStatistics(prrs.source));
335: } else if (rs instanceof SortResultSet) {
336: SortResultSet srs = (SortResultSet) rs;
337:
338: return new RealSortStatistics(srs.numOpens, srs.rowsSeen,
339: srs.rowsFiltered, srs.constructorTime,
340: srs.openTime, srs.nextTime, srs.closeTime,
341: srs.resultSetNumber, srs.rowsInput,
342: srs.rowsReturned, srs.distinct,
343: srs.isInSortedOrder, srs.sortProperties,
344: srs.optimizerEstimatedRowCount,
345: srs.optimizerEstimatedCost,
346: getResultSetStatistics(srs.source));
347: } else if (rs instanceof DistinctScalarAggregateResultSet) {
348: DistinctScalarAggregateResultSet dsars = (DistinctScalarAggregateResultSet) rs;
349:
350: return new RealDistinctScalarAggregateStatistics(
351: dsars.numOpens, dsars.rowsSeen, dsars.rowsFiltered,
352: dsars.constructorTime, dsars.openTime,
353: dsars.nextTime, dsars.closeTime,
354: dsars.resultSetNumber, dsars.rowsInput,
355: dsars.optimizerEstimatedRowCount,
356: dsars.optimizerEstimatedCost,
357: getResultSetStatistics(dsars.source));
358: } else if (rs instanceof ScalarAggregateResultSet) {
359: ScalarAggregateResultSet sars = (ScalarAggregateResultSet) rs;
360:
361: return new RealScalarAggregateStatistics(sars.numOpens,
362: sars.rowsSeen, sars.rowsFiltered,
363: sars.constructorTime, sars.openTime, sars.nextTime,
364: sars.closeTime, sars.resultSetNumber,
365: sars.singleInputRow, sars.rowsInput,
366: sars.optimizerEstimatedRowCount,
367: sars.optimizerEstimatedCost,
368: getResultSetStatistics(sars.source));
369: } else if (rs instanceof GroupedAggregateResultSet) {
370: GroupedAggregateResultSet gars = (GroupedAggregateResultSet) rs;
371:
372: return new RealGroupedAggregateStatistics(gars.numOpens,
373: gars.rowsSeen, gars.rowsFiltered,
374: gars.constructorTime, gars.openTime, gars.nextTime,
375: gars.closeTime, gars.resultSetNumber,
376: gars.rowsInput, gars.hasDistinctAggregate,
377: gars.isInSortedOrder, gars.sortProperties,
378: gars.optimizerEstimatedRowCount,
379: gars.optimizerEstimatedCost,
380: getResultSetStatistics(gars.source));
381: } else if (rs instanceof TableScanResultSet) {
382: boolean instantaneousLocks = false;
383: TableScanResultSet tsrs = (TableScanResultSet) rs;
384: String startPosition = null;
385: String stopPosition = null;
386: String isolationLevel = null;
387: String lockString = null;
388: String lockRequestString = null;
389:
390: switch (tsrs.isolationLevel) {
391: case TransactionController.ISOLATION_SERIALIZABLE:
392: isolationLevel = MessageService
393: .getTextMessage(SQLState.LANG_SERIALIZABLE);
394: break;
395:
396: case TransactionController.ISOLATION_REPEATABLE_READ:
397: isolationLevel = MessageService
398: .getTextMessage(SQLState.LANG_REPEATABLE_READ);
399: break;
400:
401: case TransactionController.ISOLATION_READ_COMMITTED_NOHOLDLOCK:
402: instantaneousLocks = true;
403: //fall through
404: case TransactionController.ISOLATION_READ_COMMITTED:
405: isolationLevel = MessageService
406: .getTextMessage(SQLState.LANG_READ_COMMITTED);
407: break;
408:
409: case TransactionController.ISOLATION_READ_UNCOMMITTED:
410: isolationLevel = MessageService
411: .getTextMessage(SQLState.LANG_READ_UNCOMMITTED);
412: break;
413: }
414:
415: if (tsrs.forUpdate) {
416: lockString = MessageService
417: .getTextMessage(SQLState.LANG_EXCLUSIVE);
418: } else {
419: if (instantaneousLocks) {
420: lockString = MessageService
421: .getTextMessage(SQLState.LANG_INSTANTANEOUS_SHARE);
422: } else {
423: lockString = MessageService
424: .getTextMessage(SQLState.LANG_SHARE);
425: }
426: }
427:
428: switch (tsrs.lockMode) {
429: case TransactionController.MODE_TABLE:
430: // RESOLVE: Not sure this will really work, as we
431: // are tacking together English words to make a phrase.
432: // Will this work in other languages?
433: lockRequestString = lockString
434: + " "
435: + MessageService
436: .getTextMessage(SQLState.LANG_TABLE);
437: break;
438:
439: case TransactionController.MODE_RECORD:
440: // RESOLVE: Not sure this will really work, as we
441: // are tacking together English words to make a phrase.
442: // Will this work in other languages?
443: lockRequestString = lockString
444: + " "
445: + MessageService
446: .getTextMessage(SQLState.LANG_ROW);
447: break;
448: }
449:
450: if (tsrs.indexName != null) {
451: /* Start and stop position strings will be non-null
452: * if the TSRS has been closed. Otherwise, we go off
453: * and build the strings now.
454: */
455: startPosition = tsrs.startPositionString;
456: if (startPosition == null) {
457: startPosition = tsrs.printStartPosition();
458: }
459: stopPosition = tsrs.stopPositionString;
460: if (stopPosition == null) {
461: stopPosition = tsrs.printStopPosition();
462: }
463: }
464:
465: return new RealTableScanStatistics(tsrs.numOpens,
466: tsrs.rowsSeen, tsrs.rowsFiltered,
467: tsrs.constructorTime, tsrs.openTime, tsrs.nextTime,
468: tsrs.closeTime, tsrs.resultSetNumber,
469: tsrs.tableName,
470: tsrs.userSuppliedOptimizerOverrides,
471: tsrs.indexName, tsrs.isConstraint, tsrs
472: .printQualifiers(tsrs.qualifiers), tsrs
473: .getScanProperties(), startPosition,
474: stopPosition, isolationLevel, lockRequestString,
475: tsrs.rowsPerRead, tsrs.coarserLock,
476: tsrs.optimizerEstimatedRowCount,
477: tsrs.optimizerEstimatedCost);
478: }
479:
480: else if (rs instanceof LastIndexKeyResultSet) {
481: LastIndexKeyResultSet lrs = (LastIndexKeyResultSet) rs;
482: String isolationLevel = null;
483: String lockRequestString = null;
484:
485: switch (lrs.isolationLevel) {
486: case TransactionController.ISOLATION_SERIALIZABLE:
487: isolationLevel = MessageService
488: .getTextMessage(SQLState.LANG_SERIALIZABLE);
489: break;
490:
491: case TransactionController.ISOLATION_REPEATABLE_READ:
492: isolationLevel = MessageService
493: .getTextMessage(SQLState.LANG_REPEATABLE_READ);
494: break;
495:
496: case TransactionController.ISOLATION_READ_COMMITTED_NOHOLDLOCK:
497: case TransactionController.ISOLATION_READ_COMMITTED:
498: isolationLevel = MessageService
499: .getTextMessage(SQLState.LANG_READ_COMMITTED);
500: break;
501:
502: case TransactionController.ISOLATION_READ_UNCOMMITTED:
503: isolationLevel = MessageService
504: .getTextMessage(SQLState.LANG_READ_UNCOMMITTED);
505: break;
506: }
507:
508: switch (lrs.lockMode) {
509: case TransactionController.MODE_TABLE:
510: lockRequestString = MessageService
511: .getTextMessage(SQLState.LANG_SHARE_TABLE);
512: break;
513:
514: case TransactionController.MODE_RECORD:
515: lockRequestString = MessageService
516: .getTextMessage(SQLState.LANG_SHARE_ROW);
517: break;
518: }
519:
520: return new RealLastIndexKeyScanStatistics(lrs.numOpens,
521: lrs.constructorTime, lrs.openTime, lrs.nextTime,
522: lrs.closeTime, lrs.resultSetNumber, lrs.tableName,
523: lrs.indexName, isolationLevel, lockRequestString,
524: lrs.optimizerEstimatedRowCount,
525: lrs.optimizerEstimatedCost);
526: } else if (rs instanceof HashLeftOuterJoinResultSet) {
527: HashLeftOuterJoinResultSet hlojrs = (HashLeftOuterJoinResultSet) rs;
528:
529: return new RealHashLeftOuterJoinStatistics(hlojrs.numOpens,
530: hlojrs.rowsSeen, hlojrs.rowsFiltered,
531: hlojrs.constructorTime, hlojrs.openTime,
532: hlojrs.nextTime, hlojrs.closeTime,
533: hlojrs.resultSetNumber, hlojrs.rowsSeenLeft,
534: hlojrs.rowsSeenRight, hlojrs.rowsReturned,
535: hlojrs.restrictionTime,
536: hlojrs.optimizerEstimatedRowCount,
537: hlojrs.optimizerEstimatedCost,
538: hlojrs.userSuppliedOptimizerOverrides,
539: getResultSetStatistics(hlojrs.leftResultSet),
540: getResultSetStatistics(hlojrs.rightResultSet),
541: hlojrs.emptyRightRowsReturned);
542: } else if (rs instanceof NestedLoopLeftOuterJoinResultSet) {
543: NestedLoopLeftOuterJoinResultSet nllojrs = (NestedLoopLeftOuterJoinResultSet) rs;
544:
545: return new RealNestedLoopLeftOuterJoinStatistics(
546: nllojrs.numOpens, nllojrs.rowsSeen,
547: nllojrs.rowsFiltered, nllojrs.constructorTime,
548: nllojrs.openTime, nllojrs.nextTime,
549: nllojrs.closeTime, nllojrs.resultSetNumber,
550: nllojrs.rowsSeenLeft, nllojrs.rowsSeenRight,
551: nllojrs.rowsReturned, nllojrs.restrictionTime,
552: nllojrs.optimizerEstimatedRowCount,
553: nllojrs.optimizerEstimatedCost,
554: nllojrs.userSuppliedOptimizerOverrides,
555: getResultSetStatistics(nllojrs.leftResultSet),
556: getResultSetStatistics(nllojrs.rightResultSet),
557: nllojrs.emptyRightRowsReturned);
558: } else if (rs instanceof HashJoinResultSet) {
559: HashJoinResultSet hjrs = (HashJoinResultSet) rs;
560:
561: return new RealHashJoinStatistics(hjrs.numOpens,
562: hjrs.rowsSeen, hjrs.rowsFiltered,
563: hjrs.constructorTime, hjrs.openTime, hjrs.nextTime,
564: hjrs.closeTime, hjrs.resultSetNumber,
565: hjrs.rowsSeenLeft, hjrs.rowsSeenRight,
566: hjrs.rowsReturned, hjrs.restrictionTime,
567: hjrs.oneRowRightSide,
568: hjrs.optimizerEstimatedRowCount,
569: hjrs.optimizerEstimatedCost,
570: hjrs.userSuppliedOptimizerOverrides,
571: getResultSetStatistics(hjrs.leftResultSet),
572: getResultSetStatistics(hjrs.rightResultSet));
573: } else if (rs instanceof NestedLoopJoinResultSet) {
574: NestedLoopJoinResultSet nljrs = (NestedLoopJoinResultSet) rs;
575:
576: return new RealNestedLoopJoinStatistics(nljrs.numOpens,
577: nljrs.rowsSeen, nljrs.rowsFiltered,
578: nljrs.constructorTime, nljrs.openTime,
579: nljrs.nextTime, nljrs.closeTime,
580: nljrs.resultSetNumber, nljrs.rowsSeenLeft,
581: nljrs.rowsSeenRight, nljrs.rowsReturned,
582: nljrs.restrictionTime, nljrs.oneRowRightSide,
583: nljrs.optimizerEstimatedRowCount,
584: nljrs.optimizerEstimatedCost,
585: nljrs.userSuppliedOptimizerOverrides,
586: getResultSetStatistics(nljrs.leftResultSet),
587: getResultSetStatistics(nljrs.rightResultSet));
588: } else if (rs instanceof IndexRowToBaseRowResultSet) {
589: IndexRowToBaseRowResultSet irtbrrs = (IndexRowToBaseRowResultSet) rs;
590:
591: return new RealIndexRowToBaseRowStatistics(
592: irtbrrs.numOpens, irtbrrs.rowsSeen,
593: irtbrrs.rowsFiltered, irtbrrs.constructorTime,
594: irtbrrs.openTime, irtbrrs.nextTime,
595: irtbrrs.closeTime, irtbrrs.resultSetNumber,
596: irtbrrs.indexName, irtbrrs.accessedHeapCols,
597: irtbrrs.optimizerEstimatedRowCount,
598: irtbrrs.optimizerEstimatedCost,
599: getResultSetStatistics(irtbrrs.source));
600: } else if (rs instanceof RowResultSet) {
601: RowResultSet rrs = (RowResultSet) rs;
602:
603: return new RealRowResultSetStatistics(rrs.numOpens,
604: rrs.rowsSeen, rrs.rowsFiltered,
605: rrs.constructorTime, rrs.openTime, rrs.nextTime,
606: rrs.closeTime, rrs.resultSetNumber,
607: rrs.rowsReturned, rrs.optimizerEstimatedRowCount,
608: rrs.optimizerEstimatedCost);
609: } else if (rs instanceof SetOpResultSet) {
610: SetOpResultSet srs = (SetOpResultSet) rs;
611:
612: return new RealSetOpResultSetStatistics(srs.getOpType(),
613: srs.numOpens, srs.rowsSeen, srs.rowsFiltered,
614: srs.constructorTime, srs.openTime, srs.nextTime,
615: srs.closeTime, srs.getResultSetNumber(), srs
616: .getRowsSeenLeft(), srs.getRowsSeenRight(),
617: srs.getRowsReturned(),
618: srs.optimizerEstimatedRowCount,
619: srs.optimizerEstimatedCost,
620: getResultSetStatistics(srs.getLeftSourceInput()),
621: getResultSetStatistics(srs.getRightSourceInput()));
622: } else if (rs instanceof UnionResultSet) {
623: UnionResultSet urs = (UnionResultSet) rs;
624:
625: return new RealUnionResultSetStatistics(urs.numOpens,
626: urs.rowsSeen, urs.rowsFiltered,
627: urs.constructorTime, urs.openTime, urs.nextTime,
628: urs.closeTime, urs.resultSetNumber,
629: urs.rowsSeenLeft, urs.rowsSeenRight,
630: urs.rowsReturned, urs.optimizerEstimatedRowCount,
631: urs.optimizerEstimatedCost,
632: getResultSetStatistics(urs.source1),
633: getResultSetStatistics(urs.source2));
634: } else if (rs instanceof AnyResultSet) {
635: AnyResultSet ars = (AnyResultSet) rs;
636:
637: return new RealAnyResultSetStatistics(ars.numOpens,
638: ars.rowsSeen, ars.rowsFiltered,
639: ars.constructorTime, ars.openTime, ars.nextTime,
640: ars.closeTime, ars.resultSetNumber,
641: ars.subqueryNumber, ars.pointOfAttachment,
642: ars.optimizerEstimatedRowCount,
643: ars.optimizerEstimatedCost,
644: getResultSetStatistics(ars.source));
645: } else if (rs instanceof OnceResultSet) {
646: OnceResultSet ors = (OnceResultSet) rs;
647:
648: return new RealOnceResultSetStatistics(ors.numOpens,
649: ors.rowsSeen, ors.rowsFiltered,
650: ors.constructorTime, ors.openTime, ors.nextTime,
651: ors.closeTime, ors.resultSetNumber,
652: ors.subqueryNumber, ors.pointOfAttachment,
653: ors.optimizerEstimatedRowCount,
654: ors.optimizerEstimatedCost,
655: getResultSetStatistics(ors.source));
656: } else if (rs instanceof NormalizeResultSet) {
657: NormalizeResultSet nrs = (NormalizeResultSet) rs;
658:
659: return new RealNormalizeResultSetStatistics(nrs.numOpens,
660: nrs.rowsSeen, nrs.rowsFiltered,
661: nrs.constructorTime, nrs.openTime, nrs.nextTime,
662: nrs.closeTime, nrs.resultSetNumber,
663: nrs.optimizerEstimatedRowCount,
664: nrs.optimizerEstimatedCost,
665: getResultSetStatistics(nrs.source));
666: } else if (rs instanceof MaterializedResultSet) {
667: MaterializedResultSet mrs = (MaterializedResultSet) rs;
668:
669: return new RealMaterializedResultSetStatistics(
670: mrs.numOpens, mrs.rowsSeen, mrs.rowsFiltered,
671: mrs.constructorTime, mrs.openTime, mrs.nextTime,
672: mrs.closeTime, mrs.createTCTime, mrs.fetchTCTime,
673: mrs.resultSetNumber,
674: mrs.optimizerEstimatedRowCount,
675: mrs.optimizerEstimatedCost,
676: getResultSetStatistics(mrs.source));
677: } else if (rs instanceof ScrollInsensitiveResultSet) {
678: ScrollInsensitiveResultSet sirs = (ScrollInsensitiveResultSet) rs;
679:
680: return new RealScrollInsensitiveResultSetStatistics(
681: sirs.numOpens, sirs.rowsSeen, sirs.rowsFiltered,
682: sirs.constructorTime, sirs.openTime, sirs.nextTime,
683: sirs.closeTime, sirs.numFromHashTable,
684: sirs.numToHashTable, sirs.resultSetNumber,
685: sirs.optimizerEstimatedRowCount,
686: sirs.optimizerEstimatedCost,
687: getResultSetStatistics(sirs.source));
688: } else if (rs instanceof CurrentOfResultSet) {
689: CurrentOfResultSet cors = (CurrentOfResultSet) rs;
690:
691: return new RealCurrentOfStatistics(cors.numOpens,
692: cors.rowsSeen, cors.rowsFiltered,
693: cors.constructorTime, cors.openTime, cors.nextTime,
694: cors.closeTime, cors.resultSetNumber);
695: } else if (rs instanceof HashScanResultSet) {
696: boolean instantaneousLocks = false;
697: HashScanResultSet hsrs = (HashScanResultSet) rs;
698: String startPosition = null;
699: String stopPosition = null;
700: String isolationLevel = null;
701: String lockString = null;
702:
703: switch (hsrs.isolationLevel) {
704: case TransactionController.ISOLATION_SERIALIZABLE:
705: isolationLevel = MessageService
706: .getTextMessage(SQLState.LANG_SERIALIZABLE);
707: break;
708:
709: case TransactionController.ISOLATION_REPEATABLE_READ:
710: isolationLevel = MessageService
711: .getTextMessage(SQLState.LANG_REPEATABLE_READ);
712: break;
713:
714: case TransactionController.ISOLATION_READ_COMMITTED_NOHOLDLOCK:
715: instantaneousLocks = true;
716: //fall through
717: case TransactionController.ISOLATION_READ_COMMITTED:
718: isolationLevel = MessageService
719: .getTextMessage(SQLState.LANG_READ_COMMITTED);
720: break;
721:
722: }
723:
724: if (hsrs.forUpdate) {
725: lockString = MessageService
726: .getTextMessage(SQLState.LANG_EXCLUSIVE);
727: } else {
728: if (instantaneousLocks) {
729: lockString = MessageService
730: .getTextMessage(SQLState.LANG_INSTANTANEOUS_SHARE);
731: } else {
732: lockString = MessageService
733: .getTextMessage(SQLState.LANG_SHARE);
734: }
735: }
736:
737: switch (hsrs.lockMode) {
738: case TransactionController.MODE_TABLE:
739: // RESOLVE: Not sure this will really work, as we
740: // are tacking together English words to make a phrase.
741: // Will this work in other languages?
742: lockString = lockString
743: + " "
744: + MessageService
745: .getTextMessage(SQLState.LANG_TABLE);
746: break;
747:
748: case TransactionController.MODE_RECORD:
749: // RESOLVE: Not sure this will really work, as we
750: // are tacking together English words to make a phrase.
751: // Will this work in other languages?
752: lockString = lockString
753: + " "
754: + MessageService
755: .getTextMessage(SQLState.LANG_ROW);
756: break;
757: }
758:
759: if (hsrs.indexName != null) {
760: /* Start and stop position strings will be non-null
761: * if the HSRS has been closed. Otherwise, we go off
762: * and build the strings now.
763: */
764: startPosition = hsrs.startPositionString;
765: if (startPosition == null) {
766: startPosition = hsrs.printStartPosition();
767: }
768: stopPosition = hsrs.stopPositionString;
769: if (stopPosition == null) {
770: stopPosition = hsrs.printStopPosition();
771: }
772: }
773:
774: // DistinctScanResultSet is simple sub-class of
775: // HashScanResultSet
776: if (rs instanceof DistinctScanResultSet) {
777: return new RealDistinctScanStatistics(hsrs.numOpens,
778: hsrs.rowsSeen, hsrs.rowsFiltered,
779: hsrs.constructorTime, hsrs.openTime,
780: hsrs.nextTime, hsrs.closeTime,
781: hsrs.resultSetNumber, hsrs.tableName,
782: hsrs.indexName, hsrs.isConstraint,
783: hsrs.hashtableSize, hsrs.keyColumns, hsrs
784: .printQualifiers(hsrs.scanQualifiers),
785: hsrs.printQualifiers(hsrs.nextQualifiers), hsrs
786: .getScanProperties(), startPosition,
787: stopPosition, isolationLevel, lockString,
788: hsrs.optimizerEstimatedRowCount,
789: hsrs.optimizerEstimatedCost);
790: } else {
791: return new RealHashScanStatistics(hsrs.numOpens,
792: hsrs.rowsSeen, hsrs.rowsFiltered,
793: hsrs.constructorTime, hsrs.openTime,
794: hsrs.nextTime, hsrs.closeTime,
795: hsrs.resultSetNumber, hsrs.tableName,
796: hsrs.indexName, hsrs.isConstraint,
797: hsrs.hashtableSize, hsrs.keyColumns, hsrs
798: .printQualifiers(hsrs.scanQualifiers),
799: hsrs.printQualifiers(hsrs.nextQualifiers), hsrs
800: .getScanProperties(), startPosition,
801: stopPosition, isolationLevel, lockString,
802: hsrs.optimizerEstimatedRowCount,
803: hsrs.optimizerEstimatedCost);
804: }
805: } else if (rs instanceof HashTableResultSet) {
806: HashTableResultSet htrs = (HashTableResultSet) rs;
807: int subqueryTrackingArrayLength = (htrs.subqueryTrackingArray == null) ? 0
808: : htrs.subqueryTrackingArray.length;
809: ResultSetStatistics[] subqueryTrackingArray = new ResultSetStatistics[subqueryTrackingArrayLength];
810: boolean anyAttached = false;
811: for (int index = 0; index < subqueryTrackingArrayLength; index++) {
812: if (htrs.subqueryTrackingArray[index] != null
813: && htrs.subqueryTrackingArray[index]
814: .getPointOfAttachment() == htrs.resultSetNumber) {
815: subqueryTrackingArray[index] = getResultSetStatistics(htrs.subqueryTrackingArray[index]);
816: anyAttached = true;
817: }
818: }
819: if (!anyAttached) {
820: subqueryTrackingArray = null;
821: }
822:
823: return new RealHashTableStatistics(htrs.numOpens,
824: htrs.rowsSeen, htrs.rowsFiltered,
825: htrs.constructorTime, htrs.openTime, htrs.nextTime,
826: htrs.closeTime, htrs.resultSetNumber,
827: htrs.hashtableSize, htrs.keyColumns,
828: HashScanResultSet
829: .printQualifiers(htrs.nextQualifiers),
830: htrs.scanProperties,
831: htrs.optimizerEstimatedRowCount,
832: htrs.optimizerEstimatedCost, subqueryTrackingArray,
833: getResultSetStatistics(htrs.source));
834: } else if (rs instanceof VTIResultSet) {
835: VTIResultSet vtirs = (VTIResultSet) rs;
836:
837: return new RealVTIStatistics(vtirs.numOpens,
838: vtirs.rowsSeen, vtirs.rowsFiltered,
839: vtirs.constructorTime, vtirs.openTime,
840: vtirs.nextTime, vtirs.closeTime,
841: vtirs.resultSetNumber, vtirs.javaClassName,
842: vtirs.optimizerEstimatedRowCount,
843: vtirs.optimizerEstimatedCost);
844: }
845:
846: else if (rs instanceof DependentResultSet) {
847: boolean instantaneousLocks = false;
848: DependentResultSet dsrs = (DependentResultSet) rs;
849: String startPosition = null;
850: String stopPosition = null;
851: String isolationLevel = null;
852: String lockString = null;
853: String lockRequestString = null;
854:
855: switch (dsrs.isolationLevel) {
856: case TransactionController.ISOLATION_SERIALIZABLE:
857: isolationLevel = MessageService
858: .getTextMessage(SQLState.LANG_SERIALIZABLE);
859: break;
860:
861: case TransactionController.ISOLATION_REPEATABLE_READ:
862: isolationLevel = MessageService
863: .getTextMessage(SQLState.LANG_REPEATABLE_READ);
864: break;
865:
866: case TransactionController.ISOLATION_READ_COMMITTED_NOHOLDLOCK:
867: instantaneousLocks = true;
868: //fall through
869: case TransactionController.ISOLATION_READ_COMMITTED:
870: isolationLevel = MessageService
871: .getTextMessage(SQLState.LANG_READ_COMMITTED);
872: break;
873:
874: case TransactionController.ISOLATION_READ_UNCOMMITTED:
875: isolationLevel = MessageService
876: .getTextMessage(SQLState.LANG_READ_UNCOMMITTED);
877: break;
878: }
879:
880: if (dsrs.forUpdate) {
881: lockString = MessageService
882: .getTextMessage(SQLState.LANG_EXCLUSIVE);
883: } else {
884: if (instantaneousLocks) {
885: lockString = MessageService
886: .getTextMessage(SQLState.LANG_INSTANTANEOUS_SHARE);
887: } else {
888: lockString = MessageService
889: .getTextMessage(SQLState.LANG_SHARE);
890: }
891: }
892:
893: switch (dsrs.lockMode) {
894: case TransactionController.MODE_TABLE:
895: // RESOLVE: Not sure this will really work, as we
896: // are tacking together English words to make a phrase.
897: // Will this work in other languages?
898: lockRequestString = lockString
899: + " "
900: + MessageService
901: .getTextMessage(SQLState.LANG_TABLE);
902: break;
903:
904: case TransactionController.MODE_RECORD:
905: // RESOLVE: Not sure this will really work, as we
906: // are tacking together English words to make a phrase.
907: // Will this work in other languages?
908: lockRequestString = lockString
909: + " "
910: + MessageService
911: .getTextMessage(SQLState.LANG_ROW);
912: break;
913: }
914:
915: /* Start and stop position strings will be non-null
916: * if the dSRS has been closed. Otherwise, we go off
917: * and build the strings now.
918: */
919: startPosition = dsrs.startPositionString;
920: if (startPosition == null) {
921: startPosition = dsrs.printStartPosition();
922: }
923: stopPosition = dsrs.stopPositionString;
924: if (stopPosition == null) {
925: stopPosition = dsrs.printStopPosition();
926: }
927:
928: return new RealTableScanStatistics(dsrs.numOpens,
929: dsrs.rowsSeen, dsrs.rowsFiltered,
930: dsrs.constructorTime, dsrs.openTime, dsrs.nextTime,
931: dsrs.closeTime, dsrs.resultSetNumber,
932: dsrs.tableName, null, dsrs.indexName,
933: dsrs.isConstraint, dsrs.printQualifiers(), dsrs
934: .getScanProperties(), startPosition,
935: stopPosition, isolationLevel, lockRequestString,
936: dsrs.rowsPerRead, dsrs.coarserLock,
937: dsrs.optimizerEstimatedRowCount,
938: dsrs.optimizerEstimatedCost);
939: } else {
940: return null;
941: }
942: }
943:
944: //
945: // class interface
946: //
947: public RealResultSetStatisticsFactory() {
948: }
949:
950: }
|