001: /*
002:
003: Derby - Class org.apache.derby.impl.sql.execute.BasicSortObserver
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.store.access.SortObserver;
025: import org.apache.derby.iapi.services.io.Storable;
026:
027: import org.apache.derby.iapi.types.CloneableObject;
028:
029: import org.apache.derby.iapi.services.sanity.SanityManager;
030:
031: import org.apache.derby.iapi.error.StandardException;
032:
033: import org.apache.derby.iapi.sql.execute.ExecRow;
034:
035: import org.apache.derby.iapi.types.DataValueDescriptor;
036:
037: import java.util.Vector;
038:
039: /**
040: * This is the most basic sort observer. It
041: * handles distinct sorts and non-distinct sorts.
042: *
043: * @author jamie
044: */
045: public class BasicSortObserver implements SortObserver {
046: protected boolean doClone;
047: protected boolean distinct;
048: private boolean reuseWrappers;
049: private ExecRow execRow;
050: private Vector vector;
051:
052: /**
053: * Simple constructor
054: *
055: * @param doClone If true, then rows that are retained
056: * by the sorter will be cloned. This is needed
057: * if language is reusing row wrappers.
058: *
059: * @param distinct If true, toss out duplicates.
060: * Otherwise, retain them.
061: *
062: * @param execRow ExecRow to use as source of clone for store.
063: *
064: * @param reuseWrappers Whether or not we can reuse the wrappers
065: */
066: public BasicSortObserver(boolean doClone, boolean distinct,
067: ExecRow execRow, boolean reuseWrappers) {
068: this .doClone = doClone;
069: this .distinct = distinct;
070: this .execRow = execRow;
071: this .reuseWrappers = reuseWrappers;
072: vector = new Vector();
073: }
074:
075: /**
076: * Called prior to inserting a distinct sort
077: * key.
078: *
079: * @param insertRow the current row that the sorter
080: * is on the verge of retaining
081: *
082: * @return the row to be inserted by the sorter. If null,
083: * then nothing is inserted by the sorter. Distinct
084: * sorts will want to return null.
085: *
086: * @exception StandardException never thrown
087: */
088: public DataValueDescriptor[] insertNonDuplicateKey(
089: DataValueDescriptor[] insertRow) throws StandardException {
090: return (doClone) ? getClone(insertRow) : insertRow;
091: }
092:
093: /**
094: * Called prior to inserting a duplicate sort
095: * key.
096: *
097: * @param insertRow the current row that the sorter
098: * is on the verge of retaining. It is a duplicate
099: * of existingRow.
100: *
101: * @param existingRow the row that is already in the
102: * the sorter which is a duplicate of insertRow
103: *
104: * @exception StandardException never thrown
105: */
106: public DataValueDescriptor[] insertDuplicateKey(
107: DataValueDescriptor[] insertRow,
108: DataValueDescriptor[] existingRow) throws StandardException {
109: return (distinct) ? (DataValueDescriptor[]) null
110: : (doClone) ? getClone(insertRow) : insertRow;
111:
112: }
113:
114: public void addToFreeList(DataValueDescriptor[] objectArray,
115: int maxFreeListSize) {
116: if (reuseWrappers && vector.size() < maxFreeListSize) {
117: vector.addElement(objectArray);
118: }
119: }
120:
121: public DataValueDescriptor[] getArrayClone()
122: throws StandardException {
123: int lastElement = vector.size();
124:
125: if (lastElement > 0) {
126: DataValueDescriptor[] retval = (DataValueDescriptor[]) vector
127: .elementAt(lastElement - 1);
128: vector.removeElementAt(lastElement - 1);
129: return retval;
130: }
131: return execRow.getRowArrayClone();
132: }
133:
134: private DataValueDescriptor[] getClone(
135: DataValueDescriptor[] origArray) {
136: /* If the free list is not empty, then
137: * get an DataValueDescriptor[] from there and swap
138: * objects between that DataValueDescriptor[] and
139: * origArray, returning the DataValueDescriptor[]
140: * from the free list. That will save
141: * on unnecessary cloning.
142: */
143: /* RESOLVE - We can't enable this code
144: * until Bug 2829 is fixed.
145: * (Close bug 2828 when enabling the code.
146: if (vector.size() > 0)
147: {
148: DataValueDescriptor[] retval = getArrayClone();
149: for (int index = 0; index < retval.length; index++)
150: {
151: DataValueDescriptor tmp = origArray[index];
152: origArray[index] = retval[index];
153: retval[index] = tmp;
154: }
155: return retval;
156: }
157: */
158: DataValueDescriptor[] newArray = new DataValueDescriptor[origArray.length];
159: for (int i = 0; i < origArray.length; i++) {
160: // the only difference between getClone and cloneObject is cloneObject does
161: // not objectify a stream. We use getClone here. Beetle 4896.
162: newArray[i] = origArray[i].getClone();
163: }
164:
165: return newArray;
166: }
167: }
|