Source Code Cross Referenced for DeleteNode.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) 


001:        /*
002:
003:           Derby - Class org.apache.derby.impl.sql.compile.DeleteNode
004:
005:           Licensed to the Apache Software Foundation (ASF) under one or more
006:           contributor license agreements.  See the NOTICE file distributed with
007:           this work for additional information regarding copyright ownership.
008:           The ASF licenses this file to you under the Apache License, Version 2.0
009:           (the "License"); you may not use this file except in compliance with
010:           the License.  You may obtain a copy of the License at
011:
012:              http://www.apache.org/licenses/LICENSE-2.0
013:
014:           Unless required by applicable law or agreed to in writing, software
015:           distributed under the License is distributed on an "AS IS" BASIS,
016:           WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017:           See the License for the specific language governing permissions and
018:           limitations under the License.
019:
020:         */
021:
022:        package org.apache.derby.impl.sql.compile;
023:
024:        import org.apache.derby.iapi.services.context.ContextManager;
025:
026:        import org.apache.derby.iapi.reference.SQLState;
027:        import org.apache.derby.iapi.error.StandardException;
028:
029:        import org.apache.derby.iapi.sql.conn.Authorizer;
030:        import org.apache.derby.iapi.sql.dictionary.DataDictionary;
031:        import org.apache.derby.iapi.sql.dictionary.ColumnDescriptor;
032:        import org.apache.derby.iapi.sql.dictionary.TableDescriptor;
033:        import org.apache.derby.iapi.sql.dictionary.GenericDescriptorList;
034:        import org.apache.derby.iapi.sql.dictionary.ColumnDescriptor;
035:        import org.apache.derby.iapi.sql.dictionary.ColumnDescriptorList;
036:
037:        import org.apache.derby.iapi.sql.ResultSet;
038:        import org.apache.derby.iapi.sql.StatementType;
039:
040:        import org.apache.derby.iapi.sql.compile.CompilerContext;
041:        import org.apache.derby.iapi.sql.compile.C_NodeTypes;
042:        import org.apache.derby.iapi.reference.ClassName;
043:
044:        import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
045:
046:        import org.apache.derby.iapi.sql.execute.CursorResultSet;
047:        import org.apache.derby.iapi.sql.execute.ConstantAction;
048:        import org.apache.derby.iapi.sql.execute.ExecPreparedStatement;
049:        import org.apache.derby.iapi.sql.execute.ExecRow;
050:
051:        import org.apache.derby.iapi.sql.Activation;
052:
053:        import org.apache.derby.iapi.services.sanity.SanityManager;
054:
055:        import org.apache.derby.iapi.services.compiler.MethodBuilder;
056:
057:        import org.apache.derby.iapi.store.access.StaticCompiledOpenConglomInfo;
058:        import org.apache.derby.iapi.store.access.TransactionController;
059:
060:        import org.apache.derby.vti.DeferModification;
061:
062:        import org.apache.derby.catalog.UUID;
063:        import org.apache.derby.iapi.services.io.FormatableBitSet;
064:
065:        import org.apache.derby.impl.sql.compile.ActivationClassBuilder;
066:
067:        import org.apache.derby.impl.sql.execute.DeleteConstantAction;
068:        import org.apache.derby.impl.sql.execute.FKInfo;
069:
070:        import java.lang.reflect.Modifier;
071:        import org.apache.derby.iapi.services.classfile.VMOpcode;
072:        import org.apache.derby.iapi.services.io.FormatableProperties;
073:        import java.util.Vector;
074:        import java.util.Hashtable;
075:        import java.util.Properties;
076:        import org.apache.derby.iapi.sql.compile.NodeFactory;
077:        import org.apache.derby.iapi.util.ReuseFactory;
078:        import org.apache.derby.iapi.sql.depend.Dependent;
079:        import org.apache.derby.iapi.sql.ResultDescription;
080:        import org.apache.derby.iapi.services.compiler.LocalField;
081:
082:        /**
083:         * A DeleteNode represents a DELETE statement. It is the top-level node
084:         * for the statement.
085:         *
086:         * For positioned delete, there may be no from table specified.
087:         * The from table will be derived from the cursor specification of
088:         * the named cursor.
089:         *
090:         * @author Jeff Lichtman
091:         */
092:
093:        public class DeleteNode extends DMLModStatementNode {
094:            /* Column name for the RowLocation column in the ResultSet */
095:            private static final String COLUMNNAME = "###RowLocationToDelete";
096:
097:            /* Filled in by bind. */
098:            protected boolean deferred;
099:            protected ExecRow emptyHeapRow;
100:            protected FromTable targetTable;
101:            protected FKInfo fkInfo;
102:            protected FormatableBitSet readColsBitSet;
103:
104:            private ConstantAction[] dependentConstantActions;
105:            private boolean cascadeDelete;
106:            private QueryTreeNode[] dependentNodes;
107:
108:            /**
109:             * Initializer for a DeleteNode.
110:             *
111:             * @param targetTableName	The name of the table to delete from
112:             * @param queryExpression	The query expression that will generate
113:             *				the rows to delete from the given table
114:             */
115:
116:            public void init(Object targetTableName, Object queryExpression) {
117:                super .init(queryExpression);
118:                this .targetTableName = (TableName) targetTableName;
119:            }
120:
121:            public String statementToString() {
122:                return "DELETE";
123:            }
124:
125:            /**
126:             * Bind this DeleteNode.  This means looking up tables and columns and
127:             * getting their types, and figuring out the result types of all
128:             * expressions, as well as doing view resolution, permissions checking,
129:             * etc.
130:             * <p>
131:             * If any indexes need to be updated, we add all the columns in the
132:             * base table to the result column list, so that we can use the column
133:             * values as look-up keys for the index rows to be deleted.  Binding a
134:             * delete will also massage the tree so that the ResultSetNode has 
135:             * column containing the RowLocation of the base row.
136:             *
137:             * @return	The bound query tree
138:             *
139:             * @exception StandardException		Thrown on error
140:             */
141:
142:            public QueryTreeNode bind() throws StandardException {
143:                // We just need select privilege on the where clause tables
144:                getCompilerContext()
145:                        .pushCurrentPrivType(Authorizer.SELECT_PRIV);
146:                try {
147:                    FromList fromList = (FromList) getNodeFactory().getNode(
148:                            C_NodeTypes.FROM_LIST,
149:                            getNodeFactory().doJoinOrderOptimization(),
150:                            getContextManager());
151:                    ResultColumn rowLocationColumn = null;
152:                    CurrentRowLocationNode rowLocationNode;
153:                    TableName cursorTargetTableName = null;
154:                    CurrentOfNode currentOfNode = null;
155:
156:                    DataDictionary dataDictionary = getDataDictionary();
157:                    super .bindTables(dataDictionary);
158:
159:                    // wait to bind named target table until the underlying
160:                    // cursor is bound, so that we can get it from the
161:                    // cursor if this is a positioned delete.
162:
163:                    // for positioned delete, get the cursor's target table.
164:                    if (SanityManager.DEBUG)
165:                        SanityManager.ASSERT(resultSet != null
166:                                && resultSet instanceof  SelectNode,
167:                                "Delete must have a select result set");
168:
169:                    SelectNode sel;
170:                    sel = (SelectNode) resultSet;
171:                    targetTable = (FromTable) sel.fromList.elementAt(0);
172:                    if (targetTable instanceof  CurrentOfNode) {
173:                        currentOfNode = (CurrentOfNode) targetTable;
174:
175:                        cursorTargetTableName = currentOfNode
176:                                .getBaseCursorTargetTableName();
177:                        // instead of an assert, we might say the cursor is not updatable.
178:                        if (SanityManager.DEBUG)
179:                            SanityManager.ASSERT(cursorTargetTableName != null);
180:                    }
181:
182:                    if (targetTable instanceof  FromVTI) {
183:                        targetVTI = (FromVTI) targetTable;
184:                        targetVTI.setTarget();
185:                    } else {
186:                        // positioned delete can leave off the target table.
187:                        // we get it from the cursor supplying the position.
188:                        if (targetTableName == null) {
189:                            // verify we have current of
190:                            if (SanityManager.DEBUG)
191:                                SanityManager
192:                                        .ASSERT(cursorTargetTableName != null);
193:
194:                            targetTableName = cursorTargetTableName;
195:                        }
196:                        // for positioned delete, we need to verify that
197:                        // the named table is the same as the cursor's target (base table name).
198:                        else if (cursorTargetTableName != null) {
199:                            // this match requires that the named table in the delete
200:                            // be the same as a base name in the cursor.
201:                            if (!targetTableName.equals(cursorTargetTableName)) {
202:                                throw StandardException.newException(
203:                                        SQLState.LANG_CURSOR_DELETE_MISMATCH,
204:                                        targetTableName, currentOfNode
205:                                                .getCursorName());
206:                            }
207:                        }
208:                    }
209:
210:                    // descriptor must exist, tables already bound.
211:                    verifyTargetTable();
212:
213:                    /* Generate a select list for the ResultSetNode - CurrentRowLocation(). */
214:                    if (SanityManager.DEBUG)
215:                        SanityManager
216:                                .ASSERT((resultSet.resultColumns == null),
217:                                        "resultColumns is expected to be null until bind time");
218:
219:                    if (targetTable instanceof  FromVTI) {
220:                        getResultColumnList();
221:                        resultColumnList = targetTable.getResultColumnsForList(
222:                                null, resultColumnList, null);
223:
224:                        /* Set the new result column list in the result set */
225:                        resultSet.setResultColumns(resultColumnList);
226:                    } else {
227:                        /*
228:                         ** Start off assuming no columns from the base table
229:                         ** are needed in the rcl.
230:                         */
231:
232:                        resultColumnList = new ResultColumnList();
233:
234:                        FromBaseTable fbt = getResultColumnList(resultColumnList);
235:
236:                        readColsBitSet = getReadMap(dataDictionary,
237:                                targetTableDescriptor);
238:
239:                        resultColumnList = fbt.addColsToList(resultColumnList,
240:                                readColsBitSet);
241:
242:                        /*
243:                         ** If all bits are set, then behave as if we chose all
244:                         ** in the first place
245:                         */
246:                        int i = 1;
247:                        int size = targetTableDescriptor.getMaxColumnID();
248:                        for (; i <= size; i++) {
249:                            if (!readColsBitSet.get(i)) {
250:                                break;
251:                            }
252:                        }
253:
254:                        if (i > size) {
255:                            readColsBitSet = null;
256:                        }
257:
258:                        /*
259:                         ** Construct an empty heap row for use in our constant action.
260:                         */
261:                        emptyHeapRow = targetTableDescriptor
262:                                .getEmptyExecRow(getContextManager());
263:
264:                        /* Generate the RowLocation column */
265:                        rowLocationNode = (CurrentRowLocationNode) getNodeFactory()
266:                                .getNode(C_NodeTypes.CURRENT_ROW_LOCATION_NODE,
267:                                        getContextManager());
268:                        rowLocationColumn = (ResultColumn) getNodeFactory()
269:                                .getNode(C_NodeTypes.RESULT_COLUMN, COLUMNNAME,
270:                                        rowLocationNode, getContextManager());
271:                        rowLocationColumn.markGenerated();
272:
273:                        /* Append to the ResultColumnList */
274:                        resultColumnList.addResultColumn(rowLocationColumn);
275:
276:                        /* Force the added columns to take on the table's correlation name, if any */
277:                        correlateAddedColumns(resultColumnList, targetTable);
278:
279:                        /* Set the new result column list in the result set */
280:                        resultSet.setResultColumns(resultColumnList);
281:                    }
282:
283:                    /* Bind the expressions before the ResultColumns are bound */
284:                    super .bindExpressions();
285:
286:                    /* Bind untyped nulls directly under the result columns */
287:                    resultSet.getResultColumns()
288:                            .bindUntypedNullsToResultColumns(resultColumnList);
289:
290:                    if (!(targetTable instanceof  FromVTI)) {
291:                        /* Bind the new ResultColumn */
292:                        rowLocationColumn.bindResultColumnToExpression();
293:
294:                        bindConstraints(dataDictionary, getNodeFactory(),
295:                                targetTableDescriptor, null, resultColumnList,
296:                                (int[]) null, readColsBitSet, false, true); /* we alway include triggers in core language */
297:
298:                        /* If the target table is also a source table, then
299:                         * the delete will have to be in deferred mode
300:                         * For deletes, this means that the target table appears in a
301:                         * subquery.  Also, self-referencing foreign key deletes
302:                         * are deferred.  And triggers cause the delete to be deferred.
303:                         */
304:                        if (resultSet.subqueryReferencesTarget(
305:                                targetTableDescriptor.getName(), true)
306:                                || requiresDeferredProcessing()) {
307:                            deferred = true;
308:                        }
309:                    } else {
310:                        deferred = VTIDeferModPolicy.deferIt(
311:                                DeferModification.DELETE_STATEMENT, targetVTI,
312:                                null, sel.getWhereClause());
313:                    }
314:                    sel = null; // done with sel
315:
316:                    /* Verify that all underlying ResultSets reclaimed their FromList */
317:                    if (SanityManager.DEBUG) {
318:                        SanityManager
319:                                .ASSERT(
320:                                        fromList.size() == 0,
321:                                        "fromList.size() is expected to be 0, not "
322:                                                + fromList.size()
323:                                                + " on return from RS.bindExpressions()");
324:                    }
325:
326:                    //In case of cascade delete , create nodes for
327:                    //the ref action  dependent tables and bind them.
328:                    if (fkTableNames != null) {
329:                        String currentTargetTableName = targetTableDescriptor
330:                                .getSchemaName()
331:                                + "." + targetTableDescriptor.getName();
332:
333:                        if (!isDependentTable) {
334:                            //graph node
335:                            graphHashTable = new Hashtable();
336:                        }
337:
338:                        /*Check whether the current tatget is already been explored.
339:                         *If we are seeing the same table name which we binded earlier
340:                         *means we have cyclic references.
341:                         */
342:                        if (!graphHashTable.containsKey(currentTargetTableName)) {
343:                            cascadeDelete = true;
344:                            int noDependents = fkTableNames.length;
345:                            dependentNodes = new QueryTreeNode[noDependents];
346:                            graphHashTable.put(currentTargetTableName,
347:                                    new Integer(noDependents));
348:                            for (int i = 0; i < noDependents; i++) {
349:                                dependentNodes[i] = getDependentTableNode(
350:                                        fkTableNames[i], fkRefActions[i],
351:                                        fkColDescriptors[i]);
352:                                dependentNodes[i].bind();
353:                            }
354:                        }
355:                    } else {
356:                        //case where current dependent table does not have dependent tables
357:                        if (isDependentTable) {
358:                            String currentTargetTableName = targetTableDescriptor
359:                                    .getSchemaName()
360:                                    + "." + targetTableDescriptor.getName();
361:                            graphHashTable.put(currentTargetTableName,
362:                                    new Integer(0));
363:
364:                        }
365:                    }
366:                    if (isPrivilegeCollectionRequired()) {
367:                        getCompilerContext().pushCurrentPrivType(getPrivType());
368:                        getCompilerContext().addRequiredTablePriv(
369:                                targetTableDescriptor);
370:                        getCompilerContext().popCurrentPrivType();
371:                    }
372:                } finally {
373:                    getCompilerContext().popCurrentPrivType();
374:                }
375:                return this ;
376:            } // end of bind
377:
378:            int getPrivType() {
379:                return Authorizer.DELETE_PRIV;
380:            }
381:
382:            /**
383:             * Return true if the node references SESSION schema tables (temporary or permanent)
384:             *
385:             * @return	true if references SESSION schema tables, else false
386:             *
387:             * @exception StandardException		Thrown on error
388:             */
389:            public boolean referencesSessionSchema() throws StandardException {
390:                //If delete table is on a SESSION schema table, then return true. 
391:                return resultSet.referencesSessionSchema();
392:            }
393:
394:            /**
395:             * Compile constants that Execution will use
396:             *
397:             * @exception StandardException		Thrown on failure
398:             */
399:            public ConstantAction makeConstantAction() throws StandardException {
400:
401:                /* Different constant actions for base tables and updatable VTIs */
402:                if (targetTableDescriptor != null) {
403:                    // Base table
404:                    int lockMode = resultSet.updateTargetLockMode();
405:                    long heapConglomId = targetTableDescriptor
406:                            .getHeapConglomerateId();
407:                    TransactionController tc = getLanguageConnectionContext()
408:                            .getTransactionCompile();
409:                    StaticCompiledOpenConglomInfo[] indexSCOCIs = new StaticCompiledOpenConglomInfo[indexConglomerateNumbers.length];
410:
411:                    for (int index = 0; index < indexSCOCIs.length; index++) {
412:                        indexSCOCIs[index] = tc
413:                                .getStaticCompiledConglomInfo(indexConglomerateNumbers[index]);
414:                    }
415:
416:                    /*
417:                     ** Do table locking if the table's lock granularity is
418:                     ** set to table.
419:                     */
420:                    if (targetTableDescriptor.getLockGranularity() == TableDescriptor.TABLE_LOCK_GRANULARITY) {
421:                        lockMode = TransactionController.MODE_TABLE;
422:                    }
423:
424:                    ResultDescription resultDescription = null;
425:                    if (isDependentTable) {
426:                        //triggers need the result description ,
427:                        //dependent tables  don't have a source from generation time
428:                        //to get the result description
429:                        resultDescription = makeResultDescription();
430:                    }
431:
432:                    return getGenericConstantActionFactory()
433:                            .getDeleteConstantAction(
434:                                    heapConglomId,
435:                                    targetTableDescriptor.getTableType(),
436:                                    tc
437:                                            .getStaticCompiledConglomInfo(heapConglomId),
438:                                    indicesToMaintain,
439:                                    indexConglomerateNumbers,
440:                                    indexSCOCIs,
441:                                    emptyHeapRow,
442:                                    deferred,
443:                                    false,
444:                                    targetTableDescriptor.getUUID(),
445:                                    lockMode,
446:                                    null,
447:                                    null,
448:                                    null,
449:                                    0,
450:                                    null,
451:                                    null,
452:                                    resultDescription,
453:                                    getFKInfo(),
454:                                    getTriggerInfo(),
455:                                    (readColsBitSet == null) ? (FormatableBitSet) null
456:                                            : new FormatableBitSet(
457:                                                    readColsBitSet),
458:                                    getReadColMap(targetTableDescriptor
459:                                            .getNumberOfColumns(),
460:                                            readColsBitSet),
461:                                    resultColumnList
462:                                            .getStreamStorableColIds(targetTableDescriptor
463:                                                    .getNumberOfColumns()),
464:                                    (readColsBitSet == null) ? targetTableDescriptor
465:                                            .getNumberOfColumns()
466:                                            : readColsBitSet.getNumBitsSet(),
467:                                    (UUID) null, resultSet.isOneRowResultSet(),
468:                                    dependentConstantActions);
469:                } else {
470:                    /* Return constant action for VTI
471:                     * NOTE: ConstantAction responsible for preserving instantiated
472:                     * VTIs for in-memory queries and for only preserving VTIs
473:                     * that implement Serializable for SPSs.
474:                     */
475:                    return getGenericConstantActionFactory()
476:                            .getUpdatableVTIConstantAction(
477:                                    DeferModification.DELETE_STATEMENT,
478:                                    deferred);
479:                }
480:            }
481:
482:            /**
483:             * Code generation for delete.
484:             * The generated code will contain:
485:             *		o  A static member for the (xxx)ResultSet with the RowLocations
486:             *		o  The static member will be assigned the appropriate ResultSet within
487:             *		   the nested calls to get the ResultSets.  (The appropriate cast to the
488:             *		   (xxx)ResultSet will be generated.)
489:             *		o  The CurrentRowLocation() in SelectNode's select list will generate
490:             *		   a new method for returning the RowLocation as well as a call to
491:             *		   that method which will be stuffed in the call to the 
492:             *		    ProjectRestrictResultSet.
493:             *      o In case of referential actions, this function generate an
494:             *        array of resultsets on its dependent tables.
495:             *
496:             * @param acb	The ActivationClassBuilder for the class being built
497:             * @param mb	The execute() method to be built
498:             *
499:             * @exception StandardException		Thrown on error
500:             */
501:            public void generate(ActivationClassBuilder acb, MethodBuilder mb)
502:                    throws StandardException {
503:
504:                //If the DML is on the temporary table, generate the code to mark temporary table as modified in the current UOW
505:                generateCodeForTemporaryTable(acb, mb);
506:
507:                /* generate the parameters */
508:                if (!isDependentTable)
509:                    generateParameterValueSet(acb);
510:
511:                acb.pushGetResultSetFactoryExpression(mb);
512:                acb.newRowLocationScanResultSetName();
513:                resultSet.generate(acb, mb); // arg 1
514:
515:                String resultSetGetter;
516:                int argCount;
517:                String parentResultSetId;
518:
519:                // Base table
520:                if (targetTableDescriptor != null) {
521:                    /* Create the declaration for the scan ResultSet which generates the
522:                     * RowLocations to be deleted.
523:                     * Note that the field cannot be static because there
524:                     * can be multiple activations of the same activation class,
525:                     * and they can't share this field.  Only exprN fields can
526:                     * be shared (or, more generally, read-only fields).
527:                     * RESOLVE - Need to deal with the type of the field.
528:                     */
529:
530:                    acb.newFieldDeclaration(Modifier.PRIVATE,
531:                            ClassName.CursorResultSet, acb
532:                                    .getRowLocationScanResultSetName());
533:
534:                    if (cascadeDelete || isDependentTable) {
535:                        resultSetGetter = "getDeleteCascadeResultSet";
536:                        argCount = 4;
537:                    } else {
538:                        resultSetGetter = "getDeleteResultSet";
539:                        argCount = 1;
540:                    }
541:
542:                } else {
543:                    argCount = 1;
544:                    resultSetGetter = "getDeleteVTIResultSet";
545:                }
546:
547:                if (isDependentTable) {
548:                    mb.push(acb.addItem(makeConstantAction()));
549:
550:                } else {
551:                    if (cascadeDelete) {
552:                        mb.push(-1); //root table.
553:                    }
554:                }
555:
556:                String resultSetArrayType = ClassName.ResultSet + "[]";
557:                if (cascadeDelete) {
558:                    parentResultSetId = targetTableDescriptor.getSchemaName()
559:                            + "." + targetTableDescriptor.getName();
560:                    // Generate the code to build the array
561:                    LocalField arrayField = acb.newFieldDeclaration(
562:                            Modifier.PRIVATE, resultSetArrayType);
563:                    mb.pushNewArray(ClassName.ResultSet, dependentNodes.length); // new ResultSet[size]
564:                    mb.setField(arrayField);
565:                    for (int index = 0; index < dependentNodes.length; index++) {
566:
567:                        dependentNodes[index].setRefActionInfo(
568:                                fkIndexConglomNumbers[index],
569:                                fkColArrays[index], parentResultSetId, true);
570:                        mb.getField(arrayField); // first arg (resultset array reference)
571:                        /*beetle:5360 : if too many statements are added  to a  method, 
572:                         *size of method can hit  65k limit, which will
573:                         *lead to the class format errors at load time.
574:                         *To avoid this problem, when number of statements added 
575:                         *to a method is > 2048, remaing statements are added to  a new function
576:                         *and called from the function which created the function.
577:                         *See Beetle 5135 or 4293 for further details on this type of problem.
578:                         */
579:                        if (mb.statementNumHitLimit(10)) {
580:                            MethodBuilder dmb = acb.newGeneratedFun(
581:                                    ClassName.ResultSet, Modifier.PRIVATE);
582:                            dependentNodes[index].generate(acb, dmb); //generates the resultset expression
583:                            dmb.methodReturn();
584:                            dmb.complete();
585:                            /* Generate the call to the new method */
586:                            mb.pushThis();
587:                            //second arg will be generated by this call
588:                            mb.callMethod(VMOpcode.INVOKEVIRTUAL,
589:                                    (String) null, dmb.getName(),
590:                                    ClassName.ResultSet, 0);
591:                        } else {
592:                            dependentNodes[index].generate(acb, mb); //generates the resultset expression
593:                        }
594:
595:                        mb.setArrayElement(index);
596:                    }
597:                    mb.getField(arrayField); // fourth argument - array reference
598:                } else {
599:                    if (isDependentTable) {
600:                        mb.pushNull(resultSetArrayType); //No dependent tables for this table
601:                    }
602:                }
603:
604:                if (cascadeDelete || isDependentTable) {
605:                    parentResultSetId = targetTableDescriptor.getSchemaName()
606:                            + "." + targetTableDescriptor.getName();
607:                    mb.push(parentResultSetId);
608:
609:                }
610:                mb.callMethod(VMOpcode.INVOKEINTERFACE, (String) null,
611:                        resultSetGetter, ClassName.ResultSet, argCount);
612:
613:                if (!isDependentTable && cascadeDelete) {
614:                    int numResultSets = acb.getRowCount();
615:                    if (numResultSets > 0) {
616:                        //generate activation.raParentResultSets = new NoPutResultSet[size]
617:                        MethodBuilder constructor = acb.getConstructor();
618:                        constructor.pushThis();
619:                        constructor.pushNewArray(ClassName.CursorResultSet,
620:                                numResultSets);
621:                        constructor.putField(ClassName.BaseActivation,
622:                                "raParentResultSets", ClassName.CursorResultSet
623:                                        + "[]");
624:                        constructor.endStatement();
625:                    }
626:                }
627:            }
628:
629:            /**
630:             * Return the type of statement, something from
631:             * StatementType.
632:             *
633:             * @return the type of statement
634:             */
635:            protected final int getStatementType() {
636:                return StatementType.DELETE;
637:            }
638:
639:            /**
640:             *	Gets the map of all columns which must be read out of the base table.
641:             * These are the columns needed to:
642:             *
643:             *		o	maintain indices
644:             *		o	maintain foreign keys
645:             *
646:             *	The returned map is a FormatableBitSet with 1 bit for each column in the
647:             * table plus an extra, unsued 0-bit. If a 1-based column id must
648:             * be read from the base table, then the corresponding 1-based bit
649:             * is turned ON in the returned FormatableBitSet.
650:             *
651:             *	@param	dd				the data dictionary to look in
652:             *	@param	baseTable		the base table descriptor
653:             *
654:             *	@return	a FormatableBitSet of columns to be read out of the base table
655:             *
656:             * @exception StandardException		Thrown on error
657:             */
658:            public FormatableBitSet getReadMap(DataDictionary dd,
659:                    TableDescriptor baseTable) throws StandardException {
660:                boolean[] needsDeferredProcessing = new boolean[1];
661:                needsDeferredProcessing[0] = requiresDeferredProcessing();
662:
663:                Vector conglomVector = new Vector();
664:                relevantTriggers = new GenericDescriptorList();
665:
666:                FormatableBitSet columnMap = DeleteNode.getDeleteReadMap(
667:                        baseTable, conglomVector, relevantTriggers,
668:                        needsDeferredProcessing);
669:
670:                markAffectedIndexes(conglomVector);
671:
672:                adjustDeferredFlag(needsDeferredProcessing[0]);
673:
674:                return columnMap;
675:            }
676:
677:            /**
678:             * In case of referential actions, we require to perform
679:             * DML (UPDATE or DELETE) on the dependent tables. 
680:             * Following function returns the DML Node for the dependent table.
681:             */
682:            private QueryTreeNode getDependentTableNode(String tableName,
683:                    int refAction, ColumnDescriptorList cdl)
684:                    throws StandardException {
685:                QueryTreeNode node = null;
686:
687:                int index = tableName.indexOf('.');
688:                String schemaName = tableName.substring(0, index);
689:                String tName = tableName.substring(index + 1);
690:                if (refAction == StatementType.RA_CASCADE) {
691:                    node = getEmptyDeleteNode(schemaName, tName);
692:                    ((DeleteNode) node).isDependentTable = true;
693:                    ((DeleteNode) node).graphHashTable = graphHashTable;
694:                }
695:
696:                if (refAction == StatementType.RA_SETNULL) {
697:                    node = getEmptyUpdateNode(schemaName, tName, cdl);
698:                    ((UpdateNode) node).isDependentTable = true;
699:                    ((UpdateNode) node).graphHashTable = graphHashTable;
700:                }
701:
702:                return node;
703:            }
704:
705:            private QueryTreeNode getEmptyDeleteNode(String schemaName,
706:                    String targetTableName) throws StandardException {
707:
708:                ValueNode whereClause = null;
709:                TableName tableName = null;
710:                FromTable fromTable = null;
711:                QueryTreeNode retval;
712:                SelectNode resultSet;
713:
714:                tableName = new TableName();
715:                tableName.init(schemaName, targetTableName);
716:
717:                NodeFactory nodeFactory = getNodeFactory();
718:                FromList fromList = (FromList) nodeFactory.getNode(
719:                        C_NodeTypes.FROM_LIST, getContextManager());
720:                fromTable = (FromTable) nodeFactory.getNode(
721:                        C_NodeTypes.FROM_BASE_TABLE, tableName, null,
722:                        ReuseFactory.getInteger(FromBaseTable.DELETE), null,
723:                        getContextManager());
724:
725:                //we would like to use references index & table scan instead of 
726:                //what optimizer says for the dependent table scan.
727:                Properties targetProperties = new FormatableProperties();
728:                targetProperties.put("index", "null");
729:                ((FromBaseTable) fromTable)
730:                        .setTableProperties(targetProperties);
731:
732:                fromList.addFromTable(fromTable);
733:                resultSet = (SelectNode) nodeFactory.getNode(
734:                        C_NodeTypes.SELECT_NODE, null, null, /* AGGREGATE list */
735:                        fromList, /* FROM list */
736:                        whereClause, /* WHERE clause */
737:                        null, /* GROUP BY list */
738:                        getContextManager());
739:
740:                retval = (QueryTreeNode) nodeFactory.getNode(
741:                        C_NodeTypes.DELETE_NODE, tableName, resultSet,
742:                        getContextManager());
743:
744:                return retval;
745:            }
746:
747:            private QueryTreeNode getEmptyUpdateNode(String schemaName,
748:                    String targetTableName, ColumnDescriptorList cdl)
749:                    throws StandardException {
750:
751:                ValueNode whereClause = null;
752:                TableName tableName = null;
753:                FromTable fromTable = null;
754:                QueryTreeNode retval;
755:                SelectNode resultSet;
756:
757:                tableName = new TableName();
758:                tableName.init(schemaName, targetTableName);
759:
760:                NodeFactory nodeFactory = getNodeFactory();
761:                FromList fromList = (FromList) nodeFactory.getNode(
762:                        C_NodeTypes.FROM_LIST, getContextManager());
763:                fromTable = (FromTable) nodeFactory.getNode(
764:                        C_NodeTypes.FROM_BASE_TABLE, tableName, null,
765:                        ReuseFactory.getInteger(FromBaseTable.DELETE), null,
766:                        getContextManager());
767:
768:                //we would like to use references index & table scan instead of 
769:                //what optimizer says for the dependent table scan.
770:                Properties targetProperties = new FormatableProperties();
771:                targetProperties.put("index", "null");
772:                ((FromBaseTable) fromTable)
773:                        .setTableProperties(targetProperties);
774:
775:                fromList.addFromTable(fromTable);
776:
777:                resultSet = (SelectNode) nodeFactory.getNode(
778:                        C_NodeTypes.SELECT_NODE, getSetClause(tableName, cdl),
779:                        null, /* AGGREGATE list */
780:                        fromList, /* FROM list */
781:                        whereClause, /* WHERE clause */
782:                        null, /* GROUP BY list */
783:                        getContextManager());
784:
785:                retval = (QueryTreeNode) nodeFactory.getNode(
786:                        C_NodeTypes.UPDATE_NODE, tableName, resultSet,
787:                        getContextManager());
788:
789:                return retval;
790:            }
791:
792:            private ResultColumnList getSetClause(TableName tabName,
793:                    ColumnDescriptorList cdl) throws StandardException {
794:                ResultColumn resultColumn;
795:                ValueNode valueNode;
796:
797:                NodeFactory nodeFactory = getNodeFactory();
798:                ResultColumnList columnList = (ResultColumnList) nodeFactory
799:                        .getNode(C_NodeTypes.RESULT_COLUMN_LIST,
800:                                getContextManager());
801:
802:                valueNode = (ValueNode) nodeFactory.getNode(
803:                        C_NodeTypes.UNTYPED_NULL_CONSTANT_NODE,
804:                        getContextManager());
805:                for (int index = 0; index < cdl.size(); index++) {
806:                    ColumnDescriptor cd = (ColumnDescriptor) cdl
807:                            .elementAt(index);
808:                    //only columns that are nullable need to be set to 'null' for ON
809:                    //DELETE SET NULL
810:                    if ((cd.getType()).isNullable()) {
811:                        resultColumn = (ResultColumn) nodeFactory.getNode(
812:                                C_NodeTypes.RESULT_COLUMN, cd, valueNode,
813:                                getContextManager());
814:
815:                        columnList.addResultColumn(resultColumn);
816:                    }
817:                }
818:                return columnList;
819:            }
820:
821:            public QueryTreeNode optimize() throws StandardException {
822:                if (cascadeDelete) {
823:                    for (int index = 0; index < dependentNodes.length; index++) {
824:                        dependentNodes[index] = dependentNodes[index]
825:                                .optimize();
826:                    }
827:                }
828:
829:                return super .optimize();
830:            }
831:
832:            /**
833:             *	Builds a bitmap of all columns which should be read from the
834:             *	Store in order to satisfy an DELETE statement.
835:             *
836:             *
837:             *	1)	finds all indices on this table
838:             *	2)	adds the index columns to a bitmap of affected columns
839:             *	3)	adds the index descriptors to a list of conglomerate
840:             *		descriptors.
841:             *	4)	finds all DELETE triggers on the table
842:             *	5)	if there are any DELETE triggers, marks all columns in the bitmap
843:             *	6)	adds the triggers to an evolving list of triggers
844:             *
845:             *	@param	conglomVector		OUT: vector of affected indices
846:             *	@param	relevantTriggers	IN/OUT. Passed in as an empty list. Filled in as we go.
847:             *	@param	needsDeferredProcessing			IN/OUT. true if the statement already needs
848:             *											deferred processing. set while evaluating this
849:             *											routine if a trigger requires
850:             *											deferred processing
851:             *
852:             * @return a FormatableBitSet of columns to be read out of the base table
853:             *
854:             * @exception StandardException		Thrown on error
855:             */
856:            private static FormatableBitSet getDeleteReadMap(
857:                    TableDescriptor baseTable, Vector conglomVector,
858:                    GenericDescriptorList relevantTriggers,
859:                    boolean[] needsDeferredProcessing) throws StandardException {
860:                int columnCount = baseTable.getMaxColumnID();
861:                FormatableBitSet columnMap = new FormatableBitSet(
862:                        columnCount + 1);
863:
864:                /* 
865:                 ** Get a list of the indexes that need to be 
866:                 ** updated.  ColumnMap contains all indexed
867:                 ** columns where 1 or more columns in the index
868:                 ** are going to be modified.
869:                 **
870:                 ** Notice that we don't need to add constraint
871:                 ** columns.  This is because we add all key constraints
872:                 ** (e.g. foreign keys) as a side effect of adding their
873:                 ** indexes above.  And we don't need to deal with
874:                 ** check constraints on a delete.
875:                 **
876:                 ** Adding indexes also takes care of the replication 
877:                 ** requirement of having the primary key.
878:                 */
879:                DMLModStatementNode.getXAffectedIndexes(baseTable, null,
880:                        columnMap, conglomVector);
881:
882:                /*
883:                 ** If we have any triggers, then get all the columns
884:                 ** because we don't know what the user will ultimately
885:                 ** reference.
886:                 */
887:                baseTable.getAllRelevantTriggers(StatementType.DELETE,
888:                        (int[]) null, relevantTriggers);
889:                if (relevantTriggers.size() > 0) {
890:                    needsDeferredProcessing[0] = true;
891:                }
892:
893:                if (relevantTriggers.size() > 0) {
894:                    for (int i = 1; i <= columnCount; i++) {
895:                        columnMap.set(i);
896:                    }
897:                }
898:
899:                return columnMap;
900:            }
901:
902:            /*
903:             * Force column references (particularly those added by the compiler)
904:             * to use the correlation name on the base table, if any.
905:             */
906:            private void correlateAddedColumns(ResultColumnList rcl,
907:                    FromTable fromTable) throws StandardException {
908:                String correlationName = fromTable.getCorrelationName();
909:
910:                if (correlationName == null) {
911:                    return;
912:                }
913:
914:                TableName correlationNameNode = makeTableName(null,
915:                        correlationName);
916:                int count = rcl.size();
917:
918:                for (int i = 0; i < count; i++) {
919:                    ResultColumn column = (ResultColumn) rcl.elementAt(i);
920:
921:                    ValueNode expression = column.getExpression();
922:
923:                    if ((expression != null)
924:                            && (expression instanceof  ColumnReference)) {
925:                        ColumnReference reference = (ColumnReference) expression;
926:
927:                        reference.setTableNameNode(correlationNameNode);
928:                    }
929:                }
930:
931:            }
932:
933:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.