EMMA Coverage Report (generated Wed Jun 28 22:15:27 PDT 2006)
[all classes][org.apache.derby.iapi.store.access]

COVERAGE SUMMARY FOR SOURCE FILE [RowUtil.java]

nameclass, %method, %block, %line, %
RowUtil.java100% (1/1)81%  (13/16)62%  (435/705)60%  (83.9/139)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class RowUtil100% (1/1)81%  (13/16)62%  (435/705)60%  (83.9/139)
<static initializer> 100% (1/1)100% (77/77)100% (4/4)
RowUtil (): void 0%   (0/1)0%   (0/3)0%   (0/1)
columnOutOfRange (DataValueDescriptor [], FormatableBitSet, int): int 100% (1/1)100% (28/28)100% (9/9)
getColumn (DataValueDescriptor [], FormatableBitSet, int): DataValueDescriptor 100% (1/1)34%  (11/32)38%  (1.9/5)
getColumn (Object [], FormatableBitSet, int): Object 100% (1/1)88%  (28/32)76%  (3.8/5)
getFetchDescriptorConstant (int): FetchDescriptor 100% (1/1)100% (14/14)100% (3/3)
getNumberOfColumns (int, FormatableBitSet): int 100% (1/1)81%  (26/32)84%  (7.6/9)
getQualifierBitSet (Qualifier [][]): FormatableBitSet 100% (1/1)100% (41/41)100% (8/8)
isRowEmpty (DataValueDescriptor [], FormatableBitSet): boolean 100% (1/1)35%  (11/31)45%  (5/11)
newClassInfoTemplate (FormatableBitSet, int []): InstanceGetter [] 100% (1/1)74%  (29/39)76%  (6.1/8)
newRowFromClassInfoTemplate (InstanceGetter []): DataValueDescriptor [] 100% (1/1)78%  (29/37)47%  (6.1/13)
newRowFromClassInfoTemplateError (): void 0%   (0/1)0%   (0/3)0%   (0/2)
nextColumn (Object [], FormatableBitSet, int): int 100% (1/1)93%  (28/30)89%  (8/9)
qualifyRow (Object [], Qualifier [][]): boolean 100% (1/1)43%  (74/172)47%  (14.4/31)
toString (Hashtable): String 0%   (0/1)0%   (0/92)0%   (0/13)
toString (Object []): String 100% (1/1)93%  (39/42)88%  (7/8)

1/*
2 
3   Derby - Class org.apache.derby.iapi.store.access.RowUtil
4 
5   Copyright 1998, 2004 The Apache Software Foundation or its licensors, as applicable.
6 
7   Licensed under the Apache License, Version 2.0 (the "License");
8   you may not use this file except in compliance with the License.
9   You may obtain a copy of the License at
10 
11      http://www.apache.org/licenses/LICENSE-2.0
12 
13   Unless required by applicable law or agreed to in writing, software
14   distributed under the License is distributed on an "AS IS" BASIS,
15   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   See the License for the specific language governing permissions and
17   limitations under the License.
18 
19 */
20 
21package org.apache.derby.iapi.store.access;
22 
23import org.apache.derby.iapi.services.monitor.Monitor;
24 
25import org.apache.derby.iapi.services.sanity.SanityManager;
26 
27import org.apache.derby.iapi.error.StandardException; 
28import org.apache.derby.iapi.services.io.Storable;
29import org.apache.derby.iapi.types.DataValueDescriptor;
30import org.apache.derby.iapi.services.io.FormatableBitSet;
31import org.apache.derby.iapi.services.loader.InstanceGetter;
32 
33import org.apache.derby.iapi.store.raw.FetchDescriptor;
34 
35import java.lang.reflect.InvocationTargetException;
36 
37import java.util.Enumeration;
38import java.util.Hashtable;
39import java.util.Vector;
40 
41/**
42  A set of static utility methods to work with rows.
43  <P>
44  A row or partial row is described by two or three parameters.
45  <OL>
46  <LI>DataValueDescriptor[] row - an array of objects, one per column.
47  <LI>FormatableBitSet validColumns - 
48      an indication of which objects in row map to which columns
49  </OL>
50  These objects can describe a complete row or a partial row. A partial row is 
51  one where a sub-set (e.g. columns 0, 4 and 7) of the columns are supplied 
52  for update, or requested to be fetched on a read.  Here's an example
53  of code to set up a partial column list to fetch the 0th (type FOO), 
54  4th (type BAR), and 7th (type MMM) columns from a row with 10 columns, note
55  that the format for a partial row changed from a "packed" representation
56  in the 3.0 release to a "sparse" representation in later releases:
57 
58  <blockquote><pre>
59 
60  // allocate/initialize the row 
61  DataValueDescriptor row = new DataValueDescriptor[10]
62  row[0] = new FOO();
63  row[4] = new BAR();
64  row[7] = new MMM();
65  
66  // allocate/initialize the bit set 
67  FormatableBitSet FormatableBitSet = new FormatableBitSet(10);
68  
69  FormatableBitSet.set(0);
70  FormatableBitSet.set(4);
71  FormatableBitSet.set(7);
72  </blockquote></pre>
73 
74 
75  <BR><B>Column mapping<B><BR>
76  When validColumns is null:
77  <UL>
78  <LI> The number of columns is given by row.length
79  <LI> Column N maps to row[N], where column numbers start at zero.
80  </UL>
81  <BR>
82  When validColumns is not null, then
83  <UL>
84  <LI> The number of requested columns is given by the number of bits set in 
85       validColumns.
86  <LI> Column N is not in the partial row if validColumns.isSet(N) 
87       returns false.
88  <LI> Column N is in the partial row if validColumns.isSet(N) returns true.
89  <LI> If column N is in the partial row then it maps to row[N].
90           If N >= row.length then the column is taken as non existent for an
91           insert or update, and not fetched on a fetch.
92  </UL>
93  If row.length is greater than the number of columns indicated by validColumns
94  the extra entries are ignored.
95 
96**/
97public class RowUtil
98{
99        private RowUtil() {}
100 
101        /**
102                An object that can be used on a fetch to indicate no fields
103                need to be fetched.
104        */
105        public static final DataValueDescriptor[] EMPTY_ROW = 
106        new DataValueDescriptor[0];
107 
108        /**
109                An object that can be used on a fetch as a FormatableBitSet to indicate no fields
110                need to be fetched.
111        */
112        public static final FormatableBitSet EMPTY_ROW_BITSET  = 
113        new FormatableBitSet(0);
114 
115        /**
116                An object that can be used on a fetch as a FormatableBitSet to indicate no fields
117                need to be fetched.
118        */
119        public static final FetchDescriptor EMPTY_ROW_FETCH_DESCRIPTOR  = 
120        new FetchDescriptor(0);
121 
122        public static final FetchDescriptor[] ROWUTIL_FETCH_DESCRIPTOR_CONSTANTS  =
123        {EMPTY_ROW_FETCH_DESCRIPTOR,
124         new FetchDescriptor(1, 1),
125         new FetchDescriptor(2, 2),
126         new FetchDescriptor(3, 3),
127         new FetchDescriptor(4, 4),
128         new FetchDescriptor(5, 5),
129         new FetchDescriptor(6, 6),
130         new FetchDescriptor(7, 7)};
131 
132 
133        /**
134                Get the object for a column identifer (0 based) from a complete or 
135        partial row.
136 
137                @param row the row
138                @param columnList valid columns in the row
139                @param columnId which column to return (0 based)
140 
141                @return the obejct for the column, or null if the column is not represented.
142        */
143        public static DataValueDescriptor getColumn(
144    DataValueDescriptor[]   row, 
145    FormatableBitSet                 columnList, 
146    int                     columnId) 
147    {
148 
149                if (columnList == null)
150                        return columnId < row.length ? row[columnId] : null;
151 
152 
153                if (!(columnList.getLength() > columnId && columnList.isSet(columnId)))
154                        return null;
155 
156        return columnId < row.length ? row[columnId] : null;
157 
158        }
159 
160        public static Object getColumn(
161    Object[]   row, 
162    FormatableBitSet                 columnList, 
163    int                     columnId) 
164    {
165 
166                if (columnList == null)
167                        return columnId < row.length ? row[columnId] : null;
168 
169 
170                if (!(columnList.getLength() > columnId && columnList.isSet(columnId)))
171                        return null;
172 
173        return columnId < row.length ? row[columnId] : null;
174 
175        }
176 
177        /**
178                Get a FormatableBitSet representing all the columns represented in
179                a qualifier list.
180 
181                @return a FormatableBitSet describing the valid columns.
182        */
183        public static FormatableBitSet getQualifierBitSet(Qualifier[][] qualifiers) 
184    {
185                FormatableBitSet qualifierColumnList = new FormatableBitSet();
186 
187                if (qualifiers != null) 
188        {
189                        for (int i = 0; i < qualifiers.length; i++)
190                        {
191                for (int j = 0; j < qualifiers[i].length; j++)
192                {
193                    int colId = qualifiers[i][j].getColumnId();
194 
195                    // we are about to set bit colId, need length to be colId+1
196                    qualifierColumnList.grow(colId+1);
197                    qualifierColumnList.set(colId);
198                }
199                        }
200                }
201 
202                return qualifierColumnList;
203        }
204 
205    /**
206     * Get the number of columns represented by a FormatableBitSet.
207     * <p>
208     * This is simply a count of the number of bits set in the FormatableBitSet.
209     * <p>
210     *
211     * @param maxColumnNumber Because the FormatableBitSet.size() can't be used as
212     *                        the number of columns, allow caller to tell
213     *                        the maximum column number if it knows.  
214     *                        -1  means caller does not know.
215     *                        >=0 number is the largest column number.
216     *                           
217     * @param columnList valid columns in the row
218     *
219         * @return The number of columns represented in the FormatableBitSet.
220     **/
221    public static int getNumberOfColumns(
222    int     maxColumnNumber,
223    FormatableBitSet  columnList)
224    {
225        if (SanityManager.DEBUG)
226            SanityManager.ASSERT(columnList != null);
227 
228        int max_col_number = columnList.getLength();
229 
230                if (maxColumnNumber > 0 && maxColumnNumber < max_col_number)
231                        max_col_number = maxColumnNumber;
232 
233        int ret_num_cols = 0;
234 
235        for (int i = 0; i < max_col_number; i++)
236        {
237            if (columnList.isSet(i))
238                ret_num_cols++;
239        }
240 
241        return(ret_num_cols);
242    }
243 
244        /**
245                See if a row actually contains no columns.
246                Returns true if row is null or row.length is zero.
247 
248                @return true if row is empty.
249        */
250        public static boolean isRowEmpty(
251    DataValueDescriptor[]   row) 
252    {
253 
254                if (row == null)
255                        return true;
256 
257                if (row.length == 0)
258                        return true;
259 
260                return false;
261        }
262 
263        /**
264                Return the column number of the first column out of range, or a number
265        less than zero if all columns are in range.
266        */
267        public static int columnOutOfRange(
268    DataValueDescriptor[]   row, 
269    FormatableBitSet                 columnList, 
270    int                     maxColumns) 
271    {
272 
273                if (columnList == null) {
274                        if (row.length > maxColumns)
275                                return maxColumns;
276 
277                        return -1;
278                }
279 
280                int size = columnList.getLength();
281                for (int i = maxColumns; i < size; i++) {
282                        if (columnList.isSet(i))
283                                return i;
284                }
285 
286                return -1;
287        }
288 
289        /**
290                Get the next valid column after or including start column.
291                Returns -1 if no valid columns exist after startColumn
292        */
293        public static int nextColumn(
294    Object[]   row, 
295    FormatableBitSet                 columnList, 
296    int                     startColumn) 
297    {
298 
299                if (columnList != null) {
300 
301                        int size = columnList.getLength();
302 
303                        for (; startColumn < size; startColumn++) {
304                                if (columnList.isSet(startColumn)) {
305                                        return startColumn;
306                                }
307                        }
308 
309                        return -1;
310                }
311 
312                if (row == null)
313                        return -1;
314 
315                return startColumn < row.length ? startColumn : -1;
316        }
317 
318    /**
319     * Return a FetchDescriptor which describes a single column set.
320     * <p>
321     * This routine returns one of a set of constant FetchDescriptor's, and
322     * should not be altered by the caller.
323     **/
324    public static final FetchDescriptor getFetchDescriptorConstant(
325    int     single_column_number)
326    {
327        if (single_column_number < ROWUTIL_FETCH_DESCRIPTOR_CONSTANTS.length)
328        {
329            return(ROWUTIL_FETCH_DESCRIPTOR_CONSTANTS[single_column_number]);
330        }
331        else
332        {
333            return(
334                new FetchDescriptor(
335                    single_column_number, single_column_number));
336        }
337    }
338 
339    /**************************************************************************
340     * Public Methods dealing with cloning and row copying util functions
341     **************************************************************************
342     */
343 
344    /**
345     * Generate a row of InstanceGetter objects to be used to generate  "empty" rows.
346     * <p>
347     * Generate an array of InstanceGetter objects which will be used to make
348     * repeated calls to newRowFromClassInfoTemplate(), to repeatedly and
349     * efficiently generate new rows.  This is important for certain 
350     * applications like the sorter and fetchSet which generate large numbers
351     * of "new" empty rows.
352     * <p>
353     *
354         * @return The new row.
355     *
356     * @param format_ids an array of format id's, one per column in row.
357     *
358         * @exception  StandardException  Standard exception policy.
359     **/
360    public static InstanceGetter[] newClassInfoTemplate(
361    FormatableBitSet column_list,
362    int[]    format_ids) 
363        throws StandardException
364    {
365        int         num_cols = format_ids.length;
366        InstanceGetter[] ret_row  = new InstanceGetter[num_cols];
367 
368                int column_listSize = 
369            (column_list == null) ? 0 : column_list.getLength();
370 
371        for (int i = 0; i < num_cols; i++)
372        {
373            // does caller want this column?
374            if ((column_list != null)   && 
375                !((column_listSize > i) && 
376                (column_list.isSet(i))))
377            {
378                // no - column should be skipped.
379            }
380            else
381            {
382                // yes - create the column 
383 
384                // get empty instance of object identified by the format id.
385 
386                ret_row[i] = Monitor.classFromIdentifier(format_ids[i]);
387            }
388        }
389 
390        return(ret_row);
391    }
392 
393 
394    private static void newRowFromClassInfoTemplateError()
395    {
396        if (SanityManager.DEBUG)
397            SanityManager.THROWASSERT(
398                "unexpected error in newRowFromClassInfoTemplate()");
399    }
400 
401    /**
402     * Generate an "empty" row from an array of classInfo objects.
403     * <p>
404     * Generate an array of new'd objects by using the getNewInstance()
405     * method on each of the InstanceGetter objects.  It is more
406     * efficient to allocate new objects based on this "cache'd"
407     * InstanceGetter object than to call the Monitor to generate a new class
408     * from a format id.
409     * <p>
410     *
411         * @return The new row.
412     *
413     * @param classinfo_template   An array of InstanceGetter objects each of 
414     *                             which can be used to create a new instance 
415     *                             of the appropriate type to build a new empty
416     *                             template row.
417     *
418         * @exception  StandardException  Standard exception policy.
419     **/
420    public static DataValueDescriptor[] newRowFromClassInfoTemplate(
421    InstanceGetter[]    classinfo_template) 
422        throws StandardException
423    {
424 
425        DataValueDescriptor[] columns = 
426            new DataValueDescriptor[classinfo_template.length];
427 
428        try
429        {
430            for (int column_index = classinfo_template.length; 
431                 column_index-- > 0;)
432            {
433                if (classinfo_template[column_index] != null)
434                {
435                    // get empty instance of DataValueDescriptor identified by 
436                    // the format id.
437                    columns[column_index] = (DataValueDescriptor) 
438                        classinfo_template[column_index].getNewInstance();
439                }
440            }
441        }
442        catch (InstantiationException ie)
443        {
444            newRowFromClassInfoTemplateError();
445        }
446        catch (IllegalAccessException iae)
447        {
448            newRowFromClassInfoTemplateError();
449        }
450        catch (InvocationTargetException ite)
451        {
452            newRowFromClassInfoTemplateError();
453        }
454 
455                return columns;
456    }
457 
458 
459    /**
460     * return string version of row.
461     * <p>
462     * For debugging only. 
463     *
464         * @return The string version of row.
465     *
466     * @param row The row.
467     *
468     **/
469    public static String toString(Object[] row)
470    {
471        if (SanityManager.DEBUG)
472        {
473 
474            String str = new String();
475 
476            if (row != null)
477            {
478                if (row.length == 0)
479                {
480                    str = "empty row";
481                }
482                else
483                {
484                    for (int i = 0; i < row.length; i++)
485                        str += "col[" + i + "]=" + row[i];
486                }
487            }
488            else
489            {
490                str = "row is null";
491            }
492 
493            return(str);
494        }
495        else
496        {
497            return(null);
498        }
499    }
500 
501    /**
502     * return string version of a HashTable returned from a FetchSet.
503     * <p>
504     *
505         * @return The string version of row.
506     *
507     *
508     **/
509 
510    // For debugging only. 
511    public static String toString(Hashtable hash_table)
512    {
513        if (SanityManager.DEBUG)
514        {
515            String str = new String();
516 
517            Object  row_or_vector;
518 
519            for (Enumeration e = hash_table.elements(); e.hasMoreElements();)
520            {
521                row_or_vector = e.nextElement();
522 
523                if (row_or_vector instanceof Object[])
524                {
525                    // it's a row
526                    str += RowUtil.toString((Object[]) row_or_vector);
527                    str += "\n";
528                }
529                else if (row_or_vector instanceof Vector)
530                {
531                    // it's a vector
532                    Vector vec = (Vector) row_or_vector;
533 
534                    for (int i = 0; i < vec.size(); i++)
535                    {
536                        str += 
537                            "vec[" + i + "]:" + 
538                            RowUtil.toString((Object[]) vec.elementAt(i));
539 
540                        str += "\n";
541                    }
542                }
543                else
544                {
545                    str += "BAD ENTRY\n";
546                }
547            }
548            return(str);
549        }
550        else
551        {
552            return(null);
553        }
554    }
555 
556    /**
557     * Process the qualifier list on the row, return true if it qualifies.
558     * <p>
559     * A two dimensional array is to be used to pass around a AND's and OR's in
560     * conjunctive normal form.  The top slot of the 2 dimensional array is 
561     * optimized for the more frequent where no OR's are present.  The first 
562     * array slot is always a list of AND's to be treated as described above 
563     * for single dimensional AND qualifier arrays.  The subsequent slots are 
564     * to be treated as AND'd arrays or OR's.  Thus the 2 dimensional array 
565     * qual[][] argument is to be treated as the following, note if 
566     * qual.length = 1 then only the first array is valid and it is and an 
567     * array of and clauses:
568     *
569     * (qual[0][0] and qual[0][0] ... and qual[0][qual[0].length - 1])
570     * and
571     * (qual[1][0] or  qual[1][1] ... or  qual[1][qual[1].length - 1])
572     * and
573     * (qual[2][0] or  qual[2][1] ... or  qual[2][qual[2].length - 1])
574     * ...
575     * and
576     * (qual[qual.length - 1][0] or  qual[1][1] ... or  qual[1][2])
577     *
578     * 
579         * @return true if the row qualifies.
580     *
581     * @param row               The row being qualified.
582     * @param qual_list         2 dimensional array representing conjunctive
583     *                          normal form of simple qualifiers.
584     *
585         * @exception  StandardException  Standard exception policy.
586     **/
587        public static final boolean qualifyRow(
588    Object[]        row, 
589    Qualifier[][]   qual_list)
590                 throws StandardException
591        {
592        boolean     row_qualifies = true;
593 
594        if (SanityManager.DEBUG)
595        {
596            SanityManager.ASSERT(row != null);
597        }
598 
599        // First do the qual[0] which is an array of qualifer terms.
600 
601        if (SanityManager.DEBUG)
602        {
603            // routine should not be called if there is no qualifier
604            SanityManager.ASSERT(qual_list != null);
605            SanityManager.ASSERT(qual_list.length > 0);
606        }
607 
608        for (int i = 0; i < qual_list[0].length; i++)
609        {
610            // process each AND clause 
611 
612            row_qualifies = false;
613 
614            // process each OR clause.
615 
616            Qualifier q = qual_list[0][i];
617 
618            // Get the column from the possibly partial row, of the 
619            // q.getColumnId()'th column in the full row.
620            DataValueDescriptor columnValue = 
621                    (DataValueDescriptor) row[q.getColumnId()];
622 
623            row_qualifies =
624                columnValue.compare(
625                    q.getOperator(),
626                    q.getOrderable(),
627                    q.getOrderedNulls(),
628                    q.getUnknownRV());
629 
630            if (q.negateCompareResult())
631                row_qualifies = !row_qualifies;
632 
633            // Once an AND fails the whole Qualification fails - do a return!
634            if (!row_qualifies)
635                return(false);
636        }
637 
638        // all the qual[0] and terms passed, now process the OR clauses
639 
640        for (int and_idx = 1; and_idx < qual_list.length; and_idx++)
641        {
642            // loop through each of the "and" clause.
643 
644            row_qualifies = false;
645 
646            if (SanityManager.DEBUG)
647            {
648                // Each OR clause must be non-empty.
649                SanityManager.ASSERT(qual_list[and_idx].length > 0);
650            }
651 
652            for (int or_idx = 0; or_idx < qual_list[and_idx].length; or_idx++)
653            {
654                // Apply one qualifier to the row.
655                Qualifier q      = qual_list[and_idx][or_idx];
656                int       col_id = q.getColumnId();
657 
658                if (SanityManager.DEBUG)
659                {
660                    SanityManager.ASSERT(
661                        (col_id < row.length),
662                        "Qualifier is referencing a column not in the row.");
663                }
664 
665                // Get the column from the possibly partial row, of the 
666                // q.getColumnId()'th column in the full row.
667                DataValueDescriptor columnValue = 
668                    (DataValueDescriptor) row[q.getColumnId()];
669 
670                if (SanityManager.DEBUG)
671                {
672                    if (columnValue == null)
673                        SanityManager.THROWASSERT(
674                            "1:row = " + RowUtil.toString(row) +
675                            "row.length = " + row.length +
676                            ";q.getColumnId() = " + q.getColumnId());
677                }
678 
679                // do the compare between the column value and value in the
680                // qualifier.
681                row_qualifies = 
682                    columnValue.compare(
683                            q.getOperator(),
684                            q.getOrderable(),
685                            q.getOrderedNulls(),
686                            q.getUnknownRV());
687 
688                if (q.negateCompareResult())
689                    row_qualifies = !row_qualifies;
690 
691                // SanityManager.DEBUG_PRINT("StoredPage.qual", "processing qual[" + and_idx + "][" + or_idx + "] = " + qual_list[and_idx][or_idx] );
692 
693                // SanityManager.DEBUG_PRINT("StoredPage.qual", "value = " + row_qualifies);
694 
695                // processing "OR" clauses, so as soon as one is true, break
696                // to go and process next AND clause.
697                if (row_qualifies)
698                    break;
699 
700            }
701 
702            // The qualifier list represented a set of "AND'd" 
703            // qualifications so as soon as one is false processing is done.
704            if (!row_qualifies)
705                break;
706        }
707 
708        return(row_qualifies);
709    }
710 
711}

[all classes][org.apache.derby.iapi.store.access]
EMMA 2.0.5312 (C) Vladimir Roubtsov