Source Code Cross Referenced for ResultColumnList.java in  » Database-DBMS » db-derby-10.2 » org » apache » derby » impl » sql » compile » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Database DBMS » db derby 10.2 » org.apache.derby.impl.sql.compile 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:           Derby - Class org.apache.derby.impl.sql.compile.ResultColumnList
0003:
0004:           Licensed to the Apache Software Foundation (ASF) under one or more
0005:           contributor license agreements.  See the NOTICE file distributed with
0006:           this work for additional information regarding copyright ownership.
0007:           The ASF licenses this file to you under the Apache License, Version 2.0
0008:           (the "License"); you may not use this file except in compliance with
0009:           the License.  You may obtain a copy of the License at
0010:
0011:              http://www.apache.org/licenses/LICENSE-2.0
0012:
0013:           Unless required by applicable law or agreed to in writing, software
0014:           distributed under the License is distributed on an "AS IS" BASIS,
0015:           WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0016:           See the License for the specific language governing permissions and
0017:           limitations under the License.
0018:
0019:         */
0020:
0021:        package org.apache.derby.impl.sql.compile;
0022:
0023:        import org.apache.derby.iapi.services.context.ContextManager;
0024:        import org.apache.derby.iapi.services.compiler.MethodBuilder;
0025:        import org.apache.derby.iapi.services.compiler.LocalField;
0026:
0027:        import org.apache.derby.iapi.services.sanity.SanityManager;
0028:        import org.apache.derby.iapi.services.monitor.Monitor;
0029:        import org.apache.derby.iapi.services.loader.ClassFactory;
0030:        import org.apache.derby.iapi.services.io.Storable;
0031:        import org.apache.derby.iapi.services.context.ContextManager;
0032:
0033:        import org.apache.derby.iapi.error.StandardException;
0034:
0035:        import org.apache.derby.iapi.sql.compile.NodeFactory;
0036:        import org.apache.derby.iapi.sql.compile.CompilerContext;
0037:        import org.apache.derby.iapi.sql.compile.C_NodeTypes;
0038:
0039:        import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
0040:
0041:        import org.apache.derby.iapi.sql.dictionary.ColumnDescriptor;
0042:        import org.apache.derby.iapi.sql.dictionary.ColumnDescriptorList;
0043:        import org.apache.derby.iapi.sql.dictionary.DataDictionary;
0044:        import org.apache.derby.iapi.sql.dictionary.DataDictionaryContext;
0045:        import org.apache.derby.iapi.sql.dictionary.DefaultDescriptor;
0046:        import org.apache.derby.iapi.sql.dictionary.TableDescriptor;
0047:        import org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptor;
0048:
0049:        import org.apache.derby.iapi.types.TypeId;
0050:        import org.apache.derby.iapi.services.classfile.VMOpcode;
0051:        import org.apache.derby.iapi.util.JBitSet;
0052:
0053:        import org.apache.derby.iapi.reference.SQLState;
0054:
0055:        import org.apache.derby.iapi.reference.SQLState;
0056:
0057:        import org.apache.derby.iapi.sql.Activation;
0058:
0059:        import org.apache.derby.iapi.sql.ResultColumnDescriptor;
0060:        import org.apache.derby.iapi.sql.Row;
0061:        import org.apache.derby.iapi.types.TypeId;
0062:
0063:        import org.apache.derby.iapi.sql.execute.ExecRow;
0064:        import org.apache.derby.iapi.sql.execute.ExecIndexRow;
0065:        import org.apache.derby.iapi.sql.execute.ExecutionFactory;
0066:        import org.apache.derby.iapi.sql.execute.ExecutionContext;
0067:
0068:        import org.apache.derby.iapi.types.DataTypeDescriptor;
0069:        import org.apache.derby.iapi.types.DataValueDescriptor;
0070:        import org.apache.derby.iapi.types.RowLocation;
0071:
0072:        import org.apache.derby.iapi.store.access.ConglomerateController;
0073:        import org.apache.derby.iapi.store.access.StoreCostController;
0074:        import org.apache.derby.iapi.store.access.TransactionController;
0075:
0076:        import org.apache.derby.iapi.services.loader.GeneratedMethod;
0077:
0078:        import org.apache.derby.impl.sql.compile.ActivationClassBuilder;
0079:        import org.apache.derby.impl.sql.compile.ExpressionClassBuilder;
0080:
0081:        import org.apache.derby.iapi.services.io.FormatableBitSet;
0082:        import org.apache.derby.iapi.reference.ClassName;
0083:
0084:        import org.apache.derby.catalog.types.DefaultInfoImpl;
0085:
0086:        import java.lang.reflect.Modifier;
0087:
0088:        import org.apache.derby.iapi.util.ReuseFactory;
0089:        import org.apache.derby.iapi.services.classfile.VMOpcode;
0090:
0091:        import java.sql.ResultSetMetaData;
0092:        import java.sql.SQLException;
0093:        import java.sql.Types;
0094:
0095:        import java.util.Hashtable;
0096:        import java.util.Vector;
0097:
0098:        /**
0099:         * A ResultColumnList is the target list of a SELECT, INSERT, or UPDATE.
0100:         *
0101:         * @see ResultColumn
0102:         */
0103:
0104:        public class ResultColumnList extends QueryTreeNodeVector {
0105:            /* Is this the ResultColumnList for an index row? */
0106:            protected boolean indexRow;
0107:            protected long conglomerateId;
0108:
0109:            int orderBySelect = 0; // the number of result columns pulled up
0110:            // from ORDERBY list
0111:            /*
0112:             * A comment on 'orderBySelect'. When we encounter a SELECT .. ORDER BY
0113:             * statement, the columns (or expressions) in the ORDER BY clause may
0114:             * or may not have been explicitly mentioned in the SELECT column list.
0115:             * If the columns were NOT explicitly mentioned in the SELECT column
0116:             * list, then the parsing of the ORDER BY clause implicitly generates
0117:             * them into the result column list, because we'll need to have those
0118:             * columns present at execution time in order to sort by them. Those
0119:             * generated columns are added to the *end* of the ResultColumnList, and
0120:             * we keep track of the *number* of those columns in 'orderBySelect',
0121:             * so we can tell whether we are looking at a generated column by seeing
0122:             * whether its position in the ResultColumnList is in the last
0123:             * 'orderBySelect' number of columns. If the SELECT .. ORDER BY
0124:             * statement uses the "*" token to select all the columns from a table,
0125:             * then during ORDER BY parsing we redundantly generate the columns
0126:             * mentioned in the ORDER BY clause into the ResultColumnlist, but then
0127:             * later in getOrderByColumn we determine that these are duplicates and
0128:             * we take them back out again.
0129:             */
0130:
0131:            /*
0132:             ** Is this ResultColumnList for a FromBaseTable for an index
0133:             ** that is to be updated?
0134:             */
0135:            protected boolean forUpdate;
0136:
0137:            // Is a count mismatch allowed - see set/get methods for details.
0138:            private boolean countMismatchAllowed;
0139:
0140:            // Number of RCs in this RCL at "init" time, before additional
0141:            // ones were added internally.
0142:            private int initialListSize = 0;
0143:
0144:            public ResultColumnList() {
0145:            }
0146:
0147:            /**
0148:             * Add a ResultColumn (at this point, ResultColumn or
0149:             * AllResultColumn) to the list
0150:             *
0151:             * @param resultColumn	The ResultColumn to add to the list
0152:             */
0153:
0154:            public void addResultColumn(ResultColumn resultColumn) {
0155:                /* Vectors are 0-based, ResultColumns are 1-based */
0156:                resultColumn.setVirtualColumnId(size() + 1);
0157:                addElement(resultColumn);
0158:            }
0159:
0160:            /**
0161:             * Append a given ResultColumnList to this one, resetting the virtual
0162:             * column ids in the appended portion.
0163:             *
0164:             * @param resultColumns		The ResultColumnList to be appended
0165:             * @param destructiveCopy	Whether or not this is a descructive copy
0166:             *							from resultColumns
0167:             */
0168:            public void appendResultColumns(ResultColumnList resultColumns,
0169:                    boolean destructiveCopy) {
0170:                int oldSize = size();
0171:                int newID = oldSize + 1;
0172:
0173:                /*
0174:                 ** Set the virtual column ids in the list being appended.
0175:                 ** Vectors are zero-based, and virtual column ids are one-based,
0176:                 ** so the new virtual column ids start at the original size
0177:                 ** of this list, plus one.
0178:                 */
0179:                int otherSize = resultColumns.size();
0180:                for (int index = 0; index < otherSize; index++) {
0181:                    /* ResultColumns are 1-based */
0182:                    ((ResultColumn) resultColumns.elementAt(index))
0183:                            .setVirtualColumnId(newID);
0184:                    newID++;
0185:                }
0186:
0187:                if (destructiveCopy) {
0188:                    destructiveAppend(resultColumns);
0189:                } else {
0190:                    nondestructiveAppend(resultColumns);
0191:                }
0192:            }
0193:
0194:            /**
0195:             * Get a ResultColumn from a column position (1-based) in the list
0196:             *
0197:             * @param position	The ResultColumn to get from the list (1-based)
0198:             *
0199:             * @return	the column at that position.
0200:             */
0201:
0202:            public ResultColumn getResultColumn(int position) {
0203:                /*
0204:                 ** First see if it falls in position x.  If not,
0205:                 ** search the whole shebang
0206:                 */
0207:                if (position <= size()) {
0208:                    // this wraps the cast needed, 
0209:                    // and the 0-based nature of the Vectors.
0210:                    ResultColumn rc = (ResultColumn) elementAt(position - 1);
0211:                    if (rc.getColumnPosition() == position) {
0212:                        return rc;
0213:                    }
0214:                }
0215:
0216:                /*
0217:                 ** Check each column
0218:                 */
0219:                int size = size();
0220:                for (int index = 0; index < size; index++) {
0221:                    ResultColumn rc = (ResultColumn) elementAt(index);
0222:                    if (rc.getColumnPosition() == position) {
0223:                        return rc;
0224:                    }
0225:                }
0226:                return null;
0227:            }
0228:
0229:            /**
0230:             * Take a column position and a ResultSetNode and find the ResultColumn
0231:             * in this RCL whose source result set is the same as the received
0232:             * RSN and whose column position is the same as the received column
0233:             * position.
0234:             *
0235:             * @param colNum The column position (w.r.t rsn) for which we're searching
0236:             * @param rsn The result set node for which we're searching.
0237:             * @return The ResultColumn in this RCL whose source is column colNum
0238:             *  in result set rsn.  That ResultColumn's position w.r.t to this RCL
0239:             *  is also returned via the whichRC parameter.  If no match is found,
0240:             *  return null and leave whichRC untouched.
0241:             */
0242:            public ResultColumn getResultColumn(int colNum, ResultSetNode rsn,
0243:                    int[] whichRC) throws StandardException {
0244:                if (colNum == -1)
0245:                    return null;
0246:
0247:                ResultColumn rc = null;
0248:                ColumnReference colRef = null;
0249:                int[] crColNum = new int[] { -1 };
0250:
0251:                for (int index = size() - 1; index >= 0; index--) {
0252:                    rc = (ResultColumn) elementAt(index);
0253:                    if (!(rc.getExpression() instanceof  ColumnReference)) {
0254:                        // If the rc's expression isn't a column reference then
0255:                        // it can't be pointing to rsn, so just skip it.
0256:                        continue;
0257:                    }
0258:
0259:                    colRef = (ColumnReference) rc.getExpression();
0260:                    if ((rsn == colRef.getSourceResultSet(crColNum))
0261:                            && (crColNum[0] == colNum)) {
0262:                        // Found a match.
0263:                        whichRC[0] = index + 1;
0264:                        return rc;
0265:                    }
0266:                }
0267:
0268:                return null;
0269:            }
0270:
0271:            /**
0272:             * Get a ResultColumn from a column position (1-based) in the list,
0273:             * null if out of range (for order by).
0274:             *
0275:             * @param position	The ResultColumn to get from the list (1-based)
0276:             *
0277:             * @return	the column at that position, null if out of range
0278:             */
0279:            public ResultColumn getOrderByColumn(int position) {
0280:                // this wraps the cast needed, and the 0-based nature of the Vectors.
0281:                if (position == 0)
0282:                    return null;
0283:
0284:                return getResultColumn(position);
0285:            }
0286:
0287:            /**
0288:             * Get a ResultColumn that matches the specified columnName and
0289:             * mark the ResultColumn as being referenced.
0290:             *
0291:             * @param columnName	The ResultColumn to get from the list
0292:             *
0293:             * @return	the column that matches that name.
0294:             */
0295:
0296:            public ResultColumn getResultColumn(String columnName) {
0297:                int size = size();
0298:                for (int index = 0; index < size; index++) {
0299:                    ResultColumn resultColumn = (ResultColumn) elementAt(index);
0300:                    if (columnName.equals(resultColumn.getName())) {
0301:                        /* Mark ResultColumn as referenced and return it */
0302:                        resultColumn.setReferenced();
0303:                        return resultColumn;
0304:                    }
0305:                }
0306:                return null;
0307:            }
0308:
0309:            /**
0310:             * Get a ResultColumn that matches the specified columnName and
0311:             * mark the ResultColumn as being referenced.
0312:             *
0313:             * @param columnsTableName	Qualifying name for the column
0314:             * @param columnName		The ResultColumn to get from the list
0315:             *
0316:             * @return	the column that matches that name.
0317:             */
0318:
0319:            public ResultColumn getResultColumn(String columnsTableName,
0320:                    String columnName) {
0321:                int size = size();
0322:                for (int index = 0; index < size; index++) {
0323:                    ResultColumn resultColumn = (ResultColumn) elementAt(index);
0324:
0325:                    /* If the column's table name is non-null, then we have found a match
0326:                     * only if the RC's table name is non-null and the same as the
0327:                     * the CR's table name.
0328:                     */
0329:                    if (columnsTableName != null) {
0330:                        if (resultColumn.getTableName() == null) {
0331:                            continue;
0332:                        }
0333:
0334:                        if (!columnsTableName.equals(resultColumn
0335:                                .getTableName())) {
0336:                            continue;
0337:                        }
0338:                    }
0339:                    if (columnName.equals(resultColumn.getName())) {
0340:                        /* Mark ResultColumn as referenced and return it */
0341:                        resultColumn.setReferenced();
0342:                        return resultColumn;
0343:                    }
0344:                }
0345:                return null;
0346:            }
0347:
0348:            /**
0349:             * Get a ResultColumn that matches the specified columnName and
0350:             * mark the ResultColumn as being referenced.
0351:             * NOTE - this flavor enforces no ambiguity (at most 1 match)
0352:             *		  Only FromSubquery needs to call this flavor since
0353:             *		  it can have ambiguous references in its own list.
0354:             *
0355:             * @param cr					The ColumnReference to resolve
0356:             * @param exposedTableName		Exposed table name for FromTable
0357:             *
0358:             * @return	the column that matches that name.
0359:             *
0360:             * @exception StandardException	Thrown on error
0361:             */
0362:
0363:            public ResultColumn getAtMostOneResultColumn(ColumnReference cr,
0364:                    String exposedTableName) throws StandardException {
0365:                int size = size();
0366:                ResultColumn retRC = null;
0367:                String columnName = cr.getColumnName();
0368:
0369:                for (int index = 0; index < size; index++) {
0370:                    ResultColumn resultColumn = (ResultColumn) elementAt(index);
0371:
0372:                    if (columnName.equals(resultColumn.getName())) {
0373:                        /* We should get at most 1 match */
0374:                        if (retRC != null) {
0375:                            throw StandardException
0376:                                    .newException(
0377:                                            SQLState.LANG_AMBIGUOUS_COLUMN_NAME_IN_TABLE,
0378:                                            columnName, exposedTableName);
0379:                        }
0380:                        /* Mark ResultColumn as referenced and return it */
0381:                        resultColumn.setReferenced();
0382:                        retRC = resultColumn;
0383:                    }
0384:                }
0385:                return retRC;
0386:            }
0387:
0388:            /**
0389:             * For order by, get a ResultColumn that matches the specified 
0390:             * columnName.
0391:             *
0392:             * @param columnName	The ResultColumn to get from the list
0393:             * @param tableName	The table name on the OrderByColumn, if any
0394:             * @param tableNumber	The tableNumber corresponding to the FromTable with the
0395:             *						exposed name of tableName, if tableName != null.
0396:             *
0397:             * @return	the column that matches that name.
0398:             * @exception StandardException thrown on ambiguity
0399:             */
0400:            public ResultColumn getOrderByColumn(String columnName,
0401:                    TableName tableName, int tableNumber)
0402:                    throws StandardException {
0403:                int size = size();
0404:                ResultColumn retVal = null, resultColumn;
0405:
0406:                for (int index = 0; index < size; index++) {
0407:                    resultColumn = (ResultColumn) elementAt(index);
0408:
0409:                    /* The order by column is qualified, then it is okay to consider
0410:                     * this RC if:
0411:                     *	o  The RC is qualified and the qualifiers on the order by column
0412:                     *	   and the RC are equal().
0413:                     *	o  The RC is not qualified, but its expression is a ColumnReference
0414:                     *	   from the same table (as determined by the tableNumbers).
0415:                     */
0416:                    if (tableName != null) {
0417:                        ValueNode rcExpr = resultColumn.getExpression();
0418:                        if (!(rcExpr instanceof  ColumnReference))
0419:                            continue;
0420:
0421:                        ColumnReference cr = (ColumnReference) rcExpr;
0422:                        if ((!tableName.equals(cr.getTableNameNode()))
0423:                                && tableNumber != cr.getTableNumber())
0424:                            continue;
0425:                    }
0426:
0427:                    /* We finally got past the qualifiers, now see if the column
0428:                     * names are equal. If they are, then we appear to have found
0429:                     * our order by column. If we find our order by column multiple
0430:                     * times, make sure that they are truly duplicates, otherwise
0431:                     * we have an ambiguous situation. For example, the query
0432:                     *   SELECT b+c AS a, d+e AS a FROM t ORDER BY a
0433:                     * is ambiguous because we don't know which "a" is meant. But
0434:                     *   SELECT t.a, t.* FROM t ORDER BY a
0435:                     * is not ambiguous, even though column "a" is selected twice.
0436:                     * If we find our ORDER BY column at the end of the
0437:                     * SELECT column list, in the last 'orderBySelect' number
0438:                     * of columns, then this column was not explicitly mentioned
0439:                     * by the user in their SELECT column list, but was implicitly 
0440:                     * added by the parsing of the ORDER BY clause, and it
0441:                     * should be removed from the ResultColumnList and returned
0442:                     * to the caller.
0443:                     */
0444:                    if (columnName.equals(resultColumn.getName())) {
0445:                        if (retVal == null) {
0446:                            retVal = resultColumn;
0447:                        } else if (!retVal.isEquivalent(resultColumn)) {
0448:                            throw StandardException
0449:                                    .newException(
0450:                                            SQLState.LANG_DUPLICATE_COLUMN_FOR_ORDER_BY,
0451:                                            columnName);
0452:                        } else if (index >= size - orderBySelect) {// remove the column due to pullup of orderby item
0453:                            removeElement(resultColumn);
0454:                            decOrderBySelect();
0455:                            break;
0456:                        }
0457:                    }
0458:                }
0459:                return retVal;
0460:            }
0461:
0462:            /**
0463:             * For order by, get a ResultColumn that matches the specified 
0464:             * columnName.
0465:             *
0466:             * @param columnName	The ResultColumn to get from the list
0467:             * @param tableName	The table name on the OrderByColumn, if any
0468:             *
0469:             * @return	the column that matches that name.
0470:             * @exception StandardException thrown on ambiguity
0471:             */
0472:            public ResultColumn getOrderByColumn(String columnName,
0473:                    TableName tableName) throws StandardException {
0474:                int size = size();
0475:                ResultColumn retVal = null, resultColumn;
0476:
0477:                for (int index = 0; index < size; index++) {
0478:                    resultColumn = (ResultColumn) elementAt(index);
0479:
0480:                    // We may be checking on "ORDER BY T.A" against "SELECT *".
0481:                    // exposedName will not be null and "*" will not have an expression
0482:                    // or tablename.
0483:                    // We may be checking on "ORDER BY T.A" against "SELECT T.B, T.A".
0484:                    if (tableName != null) {
0485:                        ValueNode rcExpr = resultColumn.getExpression();
0486:                        if (rcExpr == null
0487:                                || !(rcExpr instanceof  ColumnReference)) {
0488:                            continue;
0489:                        }
0490:                        ColumnReference cr = (ColumnReference) rcExpr;
0491:                        if (!tableName.equals(cr.getTableNameNode()))
0492:                            continue;
0493:                    }
0494:
0495:                    /* We finally got past the qualifiers, now see if the column
0496:                     * names are equal.
0497:                     */
0498:                    if (columnName.equals(resultColumn.getName())) {
0499:                        if (retVal == null) {
0500:                            retVal = resultColumn;
0501:                        } else if (!retVal.isEquivalent(resultColumn)) {
0502:                            throw StandardException
0503:                                    .newException(
0504:                                            SQLState.LANG_DUPLICATE_COLUMN_FOR_ORDER_BY,
0505:                                            columnName);
0506:                        } else if (index >= size - orderBySelect) {// remove the column due to pullup of orderby item
0507:                            removeElement(resultColumn);
0508:                            decOrderBySelect();
0509:                            break;
0510:                        }
0511:                    }
0512:                }
0513:                return retVal;
0514:            }
0515:
0516:            /**
0517:             * Copy the result column names from the given ResultColumnList
0518:             * to this ResultColumnList.  This is useful for insert-select,
0519:             * where the columns being inserted into may be different from
0520:             * the columns being selected from.  The result column list for
0521:             * an insert is supposed to have the column names being inserted
0522:             * into.
0523:             *
0524:             * @param nameList	The ResultColumnList from which to copy
0525:             *			the column names
0526:             */
0527:
0528:            void copyResultColumnNames(ResultColumnList nameList) {
0529:                /* List checking is done during bind().  Lists should be the
0530:                 * same size when we are called.
0531:                 */
0532:                if (SanityManager.DEBUG) {
0533:                    if ((!countMismatchAllowed) && size() != nameList.size()) {
0534:                        SanityManager
0535:                                .THROWASSERT("The size of the 2 lists is expected to be the same. size() = "
0536:                                        + size()
0537:                                        + ", nameList.size() = "
0538:                                        + nameList.size());
0539:                    }
0540:                }
0541:
0542:                int size = (countMismatchAllowed) ? nameList.size() : size();
0543:                for (int index = 0; index < size; index++) {
0544:                    ResultColumn this ResultColumn = (ResultColumn) elementAt(index);
0545:                    ResultColumn nameListResultColumn = (ResultColumn) nameList
0546:                            .elementAt(index);
0547:                    this ResultColumn.setName(nameListResultColumn.getName());
0548:                    this ResultColumn.setNameGenerated(nameListResultColumn
0549:                            .isNameGenerated());
0550:                }
0551:            }
0552:
0553:            /**
0554:             * This class needs a treePrint method, even though it is not a
0555:             * descendant of QueryTreeNode, because its members contain tree
0556:             * nodes, and these have to be printed and indented properly.
0557:             *
0558:             * @param depth		The depth at which to indent the sub-nodes
0559:             */
0560:
0561:            public void treePrint(int depth) {
0562:                if (SanityManager.DEBUG) {
0563:                    for (int index = 0; index < size(); index++) {
0564:                        ((ResultColumn) elementAt(index)).treePrint(depth);
0565:                    }
0566:                }
0567:            }
0568:
0569:            /**
0570:             * Bind the expressions in this ResultColumnList.  This means binding
0571:             * the expression under each ResultColumn node.
0572:             *
0573:             * @param fromList		The FROM list for the query this
0574:             *				expression is in, for binding columns.
0575:             * @param subqueryList		The subquery list being built as we find SubqueryNodes
0576:             * @param aggregateVector	The aggregate vector being built as we find AggregateNodes
0577:             *
0578:             * @exception StandardException		Thrown on error
0579:             */
0580:            public void bindExpressions(FromList fromList,
0581:                    SubqueryList subqueryList, Vector aggregateVector)
0582:                    throws StandardException {
0583:                /* First we expand the *'s in the result column list */
0584:                expandAllsAndNameColumns(fromList);
0585:
0586:                /* Now we bind each result column */
0587:                int size = size();
0588:                for (int index = 0; index < size; index++) {
0589:                    ValueNode vn = (ValueNode) elementAt(index);
0590:                    vn = ((ResultColumn) vn).bindExpression(fromList,
0591:                            subqueryList, aggregateVector);
0592:                    setElementAt(vn, index);
0593:                }
0594:            }
0595:
0596:            /**
0597:             * Bind the result columns to the expressions that live under them.
0598:             * All this does is copy the datatype information to from each expression
0599:             * to each result column.  This is useful for SELECT statements, where
0600:             * the result type of each column is the type of the column's expression.
0601:             *
0602:             * @exception StandardException		Thrown on error
0603:             */
0604:            public void bindResultColumnsToExpressions()
0605:                    throws StandardException {
0606:                int size = size();
0607:                for (int index = 0; index < size; index++) {
0608:                    ((ResultColumn) elementAt(index))
0609:                            .bindResultColumnToExpression();
0610:                }
0611:            }
0612:
0613:            /**
0614:             * Bind the result columns by their names.  This is useful for GRANT and REVOKE statements
0615:             * like "GRANT SELECT ON t(c1,c1,c3) TO george", where the user specified a column list.
0616:             * This method does not check for duplicate column names.
0617:             *
0618:             * @param targetTableDescriptor	The descriptor for the table
0619:             *
0620:             * @exception StandardException		Thrown on error
0621:             */
0622:            public void bindResultColumnsByName(
0623:                    TableDescriptor targetTableDescriptor)
0624:                    throws StandardException {
0625:                int size = size();
0626:
0627:                for (int index = 0; index < size; index++) {
0628:                    ResultColumn rc = (ResultColumn) elementAt(index);
0629:
0630:                    rc.bindResultColumnByName(targetTableDescriptor, index + 1);
0631:                }
0632:            } // end of bindResultColumnsByName( TableDescriptor)
0633:
0634:            /**
0635:             * Bind the result columns by their names.  This is useful for update, grant, and revoke
0636:             * statements, and for INSERT statements like "insert into t (a, b, c)
0637:             * values (1, 2, 3)" where the user specified a column list.
0638:             * If the statment is an insert or update verify that the result column list does not contain any duplicates.
0639:             * NOTE: We pass the ResultColumns position in the ResultColumnList so
0640:             * that the VirtualColumnId gets set.
0641:             *
0642:             * @param targetTableDescriptor	The descriptor for the table being
0643:             *				updated or inserted into
0644:             * @param statement			DMLStatementNode containing this list, null if no duplicate checking is to be done
0645:             *
0646:             * @return A FormatableBitSet representing the set of columns with respect to the table
0647:             *
0648:             * @exception StandardException		Thrown on error
0649:             */
0650:            public FormatableBitSet bindResultColumnsByName(
0651:                    TableDescriptor targetTableDescriptor,
0652:                    DMLStatementNode statement) throws StandardException {
0653:                int size = size();
0654:                FormatableBitSet columnBitSet = new FormatableBitSet(
0655:                        targetTableDescriptor.getNumberOfColumns());
0656:
0657:                for (int index = 0; index < size; index++) {
0658:                    ResultColumn rc = (ResultColumn) elementAt(index);
0659:
0660:                    rc.bindResultColumnByName(targetTableDescriptor, index + 1);
0661:                    int colIdx = rc.getColumnPosition() - 1;
0662:                    if (SanityManager.DEBUG)
0663:                        SanityManager.ASSERT(colIdx >= 0
0664:                                && colIdx < targetTableDescriptor
0665:                                        .getNumberOfColumns(),
0666:                                "Invalid column position found for "
0667:                                        + rc.getName());
0668:                    /* Verify that this column's name is unique within the list if requested */
0669:                    if (statement != null && columnBitSet.isSet(colIdx)) {
0670:                        String colName = rc.getName();
0671:
0672:                        if (statement instanceof  UpdateNode) {
0673:                            throw StandardException.newException(
0674:                                    SQLState.LANG_DUPLICATE_COLUMN_NAME_UPDATE,
0675:                                    colName);
0676:                        } else {
0677:                            throw StandardException.newException(
0678:                                    SQLState.LANG_DUPLICATE_COLUMN_NAME_INSERT,
0679:                                    colName);
0680:                        }
0681:                    }
0682:                    columnBitSet.set(colIdx);
0683:                }
0684:                return columnBitSet;
0685:            }
0686:
0687:            /**
0688:             * Bind the result columns by their names.  This is useful for update
0689:             * VTI statements, and for INSERT statements like "insert into new t() (a, b, c)
0690:             * values (1, 2, 3)" where the user specified a column list.
0691:             * Also, verify that the result column list does not contain any duplicates.
0692:             * NOTE: We pass the ResultColumns position in the ResultColumnList so
0693:             * that the VirtualColumnId gets set.
0694:             *
0695:             * @param fullRCL	The full RCL for the target table
0696:             * @param statement			DMLStatementNode containing this list
0697:             *
0698:             * @exception StandardException		Thrown on error
0699:             */
0700:            public void bindResultColumnsByName(ResultColumnList fullRCL,
0701:                    FromVTI targetVTI, DMLStatementNode statement)
0702:                    throws StandardException {
0703:                int size = size();
0704:                Hashtable ht = new Hashtable(size + 2, (float) .999);
0705:
0706:                for (int index = 0; index < size; index++) {
0707:                    ResultColumn matchRC;
0708:                    ResultColumn rc = (ResultColumn) elementAt(index);
0709:
0710:                    /* Verify that this column's name is unique within the list */
0711:                    String colName = rc.getName();
0712:
0713:                    Object object = ht.put(colName, colName);
0714:
0715:                    if (object != null && ((String) object).equals(colName)) {
0716:                        if (SanityManager.DEBUG) {
0717:                            SanityManager
0718:                                    .ASSERT(
0719:                                            (statement instanceof  UpdateNode)
0720:                                                    || (statement instanceof  InsertNode),
0721:                                            "statement is expected to be instanceof UpdateNode or InsertNode");
0722:                        }
0723:                        if (statement instanceof  UpdateNode) {
0724:                            throw StandardException.newException(
0725:                                    SQLState.LANG_DUPLICATE_COLUMN_NAME_UPDATE,
0726:                                    colName);
0727:                        } else {
0728:                            throw StandardException.newException(
0729:                                    SQLState.LANG_DUPLICATE_COLUMN_NAME_INSERT,
0730:                                    colName);
0731:                        }
0732:                    }
0733:
0734:                    matchRC = fullRCL.getResultColumn(null, rc.getName());
0735:                    if (matchRC == null) {
0736:                        throw StandardException.newException(
0737:                                SQLState.LANG_COLUMN_NOT_FOUND_IN_TABLE, rc
0738:                                        .getName(), targetVTI
0739:                                        .getNewInvocation().getJavaClassName());
0740:                    }
0741:
0742:                    /* We have a match.  We need to create a dummy ColumnDescriptor
0743:                     * since calling code expects one to get column info.
0744:                     */
0745:                    ColumnDescriptor cd = new ColumnDescriptor(rc.getName(),
0746:                            matchRC.getVirtualColumnId(), matchRC.getType(),
0747:                            null, null, (TableDescriptor) null, null, 0, 0);
0748:                    rc.setColumnDescriptor(null, cd);
0749:                    rc.setVirtualColumnId(index + 1);
0750:                }
0751:            }
0752:
0753:            /**
0754:             * Bind the result columns by ordinal position.  This is useful for
0755:             * INSERT statements like "insert into t values (1, 2, 3)", where the
0756:             * user did not specify a column list.
0757:             *
0758:             * @param targetTableDescriptor	The descriptor for the table being
0759:             *				inserted into
0760:             *
0761:             * @exception StandardException		Thrown on error
0762:             */
0763:            public void bindResultColumnsByPosition(
0764:                    TableDescriptor targetTableDescriptor)
0765:                    throws StandardException {
0766:                int size = size();
0767:
0768:                for (int index = 0; index < size; index++) {
0769:                    /*
0770:                     ** Add one to the iterator index, because iterator indexes start at zero,
0771:                     ** and column numbers start at one.
0772:                     */
0773:                    ((ResultColumn) elementAt(index))
0774:                            .bindResultColumnByPosition(targetTableDescriptor,
0775:                                    index + 1);
0776:                }
0777:            }
0778:
0779:            /**
0780:             * Preprocess the expression trees under the RCL.
0781:             * We do a number of transformations
0782:             * here (including subqueries, IN lists, LIKE and BETWEEN) plus
0783:             * subquery flattening.
0784:             * NOTE: This is done before the outer ResultSetNode is preprocessed.
0785:             *
0786:             * @param	numTables			Number of tables in the DML Statement
0787:             * @param	outerFromList		FromList from outer query block
0788:             * @param	outerSubqueryList	SubqueryList from outer query block
0789:             * @param	outerPredicateList	PredicateList from outer query block
0790:             *
0791:             * @exception StandardException		Thrown on error
0792:             */
0793:            public void preprocess(int numTables, FromList outerFromList,
0794:                    SubqueryList outerSubqueryList,
0795:                    PredicateList outerPredicateList) throws StandardException {
0796:                int size = size();
0797:
0798:                for (int index = 0; index < size; index++) {
0799:                    ResultColumn resultColumn = (ResultColumn) elementAt(index);
0800:                    setElementAt(resultColumn.preprocess(numTables,
0801:                            outerFromList, outerSubqueryList,
0802:                            outerPredicateList), index);
0803:                }
0804:            }
0805:
0806:            /**
0807:            	Verify that all the result columns have expressions that
0808:            	are storable for them.  Check versus the given ResultColumnList.
0809:
0810:            	@exception StandardException	Thrown on error
0811:             */
0812:            void checkStorableExpressions(ResultColumnList toStore)
0813:                    throws StandardException {
0814:                int size = size();
0815:
0816:                for (int index = 0; index < size; index++) {
0817:                    ResultColumn otherRC = (ResultColumn) toStore
0818:                            .elementAt(index);
0819:
0820:                    ((ResultColumn) elementAt(index))
0821:                            .checkStorableExpression(otherRC);
0822:                }
0823:            }
0824:
0825:            /**
0826:              Return an array holding the 0 based heap offsets of 
0827:              the StreamStorable columns in this ResultColumnList.
0828:              This returns null if this list does not contain any
0829:              StreamStorableColumns. The list this returns does not
0830:              contain duplicates. This should only be used for
0831:              a resultColumnList the refers to a single heap
0832:              such as the target for an Insert, Update or Delete.
0833:              @param heapColCount the number of heap columns
0834:              @exception StandardException	Thrown on error
0835:             */
0836:            public int[] getStreamStorableColIds(int heapColCount)
0837:                    throws StandardException {
0838:                //@#$
0839:                //System.out.println("getStreamStorableColids");
0840:
0841:                int ssCount = 0;
0842:                boolean[] isSS = new boolean[heapColCount];//Should be table length.
0843:                int size = size();
0844:
0845:                for (int index = 0; index < size; index++) {
0846:                    ResultColumn rc = (ResultColumn) elementAt(index);
0847:
0848:                    if (rc.getTypeId().streamStorable()) {
0849:                        //System.out.println("    streamStorable=true");
0850:                        ColumnDescriptor cd = rc.getTableColumnDescriptor();
0851:                        isSS[cd.getPosition() - 1] = true;
0852:                    }
0853:                }
0854:
0855:                for (int ix = 0; ix < isSS.length; ix++)
0856:                    if (isSS[ix])
0857:                        ssCount++;
0858:
0859:                if (ssCount == 0)
0860:                    return null;
0861:
0862:                int[] result = new int[ssCount];
0863:                int resultOffset = 0;
0864:                for (int heapOffset = 0; heapOffset < isSS.length; heapOffset++) {
0865:                    if (isSS[heapOffset])
0866:                        result[resultOffset++] = heapOffset;
0867:                }
0868:
0869:                return result;
0870:            }
0871:
0872:            /**
0873:            	Verify that all the result columns have expressions that
0874:            	are storable for them.  Check versus the expressions under the
0875:            	ResultColumns.
0876:
0877:            	@exception StandardException	Thrown on error
0878:             */
0879:            void checkStorableExpressions() throws StandardException {
0880:                int size = size();
0881:
0882:                for (int index = 0; index < size; index++) {
0883:                    ((ResultColumn) elementAt(index)).checkStorableExpression();
0884:                }
0885:            }
0886:
0887:            /**
0888:             * Generate the code to place the columns' values into
0889:             * a row variable named "r". This wrapper is here
0890:             * rather than in ResultColumn, because that class does
0891:             * not know about the position of the columns in the list.
0892:             *
0893:             * @exception StandardException		Thrown on error
0894:             */
0895:            public void generate(ActivationClassBuilder acb, MethodBuilder mb)
0896:                    throws StandardException {
0897:                generateCore(acb, mb, false);
0898:            }
0899:
0900:            /**
0901:             * Generate the code to place the columns' values into
0902:             * a row variable named "r". This wrapper is here
0903:             * rather than in ResultColumn, because that class does
0904:             * not know about the position of the columns in the list.
0905:             *
0906:             * @exception StandardException		Thrown on error
0907:             */
0908:            void generateNulls(ActivationClassBuilder acb, MethodBuilder mb)
0909:                    throws StandardException {
0910:                generateCore(acb, mb, true);
0911:            }
0912:
0913:            /**
0914:             * Generate the code to place the columns' values into
0915:             * a row variable named "r". This wrapper is here
0916:             * rather than in ResultColumn, because that class does
0917:             * not know about the position of the columns in the list.
0918:             *
0919:             * This is the method that does the work.
0920:             */
0921:            void generateCore(ExpressionClassBuilder acb, MethodBuilder mb,
0922:                    boolean genNulls) throws StandardException {
0923:                // generate the function and initializer:
0924:                // private ExecRow fieldX;
0925:                // In the constructor:
0926:                //	 fieldX = getExecutionFactory().getValueRow(# cols);
0927:                // private ExecRow exprN()
0928:                // { 
0929:                //   fieldX.setColumn(1, col(1).generateColumn(ps)));
0930:                //   ... and so on for each column ...
0931:                //   return fieldX;
0932:                // }
0933:                // static Method exprN = method pointer to exprN;
0934:
0935:                // this sets up the method and the static field.
0936:                MethodBuilder userExprFun = acb.newUserExprFun();
0937:
0938:                /* Declare the field */
0939:                LocalField field = acb.newFieldDeclaration(Modifier.PRIVATE,
0940:                        ClassName.ExecRow);
0941:
0942:                // Generate the code to create the row in the constructor
0943:                genCreateRow(acb, field, "getValueRow", ClassName.ExecRow,
0944:                        size());
0945:
0946:                ResultColumn rc;
0947:                int size = size();
0948:
0949:                MethodBuilder cb = acb.getConstructor();
0950:
0951:                for (int index = 0; index < size; index++) {
0952:                    // generate statements of the form
0953:                    // fieldX.setColumn(columnNumber, (DataValueDescriptor) columnExpr);
0954:                    // and add them to exprFun.
0955:                    rc = (ResultColumn) elementAt(index);
0956:
0957:                    /* If we are not generating nulls, then we can skip this RC if
0958:                     * it is simply propagating a column from the source result set.
0959:                     */
0960:                    if (!genNulls) {
0961:                        ValueNode sourceExpr = rc.getExpression();
0962:
0963:                        if (sourceExpr instanceof  VirtualColumnNode
0964:                                && !(((VirtualColumnNode) sourceExpr)
0965:                                        .getCorrelated())) {
0966:                            continue;
0967:                        }
0968:
0969:                        if (sourceExpr instanceof  ColumnReference
0970:                                && !(((ColumnReference) sourceExpr)
0971:                                        .getCorrelated())) {
0972:                            continue;
0973:                        }
0974:                    }
0975:
0976:                    // row add is 1-based, and iterator index is 0-based
0977:                    if (SanityManager.DEBUG) {
0978:                        if (index + 1 != rc.getVirtualColumnId()) {
0979:                            SanityManager
0980:                                    .THROWASSERT("VirtualColumnId ("
0981:                                            + rc.getVirtualColumnId()
0982:                                            + ") does not agree with position within Vector ("
0983:                                            + (index + 1) + ")");
0984:                        }
0985:                    }
0986:
0987:                    // we need the expressions to be Columns exactly.
0988:
0989:                    /* SPECIAL CASE:  Expression is a non-null constant.
0990:                     *	Generate the setColumn() call in the constructor
0991:                     *  so that it will only be executed once per instantiation.
0992:                     *
0993:                     * Increase the statement counter in constructor.  Code size in
0994:                     * constructor can become too big (more than 64K) for Java compiler
0995:                     * to handle (beetle 4293).  We set constant columns in other
0996:                     * methods if constructor has too many statements already.
0997:                     */
0998:                    if ((!genNulls)
0999:                            && (rc.getExpression() instanceof  ConstantNode)
1000:                            && !((ConstantNode) rc.getExpression()).isNull()
1001:                            && !cb.statementNumHitLimit(1)) {
1002:
1003:                        cb.getField(field); // instance
1004:                        cb.push(index + 1); // first arg;
1005:
1006:                        rc.generateExpression(acb, cb);
1007:                        cb.cast(ClassName.DataValueDescriptor); // second arg
1008:                        cb.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.Row,
1009:                                "setColumn", "void", 2);
1010:                        continue;
1011:                    }
1012:
1013:                    userExprFun.getField(field); // instance
1014:                    userExprFun.push(index + 1); // arg1
1015:
1016:                    /* We want to reuse the null values instead of doing a new each time
1017:                     * if the caller said to generate nulls or the underlying expression
1018:                     * is a typed null value.
1019:                     */
1020:                    boolean needDVDCast = true;
1021:                    if (rc.isAutoincrementGenerated()) {
1022:                        // (com.ibm.db2j.impl... DataValueDescriptor)
1023:                        // this.getSetAutoincValue(column_number)
1024:
1025:                        userExprFun.pushThis();
1026:
1027:                        userExprFun.push(rc.getColumnPosition());
1028:                        userExprFun.push(rc.getTableColumnDescriptor()
1029:                                .getAutoincInc());
1030:
1031:                        userExprFun.callMethod(VMOpcode.INVOKEVIRTUAL,
1032:                                ClassName.BaseActivation,
1033:                                "getSetAutoincrementValue",
1034:                                ClassName.DataValueDescriptor, 2);
1035:                        needDVDCast = false;
1036:
1037:                    } else if (genNulls
1038:                            || ((rc.getExpression() instanceof  ConstantNode) && ((ConstantNode) rc
1039:                                    .getExpression()).isNull())) {
1040:                        userExprFun.getField(field);
1041:                        userExprFun.push(index + 1);
1042:                        userExprFun.callMethod(VMOpcode.INVOKEINTERFACE,
1043:                                ClassName.Row, "getColumn",
1044:                                ClassName.DataValueDescriptor, 1); // the express
1045:
1046:                        acb.generateNullWithExpress(userExprFun, rc
1047:                                .getTypeCompiler());
1048:
1049:                    } else {
1050:                        rc.generateExpression(acb, userExprFun);
1051:                    }
1052:                    if (needDVDCast)
1053:                        userExprFun.cast(ClassName.DataValueDescriptor);
1054:
1055:                    userExprFun.callMethod(VMOpcode.INVOKEINTERFACE,
1056:                            ClassName.Row, "setColumn", "void", 2);
1057:                }
1058:                userExprFun.getField(field);
1059:                userExprFun.methodReturn();
1060:
1061:                // we are now done modifying userExprFun
1062:                userExprFun.complete();
1063:
1064:                // what we return is the access of the field, i.e. the pointer to the method.
1065:                acb.pushMethodReference(mb, userExprFun);
1066:            }
1067:
1068:            /**
1069:             *	Build an empty row with the size and shape of the ResultColumnList.
1070:             *
1071:             *	@return	an empty row of the correct size and shape.
1072:             * @exception StandardException		Thrown on error
1073:             */
1074:            public ExecRow buildEmptyRow() throws StandardException {
1075:                int columnCount = size();
1076:                ExecRow row = getExecutionFactory().getValueRow(columnCount);
1077:                int position = 1;
1078:
1079:                for (int index = 0; index < columnCount; index++) {
1080:                    ResultColumn rc = (ResultColumn) elementAt(index);
1081:                    DataTypeDescriptor dataType = rc.getTypeServices();
1082:                    DataValueDescriptor dataValue = dataType.getNull();
1083:
1084:                    row.setColumn(position++, dataValue);
1085:                }
1086:
1087:                return row;
1088:            }
1089:
1090:            /**
1091:             *	Build an empty index row for the given conglomerate.
1092:             *
1093:             *	@return	an empty row of the correct size and shape.
1094:             * @exception StandardException		Thrown on error
1095:             */
1096:            public ExecRow buildEmptyIndexRow(TableDescriptor td,
1097:                    ConglomerateDescriptor cd, StoreCostController scc,
1098:                    DataDictionary dd) throws StandardException {
1099:                ResultColumn rc;
1100:
1101:                if (SanityManager.DEBUG) {
1102:                    if (!cd.isIndex()) {
1103:                        SanityManager
1104:                                .THROWASSERT("ConglomerateDescriptor expected to be for index: "
1105:                                        + cd);
1106:                    }
1107:                }
1108:
1109:                int[] baseCols = cd.getIndexDescriptor().baseColumnPositions();
1110:                ExecRow row = getExecutionFactory().getValueRow(
1111:                        baseCols.length + 1);
1112:
1113:                for (int i = 0; i < baseCols.length; i++) {
1114:                    ColumnDescriptor coldes = td
1115:                            .getColumnDescriptor(baseCols[i]);
1116:                    DataTypeDescriptor dataType = coldes.getType();
1117:
1118:                    // rc = getResultColumn(baseCols[i]);
1119:                    // rc = (ResultColumn) at(baseCols[i] - 1);
1120:                    // dataType = rc.getTypeServices();
1121:                    DataValueDescriptor dataValue = dataType.getNull();
1122:
1123:                    row.setColumn(i + 1, dataValue);
1124:                }
1125:
1126:                RowLocation rlTemplate = scc.newRowLocationTemplate();
1127:
1128:                row.setColumn(baseCols.length + 1, rlTemplate);
1129:
1130:                return row;
1131:            }
1132:
1133:            /**
1134:            	Generates a row with the size and shape of the ResultColumnList.
1135:
1136:            	Some structures, like FromBaseTable and DistinctNode,
1137:            	need to generate rowAllocator functions to get a row
1138:            	the size and shape of their ResultColumnList.  
1139:
1140:            	We return the method pointer, which is a field access
1141:            	in the generated class.
1142:
1143:            	@exception StandardException
1144:             */
1145:            void generateHolder(ExpressionClassBuilder acb, MethodBuilder mb)
1146:                    throws StandardException {
1147:                generateHolder(acb, mb, (FormatableBitSet) null,
1148:                        (FormatableBitSet) null);
1149:            }
1150:
1151:            /**
1152:            	Generates a row with the size and shape of the ResultColumnList.
1153:
1154:            	Some structures, like FromBaseTable and DistinctNode,
1155:            	need to generate rowAllocator functions to get a row
1156:            	the size and shape of their ResultColumnList.  
1157:
1158:            	We return the method pointer, which is a field access
1159:            	in the generated class.
1160:
1161:            	@exception StandardException
1162:             */
1163:            void generateHolder(ExpressionClassBuilder acb, MethodBuilder mb,
1164:                    FormatableBitSet referencedCols,
1165:                    FormatableBitSet propagatedCols) throws StandardException {
1166:
1167:                // what we return is a pointer to the method.
1168:                acb.pushMethodReference(mb, generateHolderMethod(acb,
1169:                        referencedCols, propagatedCols));
1170:            }
1171:
1172:            MethodBuilder generateHolderMethod(ExpressionClassBuilder acb,
1173:                    FormatableBitSet referencedCols,
1174:                    FormatableBitSet propagatedCols) throws StandardException {
1175:                int numCols;
1176:                String rowAllocatorMethod;
1177:                String rowAllocatorType;
1178:                int highestColumnNumber = -1;
1179:
1180:                if (referencedCols != null) {
1181:                    // Find the number of the last column referenced in the table
1182:                    for (int i = referencedCols.anySetBit(); i != -1; i = referencedCols
1183:                            .anySetBit(i)) {
1184:                        highestColumnNumber = i;
1185:                    }
1186:                } else {
1187:                    highestColumnNumber = size() - 1;
1188:                }
1189:
1190:                // Within the constructor:
1191:                //	 fieldX = getExecutionFactory().getValueRow(# cols);
1192:                // The body of the new method:
1193:                // { 
1194:                //   fieldX.setColumn(1, col(1).generateColumn(ps)));
1195:                //   ... and so on for each column ...
1196:                //   return fieldX;
1197:                // }
1198:                // static Method exprN = method pointer to exprN;
1199:
1200:                // this sets up the method and the static field
1201:                MethodBuilder exprFun = acb.newExprFun();
1202:
1203:                // Allocate the right type of row, depending on
1204:                // whether we're scanning an index or a heap.
1205:                if (indexRow) {
1206:                    rowAllocatorMethod = "getIndexableRow";
1207:                    rowAllocatorType = ClassName.ExecIndexRow;
1208:                } else {
1209:                    rowAllocatorMethod = "getValueRow";
1210:                    rowAllocatorType = ClassName.ExecRow;
1211:                }
1212:                numCols = size();
1213:
1214:                /* Declare the field */
1215:                LocalField lf = acb.newFieldDeclaration(Modifier.PRIVATE,
1216:                        ClassName.ExecRow);
1217:                // Generate the code to create the row in the constructor
1218:                genCreateRow(acb, lf, rowAllocatorMethod, rowAllocatorType,
1219:                        highestColumnNumber + 1);
1220:
1221:                // now we fill in the body of the function
1222:
1223:                int colNum;
1224:
1225:                // If there is a referenced column map, the first column to fill
1226:                // in is the first one in the bit map - otherwise, it is
1227:                // column 0.
1228:                if (referencedCols != null)
1229:                    colNum = referencedCols.anySetBit();
1230:                else
1231:                    colNum = 0;
1232:
1233:                for (int index = 0; index < numCols; index++) {
1234:                    ResultColumn rc = ((ResultColumn) elementAt(index));
1235:
1236:                    /* Special code generation for RID since expression is CurrentRowLocationNode.
1237:                     * Really need yet another node type that does its own code generation.
1238:                     */
1239:                    if (rc.getExpression() instanceof  CurrentRowLocationNode) {
1240:                        ConglomerateController cc = null;
1241:                        int savedItem;
1242:                        RowLocation rl;
1243:
1244:                        cc = getLanguageConnectionContext()
1245:                                .getTransactionCompile()
1246:                                .openConglomerate(
1247:                                        conglomerateId,
1248:                                        false,
1249:                                        0,
1250:                                        TransactionController.MODE_RECORD,
1251:                                        TransactionController.ISOLATION_READ_COMMITTED);
1252:                        try {
1253:                            rl = cc.newRowLocationTemplate();
1254:                        } finally {
1255:                            if (cc != null) {
1256:                                cc.close();
1257:                            }
1258:                        }
1259:
1260:                        savedItem = acb.addItem(rl);
1261:
1262:                        // get the RowLocation template
1263:                        exprFun.getField(lf); // instance for setColumn
1264:                        exprFun.push(highestColumnNumber + 1); // first arg
1265:
1266:                        exprFun.pushThis(); // instance for getRowLocationTemplate
1267:                        exprFun.push(savedItem); // first arg
1268:                        exprFun.callMethod(VMOpcode.INVOKEINTERFACE,
1269:                                ClassName.Activation, "getRowLocationTemplate",
1270:                                ClassName.RowLocation, 1);
1271:
1272:                        exprFun.upCast(ClassName.DataValueDescriptor);
1273:                        exprFun.callMethod(VMOpcode.INVOKEINTERFACE,
1274:                                ClassName.Row, "setColumn", "void", 2);
1275:                        continue;
1276:                    }
1277:
1278:                    /* Skip over those columns whose source is the immediate
1279:                     * child result set.  (No need to generate a wrapper
1280:                     * for a SQL NULL when we are smart enough not to pass
1281:                     * that wrapper to the store.)
1282:                     * NOTE: Believe it or not, we have to check for the case
1283:                     * where referencedCols is not null, but no bits are set.
1284:                     * This can happen when we need to get all of the columns
1285:                     * from the heap due to a check constraint.
1286:                     */
1287:                    if (propagatedCols != null
1288:                            && propagatedCols.getNumBitsSet() != 0) {
1289:                        /* We can skip this RC if it is simply propagating 
1290:                         * a column from the source result set.
1291:                         */
1292:                        ValueNode sourceExpr = rc.getExpression();
1293:
1294:                        if (sourceExpr instanceof  VirtualColumnNode) {
1295:                            // There is a referenced columns bit set, so use
1296:                            // it to figure out what the next column number is.
1297:                            // colNum = referencedCols.anySetBit(colNum);
1298:                            continue;
1299:                        }
1300:                    }
1301:
1302:                    // generate the column space creation call
1303:                    // generate statements of the form
1304:                    // r.setColumn(columnNumber, columnShape);
1305:                    //
1306:                    // This assumes that there are no "holes" in the column positions,
1307:                    // and that column positions reflect the stored format/order
1308:                    exprFun.getField(lf); // instance
1309:                    exprFun.push(colNum + 1); // first arg
1310:                    rc.generateHolder(acb, exprFun);
1311:
1312:                    exprFun.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.Row,
1313:                            "setColumn", "void", 2);
1314:
1315:                    // If there is a bit map of referenced columns, use it to
1316:                    // figure out what the next column is, otherwise just go
1317:                    // to the next column.
1318:                    if (referencedCols != null)
1319:                        colNum = referencedCols.anySetBit(colNum);
1320:                    else
1321:                        colNum++;
1322:                }
1323:
1324:                // generate:
1325:                // return fieldX;
1326:                // and add to the end of exprFun's body.
1327:                exprFun.getField(lf);
1328:                exprFun.methodReturn();
1329:
1330:                // we are done putting stuff in exprFun:
1331:                exprFun.complete();
1332:
1333:                return exprFun;
1334:            }
1335:
1336:            /**
1337:             * Generate the code to create an empty row in the constructor.
1338:             *
1339:             * @param acb					The ACB.
1340:             * @param field					The field for the new row.
1341:             * @param rowAllocatorMethod	The method to call.
1342:             * @param rowAllocatorType		The row type.
1343:             * @param numCols				The number of columns in the row.
1344:             *
1345:             * @exception StandardException		Thrown on error
1346:             */
1347:            private void genCreateRow(ExpressionClassBuilder acb,
1348:                    LocalField field, String rowAllocatorMethod,
1349:                    String rowAllocatorType, int numCols)
1350:                    throws StandardException {
1351:                // Create the row in the constructor
1352:                //	 fieldX = getExecutionFactory().getValueRow(# cols);
1353:
1354:                MethodBuilder cb = acb.getConstructor();
1355:
1356:                acb.pushGetExecutionFactoryExpression(cb); // instance
1357:                cb.push(numCols);
1358:                cb.callMethod(VMOpcode.INVOKEINTERFACE, (String) null,
1359:                        rowAllocatorMethod, rowAllocatorType, 1);
1360:                cb.setField(field);
1361:                /* Increase the statement counter in constructor.  Code size in
1362:                 * constructor can become too big (more than 64K) for Java compiler
1363:                 * to handle (beetle 4293).  We set constant columns in other
1364:                 * methods if constructor has too many statements already.
1365:                 */
1366:                cb.statementNumHitLimit(1); // ignore return value
1367:            }
1368:
1369:            /**
1370:             * Make a ResultDescription for use in a ResultSet.
1371:             * This is useful when generating/executing a NormalizeResultSet, since
1372:             * it can appear anywhere in the tree.
1373:             *
1374:             * @return	A ResultDescription for this ResultSetNode.
1375:             */
1376:
1377:            public ResultColumnDescriptor[] makeResultDescriptors() {
1378:                ExecutionContext ec = (ExecutionContext) getContextManager()
1379:                        .getContext(ExecutionContext.CONTEXT_ID);
1380:                return makeResultDescriptors(ec);
1381:            }
1382:
1383:            ResultColumnDescriptor[] makeResultDescriptors(ExecutionContext ec) {
1384:                ResultColumnDescriptor colDescs[] = new ResultColumnDescriptor[size()];
1385:                int size = size();
1386:
1387:                for (int index = 0; index < size; index++) {
1388:                    // the ResultColumn nodes are descriptors, so take 'em...
1389:                    colDescs[index] = ec
1390:                            .getExecutionFactory()
1391:                            .getResultColumnDescriptor(
1392:                                    ((ResultColumnDescriptor) elementAt(index)));
1393:                }
1394:
1395:                return colDescs;
1396:            }
1397:
1398:            /**
1399:             * Expand any *'s in the ResultColumnList.  In addition, we will guarantee that
1400:             * each ResultColumn has a name.  (All generated names will be unique across the
1401:             * entire statement.)
1402:             *
1403:             *
1404:             * @exception StandardException		Thrown on error
1405:             */
1406:
1407:            public void expandAllsAndNameColumns(FromList fromList)
1408:                    throws StandardException {
1409:                boolean expanded = false;
1410:                ResultColumnList allExpansion;
1411:                TableName fullTableName;
1412:
1413:                /* First walk result column list looking for *'s to expand */
1414:                for (int index = 0; index < size(); index++) {
1415:                    ResultColumn rc = (ResultColumn) elementAt(index);
1416:                    if (rc instanceof  AllResultColumn) {
1417:                        expanded = true;
1418:
1419:                        //fullTableName = ((AllResultColumn) rc).getFullTableName();
1420:                        TableName temp = rc.getTableNameObject();
1421:                        if (temp != null) {
1422:                            String sName = temp.getSchemaName();
1423:                            String tName = temp.getTableName();
1424:                            fullTableName = makeTableName(sName, tName);
1425:                        } else
1426:                            fullTableName = null;
1427:                        allExpansion = fromList.expandAll(fullTableName);
1428:
1429:                        /* Make sure that every column has a name */
1430:                        allExpansion.nameAllResultColumns();
1431:
1432:                        /* Make sure that every RC and expression is marked as being in
1433:                         * the SELECT list.
1434:                         */
1435:                        allExpansion.setClause(ValueNode.IN_SELECT_LIST);
1436:
1437:                        /* Replace the AllResultColumn with the expanded list. 
1438:                         * We will update the VirtualColumnIds once below.
1439:                         */
1440:                        removeElementAt(index);
1441:                        for (int inner = 0; inner < allExpansion.size(); inner++) {
1442:                            insertElementAt(allExpansion.elementAt(inner),
1443:                                    index + inner);
1444:                        }
1445:
1446:                        // If the rc was a "*", we need to set the initial list size
1447:                        // to the number of columns that are actually returned to
1448:                        // the user.
1449:                        markInitialSize();
1450:                    } else {
1451:                        /* Make sure that every column has a name */
1452:                        rc.guaranteeColumnName();
1453:                    }
1454:                }
1455:
1456:                /* Go back and update the VirtualColumnIds if we expanded any *'s */
1457:                if (expanded) {
1458:                    int size = size();
1459:
1460:                    for (int index = 0; index < size; index++) {
1461:                        /* Vectors are 0-based, VirtualColumnIds are 1-based. */
1462:                        ((ResultColumn) elementAt(index))
1463:                                .setVirtualColumnId(index + 1);
1464:                    }
1465:                }
1466:            }
1467:
1468:            /**
1469:             * Generate (unique across the entire statement) column names for those
1470:             * ResultColumns in this list which are not named.
1471:             *
1472:             * @exception StandardException		Thrown on error
1473:             */
1474:            public void nameAllResultColumns() throws StandardException {
1475:                int size = size();
1476:
1477:                for (int index = 0; index < size; index++) {
1478:                    ResultColumn resultColumn = (ResultColumn) elementAt(index);
1479:
1480:                    resultColumn.guaranteeColumnName();
1481:                }
1482:            }
1483:
1484:            /**
1485:             * Copy the types and lengths for this RCL (the target)
1486:             * to another RCL (the source).  
1487:             * This is useful when adding a NormalizeResultSetNode.
1488:             *
1489:             * @param sourceRCL	The source RCL
1490:             */
1491:            public void copyTypesAndLengthsToSource(ResultColumnList sourceRCL)
1492:                    throws StandardException {
1493:                /* Source and target can have different lengths. */
1494:                int size = (size() > sourceRCL.size()) ? size() : sourceRCL
1495:                        .size();
1496:                for (int index = 0; index < size; index++) {
1497:                    ResultColumn sourceRC = (ResultColumn) sourceRCL
1498:                            .elementAt(index);
1499:                    ResultColumn resultColumn = (ResultColumn) elementAt(index);
1500:                    sourceRC.setType(resultColumn.getTypeServices());
1501:                    sourceRC.getExpression().setType(
1502:                            resultColumn.getTypeServices());
1503:                }
1504:            }
1505:
1506:            /*
1507:             ** Check whether the column lengths and types of the result columns
1508:             ** match the expressions under those columns.  This is useful for
1509:             ** INSERT and UPDATE statements.  For SELECT statements this method
1510:             ** should always return true.  There is no need to call this for a
1511:             ** DELETE statement.
1512:             ** NOTE: We skip over generated columns since they won't have a
1513:             ** column descriptor.
1514:             **
1515:             ** @return	true means all the columns match their expressions,
1516:             **		false means at least one column does not match its
1517:             **		expression
1518:             */
1519:
1520:            boolean columnTypesAndLengthsMatch() throws StandardException {
1521:                int size = size();
1522:
1523:                for (int index = 0; index < size; index++) {
1524:                    ResultColumn resultColumn = (ResultColumn) elementAt(index);
1525:
1526:                    /* Skip over generated columns */
1527:                    if (resultColumn.isGenerated()) {
1528:                        continue;
1529:                    }
1530:
1531:                    if (!resultColumn.columnTypeAndLengthMatch())
1532:                        return false;
1533:                }
1534:
1535:                return true;
1536:            }
1537:
1538:            boolean columnTypesAndLengthsMatch(ResultColumnList otherRCL)
1539:                    throws StandardException {
1540:                boolean retval = true;
1541:
1542:                /* We check every RC, even after finding 1 that requires
1543:                 * normalization, because the conversion of constants to
1544:                 * the appropriate type occurs under this loop.
1545:                 */
1546:                int size = size();
1547:                for (int index = 0; index < size; index++) {
1548:                    ResultColumn resultColumn = (ResultColumn) elementAt(index);
1549:
1550:                    ResultColumn otherResultColumn = (ResultColumn) otherRCL
1551:                            .elementAt(index);
1552:
1553:                    /* Skip over generated columns */
1554:                    if (resultColumn.isGenerated()
1555:                            || otherResultColumn.isGenerated()) {
1556:                        continue;
1557:                    }
1558:
1559:                    if (!resultColumn
1560:                            .columnTypeAndLengthMatch(otherResultColumn)) {
1561:                        retval = false;
1562:                    }
1563:                }
1564:
1565:                return retval;
1566:            }
1567:
1568:            /**
1569:             * Determine whether this RCL is a No-Op projection of the given RCL.
1570:             * It only makes sense to do this if the given RCL is from the child
1571:             * result set of the ProjectRestrict that this RCL is from.
1572:             *
1573:             * @param childRCL	The ResultColumnList of the child result set.
1574:             *
1575:             * @return	true if this RCL is a No-Op projection of the given RCL.
1576:             */
1577:            public boolean nopProjection(ResultColumnList childRCL) {
1578:                /*
1579:                 ** This RCL is a useless projection if each column in the child
1580:                 ** if the same as the column in this RCL.  This is impossible
1581:                 ** if the two RCLs have different numbers of columns.
1582:                 */
1583:                if (this .size() != childRCL.size()) {
1584:                    return false;
1585:                }
1586:
1587:                /*
1588:                 ** The two lists have the same numbers of elements.  Are the lists
1589:                 ** identical?  In other words, is the expression in every ResultColumn
1590:                 ** in the PRN's RCL a ColumnReference that points to the corresponding
1591:                 ** column in the child?
1592:                 */
1593:                int size = size();
1594:                for (int index = 0; index < size; index++) {
1595:                    ResultColumn this Column = (ResultColumn) elementAt(index);
1596:                    ResultColumn referencedColumn = null;
1597:
1598:                    /*
1599:                     ** A No-Op projection can point to a VirtualColumnNode or a
1600:                     ** ColumnReference.
1601:                     */
1602:                    if (this Column.getExpression() instanceof  VirtualColumnNode) {
1603:                        referencedColumn = ((VirtualColumnNode) (this Column
1604:                                .getExpression())).getSourceColumn();
1605:                    } else if (this Column.getExpression() instanceof  ColumnReference) {
1606:                        referencedColumn = ((ColumnReference) (this Column
1607:                                .getExpression())).getSource();
1608:                    } else {
1609:                        return false;
1610:                    }
1611:
1612:                    ResultColumn childColumn = (ResultColumn) childRCL
1613:                            .elementAt(index);
1614:
1615:                    if (referencedColumn != childColumn) {
1616:                        return false;
1617:                    }
1618:                }
1619:
1620:                return true;
1621:            }
1622:
1623:            /**
1624:             *  Create a shallow copy of a ResultColumnList and its ResultColumns.
1625:             *  (All other pointers are preserved.)
1626:             *  Useful for building new ResultSetNodes during preprocessing.
1627:             *
1628:             *  @return None.
1629:             *
1630:             * @exception StandardException		Thrown on error
1631:             */
1632:            public ResultColumnList copyListAndObjects()
1633:                    throws StandardException {
1634:                ResultColumn newResultColumn;
1635:                ResultColumn origResultColumn;
1636:                ResultColumnList newList;
1637:
1638:                /* Create the new ResultColumnList */
1639:                newList = (ResultColumnList) getNodeFactory().getNode(
1640:                        C_NodeTypes.RESULT_COLUMN_LIST, getContextManager());
1641:
1642:                /* Walk the current list - for each ResultColumn in the list, make a copy
1643:                 * and add it to the new list.
1644:                 */
1645:                int size = size();
1646:
1647:                for (int index = 0; index < size; index++) {
1648:                    origResultColumn = (ResultColumn) elementAt(index);
1649:
1650:                    newResultColumn = origResultColumn.cloneMe();
1651:
1652:                    newList.addResultColumn(newResultColumn);
1653:                }
1654:
1655:                return newList;
1656:            }
1657:
1658:            /**
1659:             * Walk the list and replace ResultColumn.expression with a new 
1660:             * VirtualColumnNode.  This is useful when propagating a ResultColumnList
1661:             * up the query tree.
1662:             * NOTE: This flavor marks all of the underlying RCs as referenced.
1663:             *
1664:             * @param sourceResultSet		ResultSetNode that is source of value
1665:             *
1666:             * @exception StandardException		Thrown on error
1667:             */
1668:            public void genVirtualColumnNodes(ResultSetNode sourceResultSet,
1669:                    ResultColumnList sourceResultColumnList)
1670:                    throws StandardException {
1671:                genVirtualColumnNodes(sourceResultSet, sourceResultColumnList,
1672:                        true);
1673:            }
1674:
1675:            /**
1676:             * Walk the list and replace ResultColumn.expression with a new 
1677:             * VirtualColumnNode.  This is useful when propagating a ResultColumnList
1678:             * up the query tree.
1679:             *
1680:             * @param sourceResultSet		ResultSetNode that is source of value
1681:             * @param markReferenced		Whether or not to mark the underlying RCs
1682:             *								as referenced
1683:             *
1684:             * @exception StandardException		Thrown on error
1685:             */
1686:            public void genVirtualColumnNodes(ResultSetNode sourceResultSet,
1687:                    ResultColumnList sourceResultColumnList,
1688:                    boolean markReferenced) throws StandardException {
1689:                int size = size();
1690:
1691:                for (int index = 0; index < size; index++) {
1692:                    ResultColumn resultColumn = (ResultColumn) elementAt(index);
1693:
1694:                    /* dts = resultColumn.getExpression().getTypeServices(); */
1695:                    DataTypeDescriptor dts = resultColumn.getTypeServices();
1696:
1697:                    /* Vectors are 0-based, VirtualColumnIds are 1-based */
1698:                    resultColumn.expression = (ValueNode) getNodeFactory()
1699:                            .getNode(C_NodeTypes.VIRTUAL_COLUMN_NODE,
1700:                                    sourceResultSet,
1701:                                    sourceResultColumnList.elementAt(index),
1702:                                    ReuseFactory.getInteger(index + 1),
1703:                                    getContextManager());
1704:
1705:                    /* Mark the ResultColumn as being referenced */
1706:                    if (markReferenced) {
1707:                        resultColumn.setReferenced();
1708:                    }
1709:                }
1710:            }
1711:
1712:            /**
1713:             * Walk the list and adjust the virtualColumnIds in the ResultColumns
1714:             * by the specified amount.  If ResultColumn.expression is a VirtualColumnNode,
1715:             * then we adjust the columnId there as well.
1716:             *
1717:             * @param adjust		The size of the increment.
1718:             */
1719:            public void adjustVirtualColumnIds(int adjust) {
1720:                int size = size();
1721:
1722:                for (int index = 0; index < size; index++) {
1723:                    ResultColumn resultColumn = (ResultColumn) elementAt(index);
1724:                    resultColumn.adjustVirtualColumnId(adjust);
1725:                    if (SanityManager.DEBUG) {
1726:                        if (!(resultColumn.getExpression() instanceof  VirtualColumnNode)) {
1727:                            SanityManager
1728:                                    .THROWASSERT("resultColumn.getExpression() is expected to be "
1729:                                            + "instanceof VirtualColumnNode"
1730:                                            + " not "
1731:                                            + resultColumn.getExpression()
1732:                                                    .getClass().getName());
1733:                        }
1734:                    }
1735:
1736:                    ((VirtualColumnNode) resultColumn.getExpression()).columnId += adjust;
1737:                }
1738:            }
1739:
1740:            /**
1741:             * Project out any unreferenced ResultColumns from the list and 
1742:             * reset the virtual column ids in the referenced ResultColumns.
1743:             * If all ResultColumns are projected out, then the list is not empty.
1744:             * 
1745:             * @exception StandardException		Thrown on error
1746:             */
1747:            public void doProjection() throws StandardException {
1748:                int numDeleted = 0;
1749:                int size = size();
1750:                ResultColumnList deletedRCL = new ResultColumnList();
1751:                for (int index = 0; index < size; index++) {
1752:                    ResultColumn resultColumn = (ResultColumn) elementAt(index);
1753:
1754:                    /* RC's for FromBaseTables are marked as referenced during binding.
1755:                     * For other nodes, namely JoinNodes, we need to go 1 level
1756:                     * down the RC/VCN chain to see if the RC is referenced.  This is
1757:                     * because we propagate the referencing info from the bottom up.
1758:                     */
1759:                    if ((!resultColumn.isReferenced())
1760:                            && (resultColumn.getExpression() instanceof  VirtualColumnNode)
1761:                            && !(((VirtualColumnNode) resultColumn
1762:                                    .getExpression()).getSourceColumn()
1763:                                    .isReferenced())) {
1764:                        // Remember the RC to delete when done
1765:                        deletedRCL.addElement(resultColumn);
1766:
1767:                        /* Remember how many we have deleted and decrement the
1768:                         * VirtualColumnIds for all nodes which appear after us
1769:                         * in the list.
1770:                         */
1771:                        numDeleted++;
1772:                    } else {
1773:                        /* Decrement the VirtualColumnId for each node in the list
1774:                         * after the 1st deleted one.
1775:                         */
1776:                        if (numDeleted >= 1)
1777:                            resultColumn.adjustVirtualColumnId(-numDeleted);
1778:                        /* Make sure that the RC is marked as referenced! */
1779:                        resultColumn.setReferenced();
1780:                    }
1781:                }
1782:
1783:                // Go back and delete the RCs to be delete from the list
1784:                for (int index = 0; index < deletedRCL.size(); index++) {
1785:                    removeElement((ResultColumn) deletedRCL.elementAt(index));
1786:                }
1787:            }
1788:
1789:            /** 
1790:             * Check the uniqueness of the column names within a column list.
1791:             *
1792:             * @param errForGenCols	Raise an error for any generated column names.
1793:             *
1794:             * @return String	The first duplicate column name, if any.
1795:             */
1796:            public String verifyUniqueNames(boolean errForGenCols)
1797:                    throws StandardException {
1798:                int size = size();
1799:                Hashtable ht = new Hashtable(size + 2, (float) .999);
1800:                ResultColumn rc;
1801:
1802:                for (int index = 0; index < size; index++) {
1803:                    rc = (ResultColumn) elementAt(index);
1804:                    if (errForGenCols && rc.isNameGenerated())
1805:                        throw StandardException
1806:                                .newException(SQLState.LANG_DB2_VIEW_REQUIRES_COLUMN_NAMES);
1807:                    /* Verify that this column's name is unique within the list */
1808:                    String colName = ((ResultColumn) elementAt(index))
1809:                            .getName();
1810:
1811:                    Object object = ht.put(colName, colName);
1812:
1813:                    if (object != null && ((String) object).equals(colName)) {
1814:                        return colName;
1815:                    }
1816:                }
1817:
1818:                /* No duplicate column names */
1819:                return null;
1820:            }
1821:
1822:            /**
1823:             * Validate the derived column list (DCL) and propagate the info
1824:             * from the list to the final ResultColumnList.
1825:             *
1826:             * @param derivedRCL	The derived column list
1827:             * @param tableName		The table name for the FromTable
1828:             *
1829:             * @exception StandardException	Thrown on error
1830:             */
1831:            public void propagateDCLInfo(ResultColumnList derivedRCL,
1832:                    String tableName) throws StandardException {
1833:                String duplicateColName;
1834:
1835:                /* Do both lists, if supplied by user, have the same degree? */
1836:                if (derivedRCL.size() != size()
1837:                        && !derivedRCL.getCountMismatchAllowed()) {
1838:                    throw StandardException.newException(
1839:                            SQLState.LANG_DERIVED_COLUMN_LIST_MISMATCH,
1840:                            tableName);
1841:                }
1842:
1843:                /* Check the uniqueness of the column names within the derived list */
1844:                duplicateColName = derivedRCL.verifyUniqueNames(false);
1845:                if (duplicateColName != null) {
1846:                    throw StandardException.newException(
1847:                            SQLState.LANG_DUPLICATE_COLUMN_NAME_DERIVED,
1848:                            duplicateColName);
1849:                }
1850:
1851:                /* We can finally copy the derived names into the final list */
1852:                copyResultColumnNames(derivedRCL);
1853:            }
1854:
1855:            /**
1856:             * Look for and reject ? parameters under ResultColumns.  This is done for
1857:             * SELECT statements.
1858:             *
1859:             * @exception StandardException		Thrown if a ? parameter found directly
1860:             *									under a ResultColumn
1861:             */
1862:
1863:            void rejectParameters() throws StandardException {
1864:                int size = size();
1865:
1866:                for (int index = 0; index < size; index++) {
1867:                    ResultColumn rc = (ResultColumn) elementAt(index);
1868:                    rc.rejectParameter();
1869:                }
1870:            }
1871:
1872:            /**
1873:             * Check for (and reject) XML values directly under the ResultColumns.
1874:             * This is done for SELECT/VALUES statements.  We reject values
1875:             * in this case because JDBC does not define an XML type/binding
1876:             * and thus there's no standard way to pass such a type back
1877:             * to a JDBC application.
1878:             *
1879:             * Note that we DO allow an XML column in a top-level RCL
1880:             * IF that column was added to the RCL by _us_ instead of
1881:             * by the user.  For example, if we have a table:
1882:             *
1883:             * create table t1 (i int, x xml)
1884:             *
1885:             * and the user query is:
1886:             *
1887:             * select i from t1 order by x
1888:             *
1889:             * the "x" column will be added (internally) to the RCL
1890:             * as part of ORDER BY processing--and so we need to
1891:             * allow that XML column to be bound without throwing
1892:             * an error.  If, as in this case, the XML column reference
1893:             * is invalid (we can't use ORDER BY on an XML column because
1894:             * XML values aren't ordered), a more appropriate error
1895:             * message should be returned to the user in later processing.
1896:             * If we didn't allow for this, the user would get an
1897:             * error saying that XML columns are not valid as part
1898:             * of the result set--but as far as s/he knows, there
1899:             * isn't such a column: only "i" is supposed to be returned
1900:             * (the RC for "x" was added to the RCL by _us_ as part of
1901:             * ORDER BY processing).
1902:             *
1903:             * ASSUMPTION: Any RCs that are generated internally and
1904:             * added to this RCL (before this RCL is bound) are added
1905:             * at the _end_ of the list.  If that's true, then any
1906:             * RC with an index greater than the size of the initial
1907:             * (user-specified) list must have been added internally
1908:             * and will not be returned to the user.
1909:             *
1910:             * @exception StandardException		Thrown if an XML value found
1911:             *									directly under a ResultColumn
1912:             */
1913:            void rejectXMLValues() throws StandardException {
1914:                int sz = size();
1915:                ResultColumn rc = null;
1916:                for (int i = 1; i <= sz; i++) {
1917:
1918:                    if (i > initialListSize)
1919:                        // this RC was generated internally and will not
1920:                        // be returned to the user, so don't throw error.
1921:                        continue;
1922:
1923:                    rc = getResultColumn(i);
1924:                    if ((rc != null) && (rc.getType() != null)
1925:                            && rc.getType().getTypeId().isXMLTypeId()) { // Disallow it.
1926:                        throw StandardException
1927:                                .newException(SQLState.LANG_ATTEMPT_TO_SELECT_XML);
1928:                    }
1929:
1930:                }
1931:            }
1932:
1933:            /**
1934:             * Set the resultSetNumber in all of the ResultColumns.
1935:             *
1936:             * @param resultSetNumber	The resultSetNumber
1937:             */
1938:            public void setResultSetNumber(int resultSetNumber) {
1939:                int size = size();
1940:
1941:                for (int index = 0; index < size; index++) {
1942:                    ((ResultColumn) elementAt(index))
1943:                            .setResultSetNumber(resultSetNumber);
1944:                }
1945:            }
1946:
1947:            /**
1948:             * Mark all of the ResultColumns as redundant.
1949:             * Useful when chopping a ResultSetNode out of a tree when there are
1950:             * still references to its RCL.
1951:             */
1952:            public void setRedundant() {
1953:                int size = size();
1954:
1955:                for (int index = 0; index < size; index++) {
1956:                    ((ResultColumn) elementAt(index)).setRedundant();
1957:                }
1958:            }
1959:
1960:            /**
1961:             * Verify that all of the columns in the SET clause of a positioned update
1962:             * appear in the cursor's FOR UPDATE OF list.
1963:             *
1964:             * @param ucl			The cursor's FOR UPDATE OF list.  (May be null.)
1965:             * @param cursorName	The cursor's name.
1966:             *
1967:             * @exception StandardException			Thrown on error
1968:             */
1969:            public void checkColumnUpdateability(String[] ucl, String cursorName)
1970:                    throws StandardException {
1971:                int size = size();
1972:
1973:                for (int index = 0; index < size; index++) {
1974:                    ResultColumn resultColumn = (ResultColumn) elementAt(index);
1975:
1976:                    if (resultColumn.updated()
1977:                            && !resultColumn.foundInList(ucl)) {
1978:                        throw StandardException.newException(
1979:                                SQLState.LANG_COLUMN_NOT_UPDATABLE_IN_CURSOR,
1980:                                resultColumn.getName(), cursorName);
1981:                    }
1982:                }
1983:            }
1984:
1985:            /**
1986:             * Set up the result expressions for a UNION, INTERSECT, or EXCEPT:
1987:             *	o Verify union type compatiblity
1988:             *	o Get dominant type for result (type + max length + nullability)
1989:             *  o Create a new ColumnReference with dominant type and name of from this
1990:             *    RCL and make that the new expression.
1991:             *  o Set the type info for in the ResultColumn to the dominant type
1992:             *
1993:             * NOTE - We are assuming that caller has generated a new RCL for the UNION
1994:             * with the same names as the left side's RCL and copies of the expressions.
1995:             *
1996:             * @param otherRCL	RCL from other side of the UNION.
1997:             * @param tableNumber	The tableNumber for the UNION.
1998:             * @param level		The nesting level for the UNION.
1999:             * @param operatorName "UNION", "INTERSECT", or "EXCEPT"
2000:             *
2001:             * @exception StandardException			Thrown on error
2002:             */
2003:            public void setUnionResultExpression(ResultColumnList otherRCL,
2004:                    int tableNumber, int level, String operatorName)
2005:                    throws StandardException {
2006:                TableName dummyTN;
2007:
2008:                if (SanityManager.DEBUG) {
2009:                    if (size() != otherRCL.size()) {
2010:                        SanityManager.THROWASSERT("size() = (" + size()
2011:                                + ") is expected to equal otherRCL.size ("
2012:                                + otherRCL.size() + ")");
2013:                    }
2014:                }
2015:
2016:                /* Make a dummy TableName to be shared by all new CRs */
2017:                dummyTN = (TableName) getNodeFactory()
2018:                        .getNode(C_NodeTypes.TABLE_NAME, null, null,
2019:                                getContextManager());
2020:
2021:                ContextManager cm = getContextManager();
2022:
2023:                int size = size();
2024:                for (int index = 0; index < size; index++) {
2025:                    boolean nullableResult;
2026:                    ColumnReference newCR;
2027:                    ResultColumn this RC = (ResultColumn) elementAt(index);
2028:                    ResultColumn otherRC = (ResultColumn) otherRCL
2029:                            .elementAt(index);
2030:                    ValueNode this Expr = this RC.getExpression();
2031:                    ValueNode otherExpr = otherRC.getExpression();
2032:
2033:                    // If there is one row that is not 'autoincrement', the Union should
2034:                    // not be 'autoincrement'.
2035:                    if (!otherRC.isAutoincrementGenerated()
2036:                            && this RC.isAutoincrementGenerated()) {
2037:                        this RC.resetAutoincrementGenerated();
2038:                    }
2039:                    /*
2040:                     ** If there are ? parameters in the ResultColumnList of a row
2041:                     ** in a table constructor, their types will not be set.  Just skip
2042:                     ** these - their types will be set later.  Each ? parameter will
2043:                     ** get the type of the first non-? in its column, so it can't
2044:                     ** affect the final dominant type.  It's possible that all the
2045:                     ** rows for a particular column will have ? parameters - this is
2046:                     ** an error condition that will be caught later.
2047:                     */
2048:                    TypeId this TypeId = this Expr.getTypeId();
2049:                    if (this TypeId == null)
2050:                        continue;
2051:
2052:                    TypeId otherTypeId = otherExpr.getTypeId();
2053:                    if (otherTypeId == null)
2054:                        continue;
2055:
2056:                    /* 
2057:                     ** Check type compatability.  We want to make sure that
2058:                     ** the types are assignable in either direction
2059:                     ** and they are comparable.
2060:                     */
2061:                    ClassFactory cf = getClassFactory();
2062:                    if (!this Expr.getTypeCompiler().storable(otherTypeId, cf)
2063:                            && !otherExpr.getTypeCompiler().storable(
2064:                                    this TypeId, cf)) {
2065:                        throw StandardException.newException(
2066:                                SQLState.LANG_NOT_UNION_COMPATIBLE, this TypeId
2067:                                        .getSQLTypeName(), otherTypeId
2068:                                        .getSQLTypeName(), operatorName);
2069:                    }
2070:
2071:                    DataTypeDescriptor resultType = this Expr.getTypeServices()
2072:                            .getDominantType(otherExpr.getTypeServices(), cf);
2073:
2074:                    newCR = (ColumnReference) getNodeFactory().getNode(
2075:                            C_NodeTypes.COLUMN_REFERENCE, this RC.getName(),
2076:                            dummyTN, getContextManager());
2077:                    newCR.setType(resultType);
2078:                    /* Set the tableNumber and nesting levels in newCR.
2079:                     * If thisExpr is not a CR, then newCR cannot be
2080:                     * correlated, hence source and nesting levels are
2081:                     * the same.
2082:                     */
2083:                    if (this Expr instanceof  ColumnReference) {
2084:                        newCR.copyFields((ColumnReference) this Expr);
2085:                    } else {
2086:                        newCR.setNestingLevel(level);
2087:                        newCR.setSourceLevel(level);
2088:                    }
2089:                    newCR.setTableNumber(tableNumber);
2090:                    this RC.setExpression(newCR);
2091:                    this RC.setType(this RC.getTypeServices().getDominantType(
2092:                            otherRC.getTypeServices(), cf));
2093:
2094:                    /* DB2 requires both sides of union to have same name for the result to
2095:                     * have that name. Otherwise, leave it or set it to a generated name */
2096:                    if (this RC.getName() != null && !this RC.isNameGenerated()
2097:                            && otherRC.getName() != null) {
2098:                        /* Result name needs to be changed */
2099:                        if (otherRC.isNameGenerated()) {
2100:                            this RC.setName(otherRC.getName());
2101:                            this RC.setNameGenerated(true);
2102:                        } else if (!this RC.getName().equals(otherRC.getName())) {
2103:                            /* Both sides have user specified names that don't match */
2104:                            this RC.setName(null);
2105:                            this RC.guaranteeColumnName();
2106:                            this RC.setNameGenerated(true);
2107:                        }
2108:                    }
2109:                }
2110:            }
2111:
2112:            /**
2113:             * If the resultset is a UnionNode (e.g., multi-rows in VALUES clause), we recursively call itself.
2114:             * checkAutoincrement() will set ColumnDescriptor for autoincrement columns.
2115:             * This way, all ColumnDescriptor of all rows will be set properly.
2116:             */
2117:            public void checkAutoincrementUnion(ResultSetNode rs)
2118:                    throws StandardException {
2119:                ResultSetNode lrs = ((TableOperatorNode) rs).getLeftResultSet();
2120:                ResultSetNode rrs = ((TableOperatorNode) rs)
2121:                        .getRightResultSet();
2122:
2123:                if (lrs instanceof  UnionNode) {
2124:                    this .checkAutoincrementUnion(lrs);
2125:                } else {
2126:                    this .checkAutoincrement(lrs.getResultColumns());
2127:                }
2128:
2129:                if (rrs instanceof  UnionNode) {
2130:                    this .checkAutoincrementUnion(rrs);
2131:                } else {
2132:                    this .checkAutoincrement(rrs.getResultColumns());
2133:                }
2134:            }
2135:
2136:            /**
2137:             * Do the 2 RCLs have the same type & length.
2138:             * This is useful for UNIONs when deciding whether a NormalizeResultSet is required.
2139:             *
2140:             * @param otherRCL	The other RCL.
2141:             *
2142:             * @return boolean	Whether or not there is an exact UNION type match on the 2 RCLs.
2143:             */
2144:            public boolean isExactTypeAndLengthMatch(ResultColumnList otherRCL)
2145:                    throws StandardException {
2146:                int size = size();
2147:                for (int index = 0; index < size; index++) {
2148:                    ResultColumn this RC = (ResultColumn) elementAt(index);
2149:                    ResultColumn otherRC = (ResultColumn) otherRCL
2150:                            .elementAt(index);
2151:
2152:                    if (!this RC.getTypeServices().isExactTypeAndLengthMatch(
2153:                            otherRC.getTypeServices())) {
2154:                        return false;
2155:                    }
2156:                }
2157:
2158:                return true;
2159:            }
2160:
2161:            /**
2162:             * Does the column list contain any of the given column positions
2163:             * that are updated? Implements same named routine in UpdateList.
2164:             *
2165:             * @param columns	An array of column positions
2166:             *
2167:             * @return	True if this column list contains any of the given columns
2168:             */
2169:            public boolean updateOverlaps(int[] columns) {
2170:                int size = size();
2171:
2172:                for (int index = 0; index < size; index++) {
2173:                    ResultColumn rc = (ResultColumn) elementAt(index);
2174:
2175:                    if (!rc.updated())
2176:                        continue;
2177:
2178:                    int column = rc.getColumnPosition();
2179:
2180:                    for (int i = 0; i < columns.length; i++) {
2181:                        if (columns[i] == column)
2182:                            return true;
2183:                    }
2184:                }
2185:
2186:                return false;
2187:            }
2188:
2189:            /**
2190:             * Return an array that contains references to the columns in this list
2191:             * sorted by position.
2192:             *
2193:             * @return	The sorted array.
2194:             */
2195:            ResultColumn[] getSortedByPosition() {
2196:                int size = size();
2197:                ResultColumn[] result;
2198:
2199:                /*
2200:                 ** Form an array of the original ResultColumns
2201:                 */
2202:                result = new ResultColumn[size];
2203:
2204:                /*
2205:                 ** Put the ResultColumns in the array
2206:                 */
2207:                for (int index = 0; index < size; index++) {
2208:                    result[index] = (ResultColumn) elementAt(index);
2209:                }
2210:
2211:                /*
2212:                 ** Sort the array by column position
2213:                 */
2214:                java.util.Arrays.sort(result);
2215:                return result;
2216:            }
2217:
2218:            /**
2219:             *	Return an array of all my column positions, sorted in
2220:             *	ascending order.
2221:             *
2222:             *	@return	a sorted array
2223:             */
2224:            public int[] sortMe() {
2225:                ResultColumn[] sortedResultColumns = getSortedByPosition();
2226:                int[] sortedColumnIds = new int[sortedResultColumns.length];
2227:                for (int ix = 0; ix < sortedResultColumns.length; ix++) {
2228:                    sortedColumnIds[ix] = sortedResultColumns[ix]
2229:                            .getColumnPosition();
2230:                }
2231:                return sortedColumnIds;
2232:            }
2233:
2234:            /**
2235:             * Expand this ResultColumnList by adding all columns from the given
2236:             * table that are not in this list.  The result is sorted by column
2237:             * position.
2238:             *
2239:             * @param td	The TableDescriptor for the table in question
2240:             * @param tableName	The name of the table as given in the query
2241:             *
2242:             * @return	A new ResultColumnList expanded to include all columns in
2243:             *			the given table.
2244:             *
2245:             * @exception StandardException		Thrown on error
2246:             */
2247:            public ResultColumnList expandToAll(TableDescriptor td,
2248:                    TableName tableName) throws StandardException {
2249:                ResultColumn rc;
2250:                ColumnDescriptor cd;
2251:                ResultColumnList retval;
2252:                ResultColumn[] originalRCS;
2253:                int posn;
2254:
2255:                /* Get a new ResultColumnList */
2256:                retval = (ResultColumnList) getNodeFactory().getNode(
2257:                        C_NodeTypes.RESULT_COLUMN_LIST, getContextManager());
2258:
2259:                /*
2260:                 ** Form a sorted array of the ResultColumns
2261:                 */
2262:                originalRCS = getSortedByPosition();
2263:
2264:                posn = 0;
2265:
2266:                /* Iterate through the ColumnDescriptors for the given table */
2267:                ColumnDescriptorList cdl = td.getColumnDescriptorList();
2268:                int cdlSize = cdl.size();
2269:
2270:                for (int index = 0; index < cdlSize; index++) {
2271:                    cd = (ColumnDescriptor) cdl.elementAt(index);
2272:
2273:                    if ((posn < originalRCS.length)
2274:                            && (cd.getPosition() == originalRCS[posn]
2275:                                    .getColumnPosition())) {
2276:                        rc = originalRCS[posn];
2277:                        posn++;
2278:                    } else {
2279:                        /* Build a ResultColumn/ColumnReference pair for the column */
2280:                        rc = makeColumnReferenceFromName(tableName, cd
2281:                                .getColumnName());
2282:
2283:                        /* Bind the new ResultColumn */
2284:                        rc.bindResultColumnByPosition(td, cd.getPosition());
2285:                    }
2286:
2287:                    /* Add the ResultColumn to the list */
2288:                    retval.addResultColumn(rc);
2289:                }
2290:
2291:                if (SanityManager.DEBUG)
2292:                    SanityManager
2293:                            .ASSERT(posn == originalRCS.length,
2294:                                    "ResultColumns in original list not added to expanded ResultColumnList");
2295:
2296:                return retval;
2297:            }
2298:
2299:            /**
2300:             * Bind any untyped null nodes to the types in the given ResultColumnList.
2301:             * Nodes that don't know their type may pass down nulls to
2302:             * children nodes.  In the case of something like a union, it knows
2303:             * to try its right and left result sets against each other. 
2304:             * But if a null reaches us, it means we have a null type that
2305:             * we don't know how to handle.
2306:             *
2307:             * @param bindingRCL	The ResultColumnList with the types to bind to.
2308:             *
2309:             * @exception StandardException		Thrown on error
2310:             */
2311:            public void bindUntypedNullsToResultColumns(
2312:                    ResultColumnList bindingRCL) throws StandardException {
2313:                if (bindingRCL == null) {
2314:                    throw StandardException
2315:                            .newException(SQLState.LANG_NULL_IN_VALUES_CLAUSE);
2316:                }
2317:
2318:                if (SanityManager.DEBUG)
2319:                    SanityManager
2320:                            .ASSERT(bindingRCL.size() >= this .size(),
2321:                                    "More columns in result column list than in base table");
2322:
2323:                int size = size();
2324:                for (int index = 0; index < size; index++) {
2325:                    ResultColumn bindingRC = (ResultColumn) bindingRCL
2326:                            .elementAt(index);
2327:                    ResultColumn this RC = (ResultColumn) elementAt(index);
2328:
2329:                    this RC.typeUntypedNullExpression(bindingRC);
2330:                }
2331:            }
2332:
2333:            /**
2334:             * Mark all the columns in this list as updated by an update statement.
2335:             */
2336:            void markUpdated() {
2337:                int size = size();
2338:
2339:                for (int index = 0; index < size; index++) {
2340:                    ((ResultColumn) elementAt(index)).markUpdated();
2341:                }
2342:            }
2343:
2344:            /**
2345:             * Mark all the (base) columns in this list as updatable by a positioned update
2346:             * statement.  This is necessary
2347:             * for positioned update statements, because we expand the column list
2348:             * to include all the columns in the base table, and we need to be able
2349:             * to tell which ones the user is really trying to update so we can
2350:             * determine correctly whether all the updated columns are in the
2351:             * "for update" list.
2352:             */
2353:            void markUpdatableByCursor() {
2354:                int size = size();
2355:
2356:                for (int index = 0; index < size; index++) {
2357:                    //determine if the column is a base column and not a derived column
2358:                    if (((ResultColumn) elementAt(index)).getSourceTableName() != null)
2359:                        ((ResultColumn) elementAt(index))
2360:                                .markUpdatableByCursor();
2361:                }
2362:            }
2363:
2364:            /** 
2365:             * @see QueryTreeNode#disablePrivilegeCollection
2366:             */
2367:            public void disablePrivilegeCollection() {
2368:                super .disablePrivilegeCollection();
2369:
2370:                int size = size();
2371:                for (int index = 0; index < size; index++)
2372:                    ((ResultColumn) elementAt(index))
2373:                            .disablePrivilegeCollection();
2374:            }
2375:
2376:            /**
2377:             * Verify that all of the column names in this list are contained
2378:             * within the ColumnDefinitionNodes within the TableElementList.
2379:             *
2380:             * 
2381:             * @return String	The 1st column name, if any, that is not in the list.
2382:             */
2383:            public String verifyCreateConstraintColumnList(TableElementList tel) {
2384:                int size = size();
2385:
2386:                for (int index = 0; index < size; index++) {
2387:                    String colName = ((ResultColumn) elementAt(index))
2388:                            .getName();
2389:
2390:                    if (!tel.containsColumnName(colName)) {
2391:                        return colName;
2392:                    }
2393:                }
2394:                return null;
2395:            }
2396:
2397:            /**
2398:             * Export the result column names to the passed in String[].
2399:             *
2400:             * @param columnNames	String[] to hold the column names.
2401:             */
2402:            public void exportNames(String[] columnNames) {
2403:                if (SanityManager.DEBUG) {
2404:                    if (size() != columnNames.length) {
2405:                        SanityManager.THROWASSERT("size() (" + size()
2406:                                + ") is expected to equal columnNames.length ("
2407:                                + columnNames.length + ")");
2408:                    }
2409:                }
2410:
2411:                int size = size();
2412:
2413:                for (int index = 0; index < size; index++) {
2414:                    columnNames[index] = ((ResultColumn) elementAt(index))
2415:                            .getName();
2416:                }
2417:            }
2418:
2419:            /**
2420:             * Count the number of RCs with simple ColumnReferences.  
2421:             * (RC.expression instanceof ColumnReference)  This is useful
2422:             * for ensuring that the number of columns in the group by list
2423:             * equals the number of grouping columns.
2424:             *
2425:             * @return int	The number of simple ColumnReferences.
2426:             */
2427:            public int countNumberOfSimpleColumnReferences() {
2428:                int numCRs = 0;
2429:
2430:                int size = size();
2431:
2432:                for (int index = 0; index < size; index++) {
2433:                    if (((ResultColumn) elementAt(index)).getExpression() instanceof  ColumnReference) {
2434:                        numCRs++;
2435:                    }
2436:                }
2437:
2438:                return numCRs;
2439:            }
2440:
2441:            /**
2442:             * Given a ResultColumn at the next deepest level in the tree, 
2443:             * search this RCL for its parent ResultColumn.
2444:             *
2445:             * @param childRC	The child ResultColumn
2446:             *
2447:             * @return ResultColumn	The parent ResultColumn
2448:             */
2449:            public ResultColumn findParentResultColumn(ResultColumn childRC) {
2450:                ResultColumn parentRC = null;
2451:
2452:                int size = size();
2453:
2454:                for (int index = 0; index < size; index++) {
2455:                    ResultColumn rc = (ResultColumn) elementAt(index);
2456:
2457:                    if (rc.getExpression() instanceof  ColumnReference) {
2458:                        ColumnReference cr = (ColumnReference) rc
2459:                                .getExpression();
2460:
2461:                        if (cr.getSource() == childRC) {
2462:                            parentRC = rc;
2463:                            break;
2464:                        }
2465:                    } else if (rc.getExpression() instanceof  VirtualColumnNode) {
2466:                        VirtualColumnNode vcn = (VirtualColumnNode) rc
2467:                                .getExpression();
2468:
2469:                        if (vcn.getSourceColumn() == childRC) {
2470:                            parentRC = rc;
2471:                            break;
2472:                        }
2473:                    }
2474:
2475:                }
2476:
2477:                return parentRC;
2478:            }
2479:
2480:            public void setClause(int clause) {
2481:                int size = size();
2482:
2483:                for (int index = 0; index < size; index++) {
2484:                    ResultColumn rc = (ResultColumn) elementAt(index);
2485:                    rc.setClause(clause);
2486:                }
2487:            }
2488:
2489:            /**
2490:             * Mark as updatable all the columns in this result column list
2491:             * that match the columns in the given update column list.
2492:             *
2493:             * @param updateColumns		A ResultColumnList representing the columns
2494:             *							to be updated.
2495:             */
2496:            void markUpdated(ResultColumnList updateColumns) {
2497:                ResultColumn updateColumn;
2498:                ResultColumn resultColumn;
2499:
2500:                int size = updateColumns.size();
2501:
2502:                for (int index = 0; index < size; index++) {
2503:                    updateColumn = (ResultColumn) updateColumns
2504:                            .elementAt(index);
2505:
2506:                    resultColumn = getResultColumn(updateColumn.getName());
2507:
2508:                    /*
2509:                     ** This ResultColumnList may not be bound yet - for update
2510:                     ** statements, we mark the updated columns *before* we bind
2511:                     ** the RCL.  This ordering is important because we add columns
2512:                     ** to the RCL after marking the update columns and before
2513:                     ** binding.
2514:                     **
2515:                     ** So, it can happen that there is an invalid column name in
2516:                     ** the list.  This condition will cause an exception when the
2517:                     ** RCL is bound.  Just ignore it for now.
2518:                     */
2519:                    if (resultColumn != null) {
2520:                        resultColumn.markUpdated();
2521:                    }
2522:                }
2523:            }
2524:
2525:            /**
2526:             * Mark all the columns in the select sql that this result column list represents
2527:             * as updatable if they match the columns in the given update column list.
2528:             *
2529:             * @param updateColumns		A Vector representing the columns
2530:             *							to be updated.
2531:             */
2532:            void markColumnsInSelectListUpdatableByCursor(Vector updateColumns) {
2533:                commonCodeForUpdatableByCursor(updateColumns, true);
2534:            }
2535:
2536:            /**
2537:             * dealingWithSelectResultColumnList true means we are dealing with
2538:             * ResultColumnList for a select sql. When dealing with ResultColumnList for
2539:             * select sql, it is possible that not all the updatable columns are
2540:             * projected in the select column list and hence it is possible that we may
2541:             * not find the column to be updated in the ResultColumnList and that is why
2542:             * special handling is required when dealingWithSelectResultColumnList is true.
2543:             * eg select c11, c13 from t1 for update of c11, c12
2544:             * In the eg above, we will find updatable column c11 in the select column
2545:             * list but we will not find updatable column c12 in the select column list
2546:             */
2547:            private void commonCodeForUpdatableByCursor(Vector updateColumns,
2548:                    boolean dealingWithSelectResultColumnList) {
2549:                /*
2550:                 ** If there is no update column list, or the list is empty, then it means that
2551:                 ** all the columns which have a base table associated with them are updatable.
2552:                 */
2553:                if ((updateColumns == null) || (updateColumns.size() == 0)) {
2554:                    markUpdatableByCursor();
2555:                } else {
2556:                    int ucSize = updateColumns.size();
2557:                    ResultColumn resultColumn;
2558:                    String columnName;
2559:
2560:                    for (int index = 0; index < ucSize; index++) {
2561:                        columnName = (String) updateColumns.elementAt(index);
2562:
2563:                        resultColumn = getResultColumn(columnName);
2564:                        if (SanityManager.DEBUG) {
2565:                            if (resultColumn == null
2566:                                    && !dealingWithSelectResultColumnList) {
2567:                                SanityManager
2568:                                        .THROWASSERT("No result column found with name "
2569:                                                + columnName);
2570:                            }
2571:                        }
2572:                        //Following if means the column specified in FOR UPDATE clause is not
2573:                        //part of the select list
2574:                        if (resultColumn == null
2575:                                && dealingWithSelectResultColumnList)
2576:                            continue;
2577:                        resultColumn.markUpdatableByCursor();
2578:                    }
2579:                }
2580:            }
2581:
2582:            /**
2583:             * Mark as updatable all the columns in this result column list
2584:             * that match the columns in the given update column list
2585:             *
2586:             * @param updateColumns		A Vector representing the columns
2587:             *							to be updated.
2588:             */
2589:            void markUpdatableByCursor(Vector updateColumns) {
2590:                commonCodeForUpdatableByCursor(updateColumns, false);
2591:            }
2592:
2593:            /**
2594:             * Returns true if the given column position is for a column that will
2595:             * be or could be updated by the positioned update of a cursor.
2596:             *
2597:             * @param columnPosition	The position of the column in question
2598:             *
2599:             * @return	true if the column is updatable
2600:             */
2601:            boolean updatableByCursor(int columnPosition) {
2602:                return getResultColumn(columnPosition).updatableByCursor();
2603:            }
2604:
2605:            /** 
2606:             * Return whether or not this RCL can be flattened out of a tree.
2607:             * It can only be flattened if the expressions are all cloneable.
2608:             *
2609:             * @return boolean	Whether or not this RCL can be flattened out of a tree.
2610:             */
2611:            public boolean isCloneable() {
2612:                boolean retcode = true;
2613:                int size = size();
2614:
2615:                for (int index = 0; index < size; index++) {
2616:                    ResultColumn rc = (ResultColumn) elementAt(index);
2617:
2618:                    if (!rc.getExpression().isCloneable()) {
2619:                        retcode = false;
2620:                        break;
2621:                    }
2622:                }
2623:
2624:                return retcode;
2625:            }
2626:
2627:            /**
2628:             * Remap all ColumnReferences in this tree to be clones of the
2629:             * underlying expression.
2630:             *
2631:             * @exception StandardException			Thrown on error
2632:             */
2633:            public void remapColumnReferencesToExpressions()
2634:                    throws StandardException {
2635:                int size = size();
2636:                for (int index = 0; index < size; index++) {
2637:                    ResultColumn rc = (ResultColumn) elementAt(index);
2638:
2639:                    // The expression may be null if this column is an identity
2640:                    // column generated always. If the expression is not null, it
2641:                    // is a ColumnReference; we call through to the ColumnReference
2642:                    // to give it a chance to remap itself from the outer query
2643:                    // node to this one.
2644:                    if (rc.getExpression() != null)
2645:                        rc.setExpression(rc.getExpression()
2646:                                .remapColumnReferencesToExpressions());
2647:                }
2648:            }
2649:
2650:            /*
2651:             ** Indicate that the conglomerate is an index, so we need to generate a
2652:             ** RowLocation as the last column of the result set.
2653:             **
2654:             ** @param cid	The conglomerate id of the index
2655:             */
2656:            void setIndexRow(long cid, boolean forUpdate) {
2657:                indexRow = true;
2658:                conglomerateId = cid;
2659:                this .forUpdate = forUpdate;
2660:            }
2661:
2662:            /* Debugging methods */
2663:
2664:            /**
2665:             * Verify that all ResultColumns and their expressions have type information
2666:             * and that the type information between the respective RCs and
2667:             * expressions matches.
2668:             *
2669:             * @return boolean	Whether or not the type information is consistent
2670:             */
2671:            public boolean hasConsistentTypeInfo() throws StandardException {
2672:                boolean isConsistent = true;
2673:
2674:                if (SanityManager.DEBUG) {
2675:                    int size = size();
2676:                    for (int index = 0; index < size; index++) {
2677:                        ResultColumn rc = (ResultColumn) elementAt(index);
2678:                        ValueNode expr = rc.getExpression();
2679:                        DataTypeDescriptor rcDTS = rc.getTypeServices();
2680:                        DataTypeDescriptor exDTS = expr.getTypeServices();
2681:
2682:                        if (rcDTS == null || exDTS == null) {
2683:                            isConsistent = false;
2684:                            break;
2685:                        }
2686:
2687:                        if (rcDTS.getClass().getName() != exDTS.getClass()
2688:                                .getName()) {
2689:                            isConsistent = false;
2690:                            break;
2691:                        }
2692:                    }
2693:                }
2694:
2695:                return isConsistent;
2696:            }
2697:
2698:            /**
2699:             * Return whether or not this RCL contains an AllResultColumn.
2700:             * This is useful when dealing with SELECT * views which 
2701:             * reference tables that may have had columns added to them via 
2702:             * ALTER TABLE since the view was created.
2703:             *
2704:             * @return Whether or not this RCL contains an AllResultColumn.
2705:             */
2706:            public boolean containsAllResultColumn() {
2707:                boolean containsAllResultColumn = false;
2708:
2709:                int size = size();
2710:                for (int index = 0; index < size; index++) {
2711:                    if (elementAt(index) instanceof  AllResultColumn) {
2712:                        containsAllResultColumn = true;
2713:                        break;
2714:                    }
2715:                }
2716:
2717:                return containsAllResultColumn;
2718:            }
2719:
2720:            /**
2721:             * Count the number of RCs in the list that are referenced.
2722:             *
2723:             * @return	The number of RCs in the list that are referenced.
2724:             */
2725:            public int countReferencedColumns() {
2726:                int numReferenced = 0;
2727:
2728:                int size = size();
2729:                for (int index = 0; index < size; index++) {
2730:                    ResultColumn rc = (ResultColumn) elementAt(index);
2731:                    if (rc.isReferenced()) {
2732:                        numReferenced++;
2733:                    }
2734:                }
2735:                return numReferenced;
2736:            }
2737:
2738:            /**
2739:             * Record the column ids of the referenced columns in the specified array.
2740:             *
2741:             * @param idArray	int[] for column ids
2742:             * @param basis		0 (for 0-based ids) or 1 (for 1-based ids)
2743:             */
2744:            public void recordColumnReferences(int[] idArray, int basis) {
2745:                int currArrayElement = 0;
2746:                int size = size();
2747:                for (int index = 0; index < size; index++) {
2748:                    ResultColumn rc = (ResultColumn) elementAt(index);
2749:
2750:                    if (rc.isReferenced()) {
2751:                        idArray[currArrayElement++] = index + basis;
2752:                    }
2753:                }
2754:            }
2755:
2756:            /**
2757:             * Record the top level ColumnReferences in the specified array
2758:             * and table map
2759:             * This is useful when checking for uniqueness conditions.
2760:             * NOTE: All top level CRs assumed to be from the same table.
2761:             *		 The size of the array is expected to be the # of columns
2762:             *		 in the table of interest + 1, so we use 1-base column #s.
2763:             *
2764:             * @param colArray1	boolean[] for columns
2765:             * @param tableColMap	JBitSet[] for tables
2766:             * @param tableNumber	Table number of column references
2767:             */
2768:            public void recordColumnReferences(boolean[] colArray1,
2769:                    JBitSet[] tableColMap, int tableNumber) {
2770:                int size = size();
2771:                for (int index = 0; index < size; index++) {
2772:                    int columnNumber;
2773:                    ResultColumn rc = (ResultColumn) elementAt(index);
2774:
2775:                    if (!(rc.getExpression() instanceof  ColumnReference)) {
2776:                        continue;
2777:                    }
2778:
2779:                    columnNumber = ((ColumnReference) rc.getExpression())
2780:                            .getColumnNumber();
2781:                    colArray1[columnNumber] = true;
2782:                    tableColMap[tableNumber].set(columnNumber);
2783:                }
2784:            }
2785:
2786:            /**
2787:             * Return whether or not all of the RCs in the list whose
2788:             * expressions are ColumnReferences are 
2789:             * from the same table.  One place this
2790:             * is useful for distinct elimination based on the existence
2791:             * of a uniqueness condition.
2792:             *
2793:             * @return	-1 if all of the top level CRs in the RCL
2794:             *			are not ColumnReferences from the same table,
2795:             *			else the tableNumber
2796:             */
2797:            int allTopCRsFromSameTable() {
2798:                int tableNumber = -1;
2799:
2800:                int size = size();
2801:                for (int index = 0; index < size; index++) {
2802:                    ResultColumn rc = (ResultColumn) elementAt(index);
2803:                    ValueNode vn = rc.getExpression();
2804:                    if (!(vn instanceof  ColumnReference)) {
2805:                        continue;
2806:                    }
2807:
2808:                    // Remember the tableNumber from the first CR
2809:                    ColumnReference cr = (ColumnReference) vn;
2810:                    if (tableNumber == -1) {
2811:                        tableNumber = cr.getTableNumber();
2812:                    } else if (tableNumber != cr.getTableNumber()) {
2813:                        return -1;
2814:                    }
2815:                }
2816:                return tableNumber;
2817:            }
2818:
2819:            /**
2820:             * Clear the column references from the RCL. (Restore RCL back to a state
2821:             * where none of the RCs are marked as referenced.)
2822:             */
2823:            public void clearColumnReferences() {
2824:                int size = size();
2825:                for (int index = 0; index < size; index++) {
2826:                    ResultColumn rc = (ResultColumn) elementAt(index);
2827:
2828:                    if (rc.isReferenced()) {
2829:                        rc.setUnreferenced();
2830:                    }
2831:                }
2832:            }
2833:
2834:            /**
2835:             * Copy the referenced RCs from this list to the supplied target list.
2836:             *
2837:             * @param targetList	The list to copy to
2838:             */
2839:            public void copyReferencedColumnsToNewList(
2840:                    ResultColumnList targetList) {
2841:                int size = size();
2842:                for (int index = 0; index < size; index++) {
2843:                    ResultColumn rc = (ResultColumn) elementAt(index);
2844:
2845:                    if (rc.isReferenced()) {
2846:                        targetList.addElement(rc);
2847:                    }
2848:                }
2849:            }
2850:
2851:            /**
2852:             * Copy the RCs from this list to the supplied target list.
2853:             *
2854:             * @param targetList	The list to copy to,
2855:             * @param copyList      1 based bitMap we copy columns associated with set bits.
2856:             */
2857:            public void copyColumnsToNewList(ResultColumnList targetList,
2858:                    FormatableBitSet copyList) {
2859:                int size = size();
2860:                for (int index = 0; index < size; index++) {
2861:                    ResultColumn rc = (ResultColumn) elementAt(index);
2862:                    if (copyList.isSet(rc.getColumnPosition())) {
2863:                        targetList.addElement(rc);
2864:                    }
2865:                }
2866:            }
2867:
2868:            /**
2869:             * Get a FormatableBitSet of the columns referenced in this rcl
2870:             *
2871:             * @return the FormatableBitSet
2872:             */
2873:            public FormatableBitSet getColumnReferenceMap() {
2874:                FormatableBitSet colMap = new FormatableBitSet(size());
2875:                int size = size();
2876:                for (int index = 0; index < size; index++) {
2877:                    ResultColumn rc = (ResultColumn) elementAt(index);
2878:                    if (rc.isReferenced()) {
2879:                        colMap.set(index);
2880:                    }
2881:                }
2882:                return colMap;
2883:            }
2884:
2885:            /**
2886:             * Or in any isReferenced booleans from the virtual column chain. That is the isReferenced bits on each
2887:             * ResultColumn on the list will be set if the ResultColumn is referenced or if any VirtualColumnNode in its
2888:             * expression chain refers to a referenced column.
2889:             */
2890:            void pullVirtualIsReferenced() {
2891:                int size = size();
2892:                for (int index = 0; index < size; index++) {
2893:                    ResultColumn rc = (ResultColumn) elementAt(index);
2894:                    rc.pullVirtualIsReferenced();
2895:                }
2896:            } // end of pullVirtualIsReferenced
2897:
2898:            public void clearTableNames() {
2899:                int size = size();
2900:                for (int index = 0; index < size; index++) {
2901:                    ResultColumn rc = (ResultColumn) elementAt(index);
2902:                    rc.clearTableName();
2903:                }
2904:            }
2905:
2906:            /**
2907:             * Set the value of whether or not a count mismatch is allowed between
2908:             * this RCL, as a derived column list, and an underlying RCL.  This is allowed
2909:             * for SELECT * views when an underlying table has had columns added to it
2910:             * via ALTER TABLE.
2911:             *
2912:             * @param allowed	Whether or not a mismatch is allowed.
2913:             */
2914:            protected void setCountMismatchAllowed(boolean allowed) {
2915:                countMismatchAllowed = allowed;
2916:            }
2917:
2918:            /**
2919:             * Return whether or not a count mismatch is allowed between this RCL,
2920:             * as a derived column list, and an underlying RCL.  This is allowed
2921:             * for SELECT * views when an underlying table has had columns added to it
2922:             * via ALTER TABLE.
2923:             *
2924:             * return Whether or not a mismatch is allowed.
2925:             */
2926:
2927:            protected boolean getCountMismatchAllowed() {
2928:                return countMismatchAllowed;
2929:            }
2930:
2931:            /**
2932:             * Get the size of all the columns added
2933:             * together.  Does <B>NOT</B> include the
2934:             * column overhead that the store requires.
2935:             * Also, will be a very rough estimate for
2936:             * user types.
2937:             *
2938:             * @return the size
2939:             */
2940:            public int getTotalColumnSize() {
2941:                int colSize = 0;
2942:                int size = size();
2943:                for (int index = 0; index < size; index++) {
2944:                    colSize += ((ResultColumn) elementAt(index))
2945:                            .getMaximumColumnSize();
2946:                }
2947:                return colSize;
2948:            }
2949:
2950:            /** 
2951:             * Generate an RCL to match the contents of a ResultSetMetaData.
2952:             * This is useful when dealing with VTIs.
2953:             *
2954:             * @param rsmd			The ResultSetMetaData.
2955:             * @param tableName		The TableName for the BCNs.
2956:             * @param javaClassName	The name of the VTI
2957:             *
2958:             * @exception StandardException			Thrown on error
2959:             */
2960:            public void createListFromResultSetMetaData(ResultSetMetaData rsmd,
2961:                    TableName tableName, String javaClassName)
2962:                    throws StandardException {
2963:                try {
2964:                    // JDBC columns #s are 1-based
2965:                    // Check to make sure # of columns >= 1
2966:                    int numColumns = rsmd.getColumnCount();
2967:
2968:                    if (numColumns <= 0) {
2969:                        throw StandardException.newException(
2970:                                SQLState.LANG_INVALID_V_T_I_COLUMN_COUNT,
2971:                                javaClassName, String.valueOf(numColumns));
2972:                    }
2973:
2974:                    for (int index = 1; index <= numColumns; index++) {
2975:                        boolean nullableResult = (rsmd.isNullable(index) != ResultSetMetaData.columnNoNulls);
2976:
2977:                        TypeId cti;
2978:
2979:                        int jdbcColumnType = rsmd.getColumnType(index);
2980:
2981:                        switch (jdbcColumnType) {
2982:                        case org.apache.derby.iapi.reference.JDBC20Translation.SQL_TYPES_JAVA_OBJECT:
2983:                        case Types.OTHER: {
2984:                            cti = TypeId.getUserDefinedTypeId(rsmd
2985:                                    .getColumnTypeName(index), false);
2986:                            break;
2987:                        }
2988:                        default: {
2989:                            cti = TypeId.getBuiltInTypeId(jdbcColumnType);
2990:                            break;
2991:                        }
2992:                        }
2993:
2994:                        // Handle the case where a VTI returns a bad column type
2995:                        if (cti == null) {
2996:                            throw StandardException.newException(
2997:                                    SQLState.LANG_BAD_J_D_B_C_TYPE_INFO,
2998:                                    Integer.toString(index));
2999:                        }
3000:
3001:                        // Get the maximum byte storage for this column
3002:                        int maxWidth;
3003:
3004:                        /* Get maximum byte storage from rsmd for variable
3005:                         * width types, set it to MAXINT for the long types,
3006:                         * otherwise get it from the TypeId
3007:                         */
3008:                        if (cti.variableLength()) {
3009:                            maxWidth = rsmd.getColumnDisplaySize(index);
3010:                        } else if (jdbcColumnType == Types.LONGVARCHAR
3011:                                || jdbcColumnType == Types.LONGVARBINARY) {
3012:                            maxWidth = Integer.MAX_VALUE;
3013:                        } else {
3014:                            maxWidth = 0;
3015:                        }
3016:
3017:                        int precision = cti.isDecimalTypeId() ? rsmd
3018:                                .getPrecision(index) : 0;
3019:                        int scale = cti.isDecimalTypeId() ? rsmd
3020:                                .getScale(index) : 0;
3021:                        DataTypeDescriptor dts = new DataTypeDescriptor(cti,
3022:                                precision, scale, nullableResult, maxWidth);
3023:                        ValueNode bcn = (ValueNode) getNodeFactory().getNode(
3024:                                C_NodeTypes.BASE_COLUMN_NODE,
3025:                                rsmd.getColumnName(index), tableName, dts,
3026:                                getContextManager());
3027:                        ResultColumn rc = (ResultColumn) getNodeFactory()
3028:                                .getNode(C_NodeTypes.RESULT_COLUMN,
3029:                                        rsmd.getColumnName(index), bcn,
3030:                                        getContextManager());
3031:                        rc.setType(dts);
3032:                        addResultColumn(rc);
3033:                    }
3034:                } catch (Throwable t) {
3035:                    if (t instanceof  StandardException) {
3036:                        throw (StandardException) t;
3037:                    } else {
3038:                        throw StandardException.unexpectedUserException(t);
3039:                    }
3040:                }
3041:            }
3042:
3043:            /**
3044:             * Add an RC to the end of the list for the RID from an index.
3045:             * NOTE: RC.expression is a CurrentRowLocationNode.  This was previously only used
3046:             * for non-select DML.  We test for this node when generating the holder above
3047:             * and generate the expected code.  (We really should create yet another new node
3048:             * type with its own code generation.)
3049:             *
3050:             * @exception StandardException			Thrown on error
3051:             */
3052:            public void addRCForRID() throws StandardException {
3053:                ResultColumn rowLocationColumn;
3054:                CurrentRowLocationNode rowLocationNode;
3055:
3056:                /* Generate the RowLocation column */
3057:                rowLocationNode = (CurrentRowLocationNode) getNodeFactory()
3058:                        .getNode(C_NodeTypes.CURRENT_ROW_LOCATION_NODE,
3059:                                getContextManager());
3060:                rowLocationColumn = (ResultColumn) getNodeFactory().getNode(
3061:                        C_NodeTypes.RESULT_COLUMN, "", rowLocationNode,
3062:                        getContextManager());
3063:                rowLocationColumn.markGenerated();
3064:
3065:                /* Append to the ResultColumnList */
3066:                addResultColumn(rowLocationColumn);
3067:            }
3068:
3069:            /**
3070:             * Walk the list and mark all RCs as unreferenced.  This is useful
3071:             * when recalculating which RCs are referenced at what level like
3072:             * when deciding which columns need to be returned from a non-matching
3073:             * index scan (as opposed to those returned from the base table).
3074:             *
3075:             * @exception StandardException		Thrown on error
3076:             */
3077:            public void markAllUnreferenced() throws StandardException {
3078:                int size = size();
3079:
3080:                for (int index = 0; index < size; index++) {
3081:                    ResultColumn resultColumn = (ResultColumn) elementAt(index);
3082:                    resultColumn.setUnreferenced();
3083:                }
3084:            }
3085:
3086:            /**
3087:             * Determine if all of the RC.expressions are columns in the source result set.
3088:             * This is useful for determining if we need to do reflection
3089:             * at execution time.
3090:             *
3091:             * @param sourceRS	The source ResultSet.
3092:             *
3093:             * @return Whether or not all of the RC.expressions are columns in the source result set.
3094:             */
3095:            boolean allExpressionsAreColumns(ResultSetNode sourceRS) {
3096:                int size = size();
3097:
3098:                for (int index = 0; index < size; index++) {
3099:                    ResultColumn resultColumn;
3100:                    ValueNode expr;
3101:
3102:                    resultColumn = (ResultColumn) elementAt(index);
3103:                    expr = resultColumn.getExpression();
3104:                    if (!(expr instanceof  VirtualColumnNode)
3105:                            && !(expr instanceof  ColumnReference)) {
3106:                        return false;
3107:                    }
3108:
3109:                    /* If the expression is a VirtualColumnNode, make sure that the column
3110:                     * is coming from the source result set, ie, that it is not a correlated
3111:                     * column.
3112:                     */
3113:                    if (expr instanceof  VirtualColumnNode) {
3114:                        VirtualColumnNode vcn = (VirtualColumnNode) expr;
3115:                        if (vcn.getSourceResultSet() != sourceRS) {
3116:                            vcn.setCorrelated();
3117:                            return false;
3118:                        }
3119:                    }
3120:
3121:                    /* Make sure this is not a correlated CR */
3122:                    if (expr instanceof  ColumnReference) {
3123:                        ColumnReference cr = (ColumnReference) expr;
3124:                        if (cr.getCorrelated()) {
3125:                            return false;
3126:                        }
3127:                    }
3128:                }
3129:                return true;
3130:            }
3131:
3132:            /**
3133:             * Map the source columns to these columns.  Build an array to represent the mapping.
3134:             * For each RC, if the expression is simply a VCN or a CR then set the array element to be
3135:             * the virtual column number of the source RC.  Otherwise, set the array element to
3136:             * -1.
3137:             * This is useful for determining if we need to do reflection
3138:             * at execution time.
3139:             *
3140:             * @return	Array representiong mapping of RCs to source RCs.
3141:             */
3142:            int[] mapSourceColumns() {
3143:                int[] mapArray = new int[size()];
3144:                ResultColumn resultColumn;
3145:
3146:                int size = size();
3147:
3148:                for (int index = 0; index < size; index++) {
3149:                    resultColumn = (ResultColumn) elementAt(index);
3150:                    if (resultColumn.getExpression() instanceof  VirtualColumnNode) {
3151:                        VirtualColumnNode vcn = (VirtualColumnNode) resultColumn
3152:                                .getExpression();
3153:
3154:                        // Can't deal with correlated VCNs
3155:                        if (vcn.getCorrelated()) {
3156:                            mapArray[index] = -1;
3157:                        } else {
3158:                            // Virtual column #s are 1-based
3159:                            mapArray[index] = vcn.getSourceColumn()
3160:                                    .getVirtualColumnId();
3161:                        }
3162:                    } else if (resultColumn.getExpression() instanceof  ColumnReference) {
3163:                        ColumnReference cr = (ColumnReference) resultColumn
3164:                                .getExpression();
3165:
3166:                        // Can't deal with correlated CRs
3167:                        if (cr.getCorrelated()) {
3168:                            mapArray[index] = -1;
3169:                        } else {
3170:                            // Virtual column #s are 1-based
3171:                            mapArray[index] = cr.getSource()
3172:                                    .getVirtualColumnId();
3173:                        }
3174:                    } else {
3175:                        mapArray[index] = -1;
3176:                    }
3177:                }
3178:
3179:                return mapArray;
3180:            }
3181:
3182:            /** Set the nullability of every ResultColumn in this list */
3183:            public void setNullability(boolean nullability) {
3184:                int size = size();
3185:
3186:                for (int index = 0; index < size; index++) {
3187:                    ResultColumn resultColumn = (ResultColumn) elementAt(index);
3188:                    resultColumn.setNullability(nullability);
3189:                }
3190:            }
3191:
3192:            /**
3193:             * Generate a FormatableBitSet representing the columns that are referenced in this RCL.
3194:             * The caller decides if they want this FormatableBitSet if every RC is referenced.
3195:             * 
3196:             * @param positionedUpdate Whether or not the scan that the RCL 
3197:             *						belongs to is for update w/o a column list
3198:             * @param always		Whether or not caller always wants a non-null FormatableBitSet if
3199:             *						all RCs are referenced.
3200:             * @param onlyBCNs		If true, only set bit if expression is a BaseColumnNode,
3201:             *						otherwise set bit for all referenced RCs.
3202:             *
3203:             * @return The FormatableBitSet representing the referenced RCs.
3204:             */
3205:
3206:            FormatableBitSet getReferencedFormatableBitSet(
3207:                    boolean positionedUpdate, boolean always, boolean onlyBCNs) {
3208:                int index;
3209:                int colsAdded = 0;
3210:                int size = size();
3211:
3212:                FormatableBitSet newReferencedCols = new FormatableBitSet(size);
3213:
3214:                /*
3215:                 ** For an updatable cursor, we need
3216:                 ** all columns.
3217:                 */
3218:                if (positionedUpdate) {
3219:                    if (always) {
3220:                        /* Set all bits in the bit map */
3221:                        for (index = 0; index < size; index++) {
3222:                            newReferencedCols.set(index);
3223:                        }
3224:
3225:                        return newReferencedCols;
3226:                    } else {
3227:                        return null;
3228:                    }
3229:                }
3230:
3231:                for (index = 0; index < size; index++) {
3232:                    ResultColumn oldCol = (ResultColumn) elementAt(index);
3233:                    if (oldCol.isReferenced()) {
3234:                        /* Skip RCs whose expression is not a BCN
3235:                         * when requested to do so.
3236:                         */
3237:                        if (onlyBCNs
3238:                                && !(oldCol.getExpression() instanceof  BaseColumnNode)) {
3239:                            continue;
3240:                        }
3241:                        newReferencedCols.set(index);
3242:                        colsAdded++;
3243:                    }
3244:                }
3245:
3246:                /* Return the FormatableBitSet if not all RCs are referenced or if
3247:                 * the caller always wants the FormatableBitSet returned.
3248:                 */
3249:                if (colsAdded != index || always) {
3250:                    return newReferencedCols;
3251:                } else {
3252:                    return null;
3253:                }
3254:            }
3255:
3256:            /**
3257:             * Create a new, compacted RCL based on the referenced RCs
3258:             * in this list.  If the RCL being compacted is for an
3259:             * updatable scan, then we simply return this.
3260:             *
3261:             * The caller tells us whether or not they want a new list
3262:             * if there is no compaction because all RCs are referenced.
3263:             * This is useful in the case where the caller needs a new
3264:             * RCL for existing RCs so that it can augment the new list.
3265:             * 
3266:             * @param positionedUpdate Whether or not the scan that the RCL 
3267:             *						belongs to is for update w/o a column list
3268:             * @param always		Whether or not caller always wants a new RCL
3269:             *
3270:             * @return The compacted RCL if compaction occurred, otherwise return this RCL.
3271:             *
3272:             * @exception StandardException		Thrown on error
3273:             */
3274:            ResultColumnList compactColumns(boolean positionedUpdate,
3275:                    boolean always) throws StandardException {
3276:                int index;
3277:                int colsAdded = 0;
3278:
3279:                /*
3280:                 ** For an updatable cursor, we need
3281:                 ** all columns.
3282:                 */
3283:                if (positionedUpdate) {
3284:                    return this ;
3285:                }
3286:
3287:                ResultColumnList newCols = (ResultColumnList) getNodeFactory()
3288:                        .getNode(C_NodeTypes.RESULT_COLUMN_LIST,
3289:                                getContextManager());
3290:
3291:                int size = size();
3292:                for (index = 0; index < size; index++) {
3293:                    ResultColumn oldCol = (ResultColumn) elementAt(index);
3294:                    if (oldCol.isReferenced()) {
3295:                        newCols.addResultColumn(oldCol);
3296:                        colsAdded++;
3297:                    }
3298:                }
3299:
3300:                /* Return new RCL if we found unreferenced columns or if
3301:                 * the caller always wants a new list. 
3302:                 */
3303:                if (colsAdded != index || always) {
3304:                    return newCols;
3305:                } else {
3306:                    return this ;
3307:                }
3308:            }
3309:
3310:            /**
3311:             * Remove the columns which are join columns (in the
3312:             * joinColumns RCL) from this list.  This is useful
3313:             * for a JOIN with a USING clause.
3314:             * 
3315:             * @param joinColumns	The list of join columns
3316:             */
3317:            void removeJoinColumns(ResultColumnList joinColumns) {
3318:                int jcSize = joinColumns.size();
3319:                for (int index = 0; index < jcSize; index++) {
3320:                    ResultColumn joinRC = (ResultColumn) joinColumns
3321:                            .elementAt(index);
3322:                    String columnName = joinRC.getName();
3323:
3324:                    // columnName should always be non-null
3325:                    if (SanityManager.DEBUG) {
3326:                        SanityManager.ASSERT(columnName != null,
3327:                                "columnName should be non-null");
3328:                    }
3329:
3330:                    ResultColumn rightRC = getResultColumn(columnName);
3331:
3332:                    // Remove the RC from this list.
3333:                    if (rightRC != null) {
3334:                        removeElement(rightRC);
3335:                    }
3336:                }
3337:            }
3338:
3339:            /**
3340:             * Get the join columns from this list.
3341:             * This is useful for a join with a USING clause.  
3342:             * (ANSI specifies that the join columns appear 1st.) 
3343:             *
3344:             * @param joinColumns	A list of the join columns.
3345:             *
3346:             * @return A list of the join columns from this list
3347:             */
3348:            ResultColumnList getJoinColumns(ResultColumnList joinColumns) {
3349:                ResultColumnList newRCL = new ResultColumnList();
3350:
3351:                /* Find all of the join columns and put them 1st on the
3352:                 * new RCL.
3353:                 */
3354:                int jcSize = joinColumns.size();
3355:                for (int index = 0; index < jcSize; index++) {
3356:                    ResultColumn joinRC = (ResultColumn) joinColumns
3357:                            .elementAt(index);
3358:                    String columnName = joinRC.getName();
3359:
3360:                    // columnName should always be non-null
3361:                    if (SanityManager.DEBUG) {
3362:                        SanityManager.ASSERT(columnName != null,
3363:                                "columnName should be non-null");
3364:                    }
3365:
3366:                    ResultColumn xferRC = getResultColumn(columnName);
3367:
3368:                    // Add the RC to the new list.
3369:                    newRCL.addElement(xferRC);
3370:                }
3371:                return newRCL;
3372:            }
3373:
3374:            /**
3375:             * Reset the virtual column ids for all of the
3376:             * underlying RCs.  (Virtual column ids are 1-based.)
3377:             */
3378:            void resetVirtualColumnIds() {
3379:                int size = size();
3380:
3381:                for (int index = 0; index < size; index++) {
3382:                    /* ResultColumns are 1-based */
3383:                    ((ResultColumn) elementAt(index))
3384:                            .setVirtualColumnId(index + 1);
3385:                }
3386:            }
3387:
3388:            /**
3389:             * Return whether or not the same result row can be used for all
3390:             * rows returned by the associated ResultSet.  This is possible
3391:             * if all entries in the list are constants or AggregateNodes.
3392:             *
3393:             * @return Whether or not the same result row can be used for all
3394:             * rows returned by the associated ResultSet. 
3395:             */
3396:            boolean reusableResult() {
3397:                int size = size();
3398:
3399:                for (int index = 0; index < size; index++) {
3400:                    ResultColumn rc = (ResultColumn) elementAt(index);
3401:
3402:                    if ((rc.getExpression() instanceof  ConstantNode)
3403:                            || (rc.getExpression() instanceof  AggregateNode)) {
3404:                        continue;
3405:                    }
3406:                    return false;
3407:                }
3408:                return true;
3409:            }
3410:
3411:            /**
3412:             * Get an array of column positions (1-based) for all the columns
3413:             * in this RCL. Assumes that all the columns are in the passed-in
3414:             * table
3415:             *
3416:             * @return the array of strings
3417:             *
3418:             *	@exception	throws StandardException on error
3419:             */
3420:            public int[] getColumnPositions(TableDescriptor td)
3421:                    throws StandardException {
3422:                int size = size();
3423:                int[] myPositions = new int[size];
3424:                String columnName;
3425:                ColumnDescriptor cd;
3426:
3427:                for (int index = 0; index < size; index++) {
3428:                    ResultColumn resultColumn = (ResultColumn) elementAt(index);
3429:                    columnName = resultColumn.getName();
3430:                    cd = td.getColumnDescriptor(columnName);
3431:
3432:                    if (cd == null) {
3433:                        throw StandardException.newException(
3434:                                SQLState.LANG_COLUMN_NOT_FOUND_IN_TABLE,
3435:                                columnName, td.getQualifiedName());
3436:                    }
3437:
3438:                    myPositions[index] = cd.getPosition();
3439:                }
3440:
3441:                return myPositions;
3442:            }
3443:
3444:            /**
3445:             * Get an array of strings for all the columns
3446:             * in this RCL.
3447:             *
3448:             * @return the array of strings
3449:             */
3450:            public String[] getColumnNames() {
3451:                String strings[] = new String[size()];
3452:
3453:                int size = size();
3454:
3455:                for (int index = 0; index < size; index++) {
3456:                    ResultColumn resultColumn = (ResultColumn) elementAt(index);
3457:                    strings[index] = resultColumn.getName();
3458:                }
3459:                return strings;
3460:            }
3461:
3462:            /**
3463:             * Replace any DEFAULTs with the associated tree for the default.
3464:             *
3465:             * @param ttd	The TableDescriptor for the target table.
3466:             * @param tcl	The RCL for the target table.
3467:             *
3468:             * @exception StandardException		Thrown on error
3469:             */
3470:            void replaceDefaults(TableDescriptor ttd, ResultColumnList tcl)
3471:                    throws StandardException {
3472:                int size = size();
3473:
3474:                for (int index = 0; index < size; index++) {
3475:                    ResultColumn rc = (ResultColumn) elementAt(index);
3476:
3477:                    if (rc.isDefaultColumn()) {
3478:                        //				DefaultNode defaultNode = (DefaultNode) rc.getExpression();
3479:                        // Get ColumnDescriptor by name or by position?
3480:                        ColumnDescriptor cd;
3481:                        if (tcl == null) {
3482:                            cd = ttd.getColumnDescriptor(index + 1);
3483:                        } else {
3484:                            ResultColumn trc = (ResultColumn) tcl
3485:                                    .elementAt(index);
3486:                            cd = ttd.getColumnDescriptor(trc.getName());
3487:                        }
3488:
3489:                        // Too many RCs if no ColumnDescriptor
3490:                        if (cd == null) {
3491:                            throw StandardException.newException(
3492:                                    SQLState.LANG_TOO_MANY_RESULT_COLUMNS, ttd
3493:                                            .getQualifiedName());
3494:                        }
3495:
3496:                        if (cd.isAutoincrement()) {
3497:                            rc.setAutoincrementGenerated();
3498:                        } // end of if ()
3499:
3500:                        DefaultInfoImpl defaultInfo = (DefaultInfoImpl) cd
3501:                                .getDefaultInfo();
3502:                        if (defaultInfo != null) {
3503:                            /* Query is dependent on the DefaultDescriptor */
3504:                            DefaultDescriptor defaultDescriptor = cd
3505:                                    .getDefaultDescriptor(getDataDictionary());
3506:                            getCompilerContext().createDependency(
3507:                                    defaultDescriptor);
3508:
3509:                            rc.setExpression(DefaultNode.parseDefault(
3510:                                    defaultInfo.getDefaultText(),
3511:                                    getLanguageConnectionContext(),
3512:                                    getCompilerContext()));
3513:
3514:                        } else {
3515:                            rc
3516:                                    .setExpression((ValueNode) getNodeFactory()
3517:                                            .getNode(
3518:                                                    C_NodeTypes.UNTYPED_NULL_CONSTANT_NODE,
3519:                                                    getContextManager()));
3520:                        }
3521:                        rc.setDefaultColumn(false);
3522:                    }
3523:                }
3524:            }
3525:
3526:            /**
3527:             * Walk the RCL and check for DEFAULTs.  DEFAULTs
3528:             * are invalid at the time that this method is called,
3529:             * so we throw an exception if found.
3530:             * NOTE: The grammar allows:
3531:             *		VALUES DEFAULT;
3532:             *
3533:             * @exception StandardException		Thrown on error
3534:             */
3535:            void checkForInvalidDefaults() throws StandardException {
3536:                int size = size();
3537:
3538:                for (int index = 0; index < size; index++) {
3539:                    ResultColumn rc = (ResultColumn) elementAt(index);
3540:
3541:                    if (rc.isAutoincrementGenerated())
3542:                        continue;
3543:
3544:                    if (rc.isDefaultColumn()) {
3545:                        throw StandardException
3546:                                .newException(SQLState.LANG_INVALID_USE_OF_DEFAULT);
3547:                    }
3548:                }
3549:            }
3550:
3551:            /**
3552:             * Verify that all of the RCs in this list are comparable.
3553:             * 
3554:             * @exception StandardException		Thrown on error
3555:             */
3556:            void verifyAllOrderable() throws StandardException {
3557:                int size = size();
3558:
3559:                for (int index = 0; index < size; index++) {
3560:                    ResultColumn rc = (ResultColumn) elementAt(index);
3561:                    rc.verifyOrderable();
3562:                }
3563:            }
3564:
3565:            /**
3566:             *	Build this ResultColumnList from a table description and
3567:             *	an array of column IDs.
3568:             *
3569:             *	@param	table		describes the table
3570:             *	@param	columnIDs	column positions in that table (1-based)
3571:             *
3572:             * @exception StandardException		Thrown on error
3573:             */
3574:            public void populate(TableDescriptor table, int[] columnIDs)
3575:                    throws StandardException {
3576:                if (columnIDs == null) {
3577:                    return;
3578:                }
3579:
3580:                int count = columnIDs.length;
3581:                TableName tableName = makeTableName(table.getSchemaName(),
3582:                        table.getName());
3583:                String columnName;
3584:                int columnPosition;
3585:                ResultColumn rc;
3586:
3587:                for (int i = 0; i < count; i++) {
3588:                    columnPosition = columnIDs[i];
3589:                    columnName = table.getColumnDescriptor(columnPosition)
3590:                            .getColumnName();
3591:
3592:                    rc = makeColumnFromName(columnName);
3593:
3594:                    addResultColumn(rc);
3595:                }
3596:
3597:            }
3598:
3599:            private ResultColumn makeColumnFromName(String columnName)
3600:                    throws StandardException {
3601:                ResultColumn resultColumn = (ResultColumn) getNodeFactory()
3602:                        .getNode(C_NodeTypes.RESULT_COLUMN, columnName, null,
3603:                                getContextManager());
3604:
3605:                return resultColumn;
3606:            }
3607:
3608:            private ResultColumn makeColumnReferenceFromName(
3609:                    TableName tableName, String columnName)
3610:                    throws StandardException {
3611:                ContextManager cm = getContextManager();
3612:                NodeFactory nodeFactory = getNodeFactory();
3613:
3614:                ResultColumn rc = (ResultColumn) nodeFactory.getNode(
3615:                        C_NodeTypes.RESULT_COLUMN, null, nodeFactory.getNode(
3616:                                C_NodeTypes.COLUMN_REFERENCE, columnName,
3617:                                tableName, cm), cm);
3618:
3619:                return rc;
3620:            }
3621:
3622:            /**
3623:             * check if any autoincrement columns exist in the result column list.
3624:             * called from insert or update where you cannot insert/update the value
3625:             * of an autoincrement column.
3626:             *
3627:             * @exception StandardException		If the column is an ai column
3628:             */
3629:            public void checkAutoincrement(ResultColumnList sourceRSRCL)
3630:                    throws StandardException {
3631:                int size = size();
3632:
3633:                for (int index = 0; index < size; index++) {
3634:                    ResultColumn rc = (ResultColumn) elementAt(index);
3635:                    ResultColumn sourceRC = (ResultColumn) ((sourceRSRCL == null) ? null
3636:                            : sourceRSRCL.elementAt(index));
3637:                    ColumnDescriptor cd = rc.getTableColumnDescriptor();
3638:
3639:                    if ((cd != null) && (cd.isAutoincrement())) {
3640:                        if ((sourceRC != null)
3641:                                && (sourceRC.isAutoincrementGenerated())) {
3642:                            sourceRC.setColumnDescriptor(cd
3643:                                    .getTableDescriptor(), cd);
3644:
3645:                        } else {
3646:                            if (cd.isAutoincAlways())
3647:                                throw StandardException.newException(
3648:                                        SQLState.LANG_AI_CANNOT_MODIFY_AI, rc
3649:                                                .getName());
3650:                        }
3651:                    }
3652:                }
3653:            }
3654:
3655:            public void incOrderBySelect() {
3656:                orderBySelect++;
3657:            }
3658:
3659:            public void decOrderBySelect() {
3660:                orderBySelect--;
3661:            }
3662:
3663:            public int getOrderBySelect() {
3664:                return orderBySelect;
3665:            }
3666:
3667:            public void copyOrderBySelect(ResultColumnList src) {
3668:                orderBySelect = src.orderBySelect;
3669:            }
3670:
3671:            /* ****
3672:             * Take note of the size of this RCL _before_ we start
3673:             * processing/binding it.  This is so that, at bind time,
3674:             * we can tell if any columns in the RCL were added
3675:             * internally by us (i.e. they were not specified by the
3676:             * user and thus will not be returned to the user).
3677:             */
3678:            protected void markInitialSize() {
3679:                initialListSize = size();
3680:            }
3681:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.