001: /*
002:
003: Derby - Class org.apache.derby.impl.sql.execute.ValueRow
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.io.Storable;
025:
026: import org.apache.derby.iapi.error.StandardException;
027:
028: import org.apache.derby.iapi.reference.SQLState;
029:
030: import org.apache.derby.iapi.sql.execute.ExecRow;
031: import org.apache.derby.iapi.sql.execute.ExecutionContext;
032: import org.apache.derby.iapi.types.DataValueDescriptor;
033:
034: import org.apache.derby.iapi.reference.SQLState;
035:
036: import org.apache.derby.iapi.types.RowLocation;
037:
038: import org.apache.derby.iapi.services.sanity.SanityManager;
039:
040: import org.apache.derby.iapi.services.io.Formatable;
041: import org.apache.derby.iapi.services.io.ArrayUtil;
042: import org.apache.derby.iapi.services.io.StoredFormatIds;
043: import org.apache.derby.iapi.services.io.FormatIdUtil;
044:
045: import org.apache.derby.iapi.services.stream.HeaderPrintWriter;
046:
047: import java.io.ObjectOutput;
048: import java.io.ObjectInput;
049: import java.io.IOException;
050:
051: import org.apache.derby.iapi.services.io.FormatableBitSet;
052:
053: /**
054: Basic implementation of ExecRow.
055:
056: @author ames
057: */
058: public class ValueRow implements ExecRow, Formatable {
059: /********************************************************
060: **
061: ** This class implements Formatable. That means that it
062: ** can write itself to and from a formatted stream. If
063: ** you add more fields to this class, make sure that you
064: ** also write/read them with the writeExternal()/readExternal()
065: ** methods.
066: **
067: ** If, inbetween releases, you add more fields to this class,
068: ** then you should bump the version number emitted by the getTypeFormatId()
069: ** method.
070: **
071: ********************************************************/
072:
073: ///////////////////////////////////////////////////////////////////////
074: //
075: // STATE
076: //
077: ///////////////////////////////////////////////////////////////////////
078: private DataValueDescriptor[] column;
079: private int ncols;
080:
081: ///////////////////////////////////////////////////////////////////////
082: //
083: // CONSTRUCTORS
084: //
085: ///////////////////////////////////////////////////////////////////////
086:
087: /**
088: * Public niladic constructor. Needed for Formatable interface to work.
089: *
090: */
091: public ValueRow() {
092: }
093:
094: /**
095: * Make a value row with a designated number of column slots.
096: *
097: * @param ncols number of columns to allocate
098: */
099: public ValueRow(int ncols) {
100: column = new DataValueDescriptor[ncols];
101: this .ncols = ncols;
102: }
103:
104: ///////////////////////////////////////////////////////////////////////
105: //
106: // EXECROW INTERFACE
107: //
108: ///////////////////////////////////////////////////////////////////////
109:
110: // this is the actual current # of columns
111: public int nColumns() {
112: return ncols;
113: }
114:
115: // get a new Object[] for the row
116: public void getNewObjectArray() {
117: column = new DataValueDescriptor[ncols];
118: }
119:
120: /*
121: * Row interface
122: */
123: // position is 1-based
124: public DataValueDescriptor getColumn(int position) {
125: if (position <= column.length)
126: return (DataValueDescriptor) (column[position - 1]);
127: else
128: return (DataValueDescriptor) null;
129: }
130:
131: // position is 1-based.
132: public void setColumn(int position, DataValueDescriptor col) {
133:
134: if (position > column.length)
135: realloc(position); // enough for this column
136: column[position - 1] = col;
137: }
138:
139: /*
140: ** ExecRow interface
141: */
142:
143: // position is 1-based
144: public ExecRow getClone() {
145: return getClone((FormatableBitSet) null);
146: }
147:
148: public ExecRow getClone(FormatableBitSet clonedCols) {
149: int numColumns = column.length;
150:
151: /* Get the right type of row */
152: ExecRow rowClone = cloneMe();
153:
154: for (int colCtr = 0; colCtr < numColumns; colCtr++) {
155: // Copy those columns whose bit isn't set (and there is a FormatableBitSet)
156: if (clonedCols != null && !(clonedCols.get(colCtr + 1))) {
157: /* Rows are 1-based, column[] is 0-based */
158: rowClone.setColumn(colCtr + 1,
159: (DataValueDescriptor) column[colCtr]);
160: continue;
161: }
162:
163: if (column[colCtr] != null) {
164: /* Rows are 1-based, column[] is 0-based */
165: rowClone.setColumn(colCtr + 1, column[colCtr]
166: .getClone());
167: }
168: }
169: return rowClone;
170: }
171:
172: // position is 1-based
173: public ExecRow getNewNullRow() {
174: int numColumns = column.length;
175: ExecRow rowClone = cloneMe();
176:
177: for (int colCtr = 0; colCtr < numColumns; colCtr++) {
178: if (column[colCtr] != null) {
179: /* Rows are 1-based, column[] is 0-based */
180: if (column[colCtr] instanceof RowLocation) {
181: /*
182: ** The getClone() method for a RowLocation has the same
183: ** name as for DataValueDescriptor, but it's on a different
184: ** interface, so the cast must be different.
185: **
186: */
187: rowClone.setColumn(colCtr + 1, column[colCtr]
188: .getClone());
189: } else {
190: // otherwise, get a new null
191: rowClone.setColumn(colCtr + 1,
192: ((DataValueDescriptor) (column[colCtr]))
193: .getNewNull());
194: }
195: }
196: }
197: return rowClone;
198: }
199:
200: ExecRow cloneMe() {
201: return new ValueRow(ncols);
202: }
203:
204: // position is 1-based
205: public final DataValueDescriptor cloneColumn(int columnPosition) {
206: return column[columnPosition - 1].getClone();
207: }
208:
209: /*
210: * class interface
211: */
212: public String toString() {
213: // NOTE: This method is required for external functionality (the
214: // consistency checker), so do not put it under SanityManager.DEBUG.
215: String s = "{ ";
216: for (int i = 0; i < column.length; i++) {
217: if (column[i] == null)
218: s += "null";
219: else
220: s += column[i].toString();
221: if (i < (column.length - 1))
222: s += ", ";
223: }
224: s += " }";
225: return s;
226: }
227:
228: /**
229: Get the array form of the row that Access expects.
230:
231: @see ExecRow#getRowArray
232: */
233: public DataValueDescriptor[] getRowArray() {
234: return column;
235: }
236:
237: /**
238: Get a clone of the array form of the row that Access expects.
239:
240: @see ExecRow#getRowArray
241: */
242: public DataValueDescriptor[] getRowArrayClone() {
243: int numColumns = column.length;
244: DataValueDescriptor[] columnClones = new DataValueDescriptor[numColumns];
245:
246: for (int colCtr = 0; colCtr < numColumns; colCtr++) {
247: if (column[colCtr] != null) {
248: columnClones[colCtr] = column[colCtr].getClone();
249: }
250: }
251:
252: return columnClones;
253: }
254:
255: /**
256: * Set the row array
257: *
258: * @see ExecRow#setRowArray
259: */
260: public void setRowArray(DataValueDescriptor[] value) {
261: column = value;
262: }
263:
264: public void setRowArray(Storable[] value) {
265: if (value instanceof DataValueDescriptor[]) {
266: column = (DataValueDescriptor[]) value;
267: return;
268: }
269:
270: if ((column == null) || (column.length != value.length))
271: column = new DataValueDescriptor[value.length];
272:
273: System.arraycopy(value, 0, column, 0, column.length);
274: }
275:
276: // Set the number of columns in the row to ncols, preserving
277: // the existing contents.
278: protected void realloc(int ncols) {
279: DataValueDescriptor[] newcol = new DataValueDescriptor[ncols];
280:
281: System.arraycopy(column, 0, newcol, 0, column.length);
282: column = newcol;
283: }
284:
285: ///////////////////////////////////////////////////////////////////////
286: //
287: // FORMATABLE INTERFACE
288: //
289: ///////////////////////////////////////////////////////////////////////
290:
291: /**
292: * Read this object from a stream of stored objects.
293: *
294: * @param in read this.
295: *
296: * @exception IOException thrown on error
297: * @exception ClassNotFoundException thrown on error
298: */
299: public void readExternal(ObjectInput in) throws IOException,
300: ClassNotFoundException {
301: column = new DataValueDescriptor[ArrayUtil.readArrayLength(in)];
302: ArrayUtil.readArrayItems(in, column);
303: ncols = column.length;
304: }
305:
306: /**
307: * Write this object to a stream of stored objects.
308: *
309: * @param out write bytes here.
310: *
311: * @exception IOException thrown on error
312: */
313: public void writeExternal(ObjectOutput out) throws IOException {
314: ArrayUtil.writeArrayLength(out, column);
315: ArrayUtil.writeArrayItems(out, column);
316: }
317:
318: /**
319: * Get the formatID which corresponds to this class.
320: *
321: * @return the formatID of this class
322: */
323: public int getTypeFormatId() {
324: return StoredFormatIds.VALUE_ROW_V01_ID;
325: }
326:
327: }
|