Source Code Cross Referenced for InsertNode.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.InsertNode
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.services.loader.GeneratedMethod;
027:
028:        import org.apache.derby.iapi.services.compiler.JavaFactory;
029:        import org.apache.derby.iapi.services.compiler.MethodBuilder;
030:
031:        import org.apache.derby.iapi.reference.SQLState;
032:        import org.apache.derby.iapi.error.StandardException;
033:
034:        import org.apache.derby.iapi.sql.compile.C_NodeTypes;
035:
036:        import org.apache.derby.iapi.sql.conn.Authorizer;
037:
038:        import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
039:        import org.apache.derby.iapi.sql.compile.Visitable;
040:        import org.apache.derby.iapi.sql.compile.Visitor;
041:        import org.apache.derby.iapi.sql.compile.CompilerContext;
042:
043:        import org.apache.derby.iapi.reference.ClassName;
044:
045:        import org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptor;
046:        import org.apache.derby.iapi.sql.dictionary.ConstraintDescriptor;
047:        import org.apache.derby.iapi.sql.dictionary.DataDictionary;
048:        import org.apache.derby.iapi.sql.dictionary.TableDescriptor;
049:        import org.apache.derby.iapi.sql.dictionary.IndexLister;
050:        import org.apache.derby.iapi.sql.dictionary.IndexRowGenerator;
051:        import org.apache.derby.iapi.types.TypeId;
052:
053:        import org.apache.derby.iapi.sql.ResultSet;
054:        import org.apache.derby.iapi.sql.Activation;
055:        import org.apache.derby.iapi.sql.StatementType;
056:
057:        import org.apache.derby.iapi.sql.execute.ConstantAction;
058:
059:        import org.apache.derby.iapi.store.access.StaticCompiledOpenConglomInfo;
060:        import org.apache.derby.iapi.store.access.TransactionController;
061:        import org.apache.derby.iapi.types.RowLocation;
062:
063:        import org.apache.derby.impl.sql.compile.ActivationClassBuilder;
064:        import org.apache.derby.iapi.services.compiler.MethodBuilder;
065:
066:        import org.apache.derby.iapi.services.sanity.SanityManager;
067:
068:        import org.apache.derby.vti.DeferModification;
069:
070:        import org.apache.derby.iapi.services.classfile.VMOpcode;
071:        import org.apache.derby.iapi.util.StringUtil;
072:
073:        import org.apache.derby.catalog.UUID;
074:
075:        import org.apache.derby.impl.sql.execute.FKInfo;
076:
077:        import java.util.Properties;
078:
079:        import org.apache.derby.iapi.services.io.FormatableBitSet;
080:        import org.apache.derby.iapi.util.ReuseFactory;
081:
082:        /**
083:         * An InsertNode is the top node in a query tree for an
084:         * insert statement.
085:         * <p>
086:         * After parsing, the node contains
087:         *   targetTableName: the target table for the insert
088:         *   collist: a list of column names, if specified
089:         *   queryexpr: the expression being inserted, either
090:         *				a values clause or a select form; both
091:         *			    of these are represented via the SelectNode,
092:         *				potentially with a TableOperatorNode such as
093:         *				UnionNode above it.
094:         * <p>
095:         * After binding, the node has had the target table's
096:         * descriptor located and inserted, and the queryexpr
097:         * and collist have been massaged so that they are identical
098:         * to the table layout.  This involves adding any default
099:         * values for missing columns, and reordering the columns
100:         * to match the table's ordering of them.
101:         * <p>
102:         * After optimizing, ...
103:         */
104:        public final class InsertNode extends DMLModStatementNode {
105:            public ResultColumnList targetColumnList;
106:            public boolean deferred;
107:            public ValueNode checkConstraints;
108:            public Properties targetProperties;
109:            public FKInfo fkInfo;
110:            protected boolean bulkInsert;
111:            private boolean bulkInsertReplace;
112:
113:            protected RowLocation[] autoincRowLocation;
114:
115:            /**
116:             * Initializer for an InsertNode.
117:             *
118:             * @param targetName	The name of the table/VTI to insert into
119:             * @param insertColumns	A ResultColumnList with the names of the
120:             *			columns to insert into.  May be null if the
121:             *			user did not specify the columns - in this
122:             *			case, the binding phase will have to figure
123:             *			it out.
124:             * @param queryExpression	The query expression that will generate
125:             *				the rows to insert into the given table
126:             * @param targetProperties	The properties specified on the target table
127:             */
128:
129:            public void init(Object targetName, Object insertColumns,
130:                    Object queryExpression, Object targetProperties) {
131:                /* statementType gets set in super() before we've validated
132:                 * any properties, so we've kludged the code to get the
133:                 * right statementType for a bulk insert replace.
134:                 */
135:                super 
136:                        .init(
137:                                queryExpression,
138:                                ReuseFactory
139:                                        .getInteger(getStatementType((Properties) targetProperties)));
140:                setTarget((QueryTreeNode) targetName);
141:                targetColumnList = (ResultColumnList) insertColumns;
142:                this .targetProperties = (Properties) targetProperties;
143:
144:                /* Remember that the query expression is the source to an INSERT */
145:                getResultSetNode().setInsertSource();
146:            }
147:
148:            /**
149:             * Convert this object to a String.  See comments in QueryTreeNode.java
150:             * for how this should be done for tree printing.
151:             *
152:             * @return	This object as a String
153:             */
154:
155:            public String toString() {
156:                if (SanityManager.DEBUG) {
157:                    try {
158:                        return ((targetTableName != null) ? targetTableName
159:                                : targetVTI.getTableName()).toString()
160:                                + "\n"
161:                                + targetProperties
162:                                + "\n"
163:                                + super .toString();
164:                    } catch (org.apache.derby.iapi.error.StandardException e) {
165:                        return "tableName: <not_known>\n" + targetProperties
166:                                + "\n" + super .toString();
167:                    }
168:                } else {
169:                    return "";
170:                }
171:            }
172:
173:            public String statementToString() {
174:                return "INSERT";
175:            }
176:
177:            /**
178:             * Prints the sub-nodes of this object.  See QueryTreeNode.java for
179:             * how tree printing is supposed to work.
180:             *
181:             * @param depth		The depth of this node in the tree
182:             */
183:
184:            public void printSubNodes(int depth) {
185:                if (SanityManager.DEBUG) {
186:                    super .printSubNodes(depth);
187:
188:                    if (targetTableName != null) {
189:                        printLabel(depth, "targetTableName: ");
190:                        targetTableName.treePrint(depth + 1);
191:                    }
192:
193:                    if (targetColumnList != null) {
194:                        printLabel(depth, "targetColumnList: ");
195:                        targetColumnList.treePrint(depth + 1);
196:                    }
197:
198:                    /* RESOLVE - need to print out targetTableDescriptor */
199:                }
200:            }
201:
202:            /**
203:             * Bind this InsertNode.  This means looking up tables and columns and
204:             * getting their types, and figuring out the result types of all
205:             * expressions, as well as doing view resolution, permissions checking,
206:             * etc.
207:             * <p>
208:             * Binding an insert will also massage the tree so that
209:             * the collist and select column order/number are the
210:             * same as the layout of the table in the store. 
211:             *
212:             * @return	The bound query tree
213:             *
214:             * @exception StandardException		Thrown on error
215:             */
216:
217:            public QueryTreeNode bind() throws StandardException {
218:                // We just need select privilege on the expressions
219:                getCompilerContext()
220:                        .pushCurrentPrivType(Authorizer.SELECT_PRIV);
221:
222:                FromList fromList = (FromList) getNodeFactory().getNode(
223:                        C_NodeTypes.FROM_LIST,
224:                        getNodeFactory().doJoinOrderOptimization(),
225:                        getContextManager());
226:
227:                /* If any underlying ResultSetNode is a SelectNode, then we
228:                 * need to do a full bind(), including the expressions
229:                 * (since the fromList may include a FromSubquery).
230:                 */
231:                DataDictionary dataDictionary = getDataDictionary();
232:                super .bindResultSetsWithTables(dataDictionary);
233:
234:                /*
235:                 ** Get the TableDescriptor for the table we are inserting into
236:                 */
237:                verifyTargetTable();
238:
239:                // Check the validity of the targetProperties, if they exist
240:                if (targetProperties != null) {
241:                    verifyTargetProperties(dataDictionary);
242:                }
243:
244:                /*
245:                 ** Get the resultColumnList representing the columns in the base
246:                 ** table or VTI.
247:                 */
248:                getResultColumnList();
249:
250:                /* If we have a target column list, then it must have the same # of
251:                 * entries as the result set's RCL.
252:                 */
253:                if (targetColumnList != null) {
254:                    /*
255:                     * Normalize synonym qualifers for column references.
256:                     */
257:                    if (synonymTableName != null) {
258:                        normalizeSynonymColumns(targetColumnList,
259:                                targetTableName);
260:                    }
261:
262:                    /* Bind the target column list */
263:                    getCompilerContext().pushCurrentPrivType(getPrivType());
264:                    if (targetTableDescriptor != null) {
265:                        targetColumnList.bindResultColumnsByName(
266:                                targetTableDescriptor, (DMLStatementNode) this );
267:                    } else {
268:                        targetColumnList.bindResultColumnsByName(targetVTI
269:                                .getResultColumns(), targetVTI, this );
270:                    }
271:                    getCompilerContext().popCurrentPrivType();
272:                }
273:
274:                /* Verify that all underlying ResultSets reclaimed their FromList */
275:                if (SanityManager.DEBUG) {
276:                    SanityManager.ASSERT(fromList.size() == 0,
277:                            "fromList.size() is expected to be 0, not "
278:                                    + fromList.size()
279:                                    + " on return from RS.bindExpressions()");
280:                }
281:
282:                /* Replace any DEFAULTs with the associated tree */
283:                resultSet.replaceDefaults(targetTableDescriptor,
284:                        targetColumnList);
285:
286:                /* Bind the expressions now that the result columns are bound 
287:                 * NOTE: This will be the 2nd time for those underlying ResultSets
288:                 * that have tables (no harm done), but it is necessary for those
289:                 * that do not have tables.  It's too hard/not work the effort to
290:                 * avoid the redundancy.
291:                 */
292:                super .bindExpressions();
293:
294:                /*
295:                 ** If the result set is a union, it could be a table constructor.
296:                 ** Bind any nulls in the result columns of the table constructor
297:                 ** to the types of the table being inserted into.
298:                 **
299:                 ** The types of ? parameters in row constructors and table constructors
300:                 ** in an INSERT statement come from the result columns.
301:                 **
302:                 ** If there is a target column list, use that instead of the result
303:                 ** columns for the whole table, since the columns in the result set
304:                 ** correspond to the target column list.
305:                 */
306:                if (targetColumnList != null) {
307:                    if (resultSet.getResultColumns().size() > targetColumnList
308:                            .size())
309:                        throw StandardException
310:                                .newException(SQLState.LANG_DB2_INVALID_COLS_SPECIFIED);
311:                    resultSet.bindUntypedNullsToResultColumns(targetColumnList);
312:                    resultSet.setTableConstructorTypes(targetColumnList);
313:                } else {
314:                    if (resultSet.getResultColumns().size() > resultColumnList
315:                            .size())
316:                        throw StandardException
317:                                .newException(SQLState.LANG_DB2_INVALID_COLS_SPECIFIED);
318:                    resultSet.bindUntypedNullsToResultColumns(resultColumnList);
319:                    resultSet.setTableConstructorTypes(resultColumnList);
320:                }
321:
322:                /* Bind the columns of the result set to their expressions */
323:                resultSet.bindResultColumns(fromList);
324:
325:                int resCols = resultSet.getResultColumns().size();
326:                DataDictionary dd = getDataDictionary();
327:                if (targetColumnList != null) {
328:                    if (targetColumnList.size() != resCols)
329:                        throw StandardException
330:                                .newException(SQLState.LANG_DB2_INVALID_COLS_SPECIFIED);
331:                } else {
332:                    if (targetTableDescriptor != null
333:                            && targetTableDescriptor.getNumberOfColumns() != resCols)
334:                        throw StandardException
335:                                .newException(SQLState.LANG_DB2_INVALID_COLS_SPECIFIED);
336:                }
337:
338:                /* See if the ResultSet's RCL needs to be ordered to match the target
339:                 * list, or "enhanced" to accommodate defaults.  It can only need to
340:                 * be ordered if there is a target column list.  It needs to be
341:                 * enhanced if there are fewer source columns than there are columns
342:                 * in the table.
343:                 */
344:                boolean inOrder = true;
345:                int numTableColumns = resultColumnList.size();
346:
347:                /* colMap[] will be the size of the target list, which could be larger
348:                 * than the current size of the source list.  In that case, the source
349:                 * list will be "enhanced" to include defaults.
350:                 */
351:                int[] colMap = new int[numTableColumns];
352:
353:                // set the fields to an unused value
354:                for (int i = 0; i < colMap.length; i++) {
355:                    colMap[i] = -1;
356:                }
357:
358:                /* Create the source/target list mapping */
359:                if (targetColumnList != null) {
360:                    /*
361:                     ** There is a target column list, so the result columns might
362:                     ** need to be ordered.  Step through the target column list
363:                     ** and remember the position in the target table of each column.
364:                     ** Remember if any of the columns are out of order.
365:                     */
366:                    int targetSize = targetColumnList.size();
367:                    for (int index = 0; index < targetSize; index++) {
368:                        int position = ((ResultColumn) (targetColumnList
369:                                .elementAt(index))).columnDescriptor
370:                                .getPosition();
371:
372:                        if (index != position - 1) {
373:                            inOrder = false;
374:                        }
375:
376:                        // position is 1-base; colMap indexes and entries are 0-based.
377:                        colMap[position - 1] = index;
378:                    }
379:                } else {
380:                    /*
381:                     ** There is no target column list, so the result columns in the
382:                     ** source are presumed to be in the same order as the target
383:                     ** table.
384:                     */
385:                    for (int position = 0; position < resultSet
386:                            .getResultColumns().size(); position++) {
387:                        colMap[position] = position;
388:                    }
389:                }
390:
391:                // colmap[x] == y means that column x in the target table
392:                // maps to column y in the source result set.
393:                // colmap[x] == -1 means that column x in the target table
394:                // maps to its default value.
395:                // both colmap indexes and values are 0-based.
396:
397:                /* if the list is in order and complete, we don't have to change
398:                 * the tree. If it is not, then we call RSN.enhanceRCLForInsert() 
399:                 * which will either
400:                 * (reorder and/or "enhance" the source RCL within the same RSN) or
401:                 * (generate and return a PRN with a new reordered/enhanced RCL above
402:                 * the existing RSN).  This way, RSN's that understand how to do projections
403:                 * can avoid the additional PRN while those that do not will get one.
404:                 */
405:                /* NOTE - javascope gives confusing branch coverage info here.  By
406:                 * breaking apart the following if condition, I have verified that
407:                 * we test all cases.  (Jerry 7/17/97)
408:                 */
409:                if (!inOrder
410:                        || resultSet.resultColumns.size() < numTableColumns) {
411:                    // one thing we do know is that all of the resultsets underneath
412:                    // us have their resultColumn names filled in with the names of
413:                    // the target table columns.  That makes generating the mapping
414:                    // "easier" -- we simply generate the names of the target table columns
415:                    // that are included.  For the missing columns, we generate default
416:                    // value expressions.
417:
418:                    resultSet = resultSet.enhanceRCLForInsert(numTableColumns,
419:                            colMap, dataDictionary, targetTableDescriptor,
420:                            targetVTI);
421:                }
422:
423:                if (resultSet instanceof  UnionNode) {
424:                    // If we are inserting a number of rows in VALUES clause, we need to
425:                    // examine each row for 'autoincrement'.
426:                    resultColumnList.checkAutoincrementUnion(resultSet);
427:                } else
428:                    resultColumnList.checkAutoincrement(resultSet
429:                            .getResultColumns());
430:                resultColumnList.checkStorableExpressions(resultSet
431:                        .getResultColumns());
432:                /* Insert a NormalizeResultSetNode above the source if the source
433:                 * and target column types and lengths do not match.
434:                 */
435:                if (!resultColumnList.columnTypesAndLengthsMatch(resultSet
436:                        .getResultColumns())) {
437:                    resultSet = resultSet.genNormalizeResultSetNode(resultSet,
438:                            false);
439:                    resultColumnList.copyTypesAndLengthsToSource(resultSet
440:                            .getResultColumns());
441:                }
442:
443:                if (targetTableDescriptor != null) {
444:                    /* Get and bind all constraints on the table */
445:                    ResultColumnList sourceRCL = resultSet.getResultColumns();
446:                    sourceRCL.copyResultColumnNames(resultColumnList);
447:                    checkConstraints = bindConstraints(dataDictionary,
448:                            getNodeFactory(), targetTableDescriptor, null,
449:                            sourceRCL, (int[]) null, (FormatableBitSet) null,
450:                            false, true); /* we always include
451:                     * triggers in core language */
452:
453:                    /* Do we need to do a deferred mode insert */
454:                    /* 
455:                     ** Deferred if:
456:                     **	If the target table is also a source table
457:                     **	Self-referencing foreign key constraint 
458:                     **	trigger
459:                     */
460:                    if (resultSet.referencesTarget(targetTableDescriptor
461:                            .getName(), true)
462:                            || requiresDeferredProcessing()) {
463:                        deferred = true;
464:
465:                        /* Disallow bulk insert replace when target table
466:                         * is also a source table.
467:                         */
468:                        if (bulkInsertReplace
469:                                && resultSet.referencesTarget(
470:                                        targetTableDescriptor.getName(), true)) {
471:                            throw StandardException.newException(
472:                                    SQLState.LANG_INVALID_BULK_INSERT_REPLACE,
473:                                    targetTableDescriptor.getQualifiedName());
474:                        }
475:                    }
476:
477:                    /* Get the list of indexes on the table being inserted into */
478:                    getAffectedIndexes(targetTableDescriptor);
479:                    TransactionController tc = getLanguageConnectionContext()
480:                            .getTransactionCompile();
481:
482:                    autoincRowLocation = dd.computeAutoincRowLocations(tc,
483:                            targetTableDescriptor);
484:
485:                    if (isPrivilegeCollectionRequired()) {
486:                        getCompilerContext().pushCurrentPrivType(getPrivType());
487:                        getCompilerContext().addRequiredTablePriv(
488:                                targetTableDescriptor);
489:                        getCompilerContext().popCurrentPrivType();
490:                    }
491:
492:                } else {
493:                    deferred = VTIDeferModPolicy.deferIt(
494:                            DeferModification.INSERT_STATEMENT, targetVTI,
495:                            null, resultSet);
496:                }
497:
498:                getCompilerContext().popCurrentPrivType();
499:                return this ;
500:            }
501:
502:            int getPrivType() {
503:                return Authorizer.INSERT_PRIV;
504:            }
505:
506:            /**
507:             * Return true if the node references SESSION schema tables (temporary or permanent)
508:             *
509:             * @return	true if references SESSION schema tables, else false
510:             *
511:             * @exception StandardException		Thrown on error
512:             */
513:            public boolean referencesSessionSchema() throws StandardException {
514:                boolean returnValue = false;
515:
516:                //If this node references a SESSION schema table, then return true. 
517:                if (targetTableDescriptor != null)
518:                    returnValue = isSessionSchema(targetTableDescriptor
519:                            .getSchemaDescriptor());
520:
521:                if (returnValue == false)
522:                    returnValue = resultSet.referencesSessionSchema();
523:
524:                return returnValue;
525:            }
526:
527:            /**
528:             * Verify that the target properties that we are interested in
529:             * all hold valid values.
530:             * NOTE: Any target property which is valid but cannot be supported
531:             * due to a target database, etc. will be turned off quietly.
532:             *
533:             * @param dd	The DataDictionary
534:             *
535:             * @exception StandardException		Thrown on error
536:             */
537:            private void verifyTargetProperties(DataDictionary dd)
538:                    throws StandardException {
539:                // The only property that we're currently interested in is insertMode
540:                String insertMode = targetProperties.getProperty("insertMode");
541:                if (insertMode != null) {
542:                    String upperValue = StringUtil.SQLToUpperCase(insertMode);
543:                    if (!upperValue.equals("BULKINSERT")
544:                            && !upperValue.equals("REPLACE")) {
545:                        throw StandardException.newException(
546:                                SQLState.LANG_INVALID_INSERT_MODE, insertMode,
547:                                targetTableName);
548:                    } else {
549:                        /* Turn off bulkInsert if it is on and we can't support it. */
550:                        if (!verifyBulkInsert(dd, upperValue)) {
551:                            targetProperties.remove("insertMode");
552:                        } else {
553:                            /* Now we know we're doing bulk insert */
554:                            bulkInsert = true;
555:
556:                            if (upperValue.equals("REPLACE")) {
557:                                bulkInsertReplace = true;
558:                            }
559:
560:                            // Validate the bulkFetch property if specified
561:                            String bulkFetchStr = targetProperties
562:                                    .getProperty("bulkFetch");
563:                            if (bulkFetchStr != null) {
564:                                int bulkFetch = getIntProperty(bulkFetchStr,
565:                                        "bulkFetch");
566:
567:                                // verify that the specified value is valid
568:                                if (bulkFetch <= 0) {
569:                                    throw StandardException
570:                                            .newException(
571:                                                    SQLState.LANG_INVALID_BULK_FETCH_VALUE,
572:                                                    String.valueOf(bulkFetch));
573:                                }
574:                            }
575:                        }
576:                    }
577:                }
578:            }
579:
580:            /**
581:             * Do the bind time checks to see if bulkInsert is allowed on
582:             * this table.  bulkInsert is disallowed at bind time for:
583:             *		o  target databases
584:             *		o  (tables with triggers?)
585:             * (It is disallowed at execution time if the table has at
586:             * least 1 row in it or if it is a deferred mode insert.)
587:             *
588:             * @param dd	The DataDictionary
589:             * @param mode	The insert mode
590:             *
591:             * @return Whether or not bulkInsert is allowed.
592:             *
593:             * @exception StandardException		Thrown on error
594:             */
595:            private boolean verifyBulkInsert(DataDictionary dd, String mode)
596:                    throws StandardException {
597:                return true;
598:            }
599:
600:            /**
601:             * Compile constants that Execution will use
602:             *
603:             * @exception StandardException		Thrown on failure
604:             */
605:            public ConstantAction makeConstantAction() throws StandardException {
606:
607:                /* Different constant actions for base tables and updatable VTIs */
608:                if (targetTableDescriptor != null) {
609:                    // Base table
610:
611:                    long heapConglomId = targetTableDescriptor
612:                            .getHeapConglomerateId();
613:                    TransactionController tc = getLanguageConnectionContext()
614:                            .getTransactionCompile();
615:                    int numIndexes = (targetTableDescriptor != null) ? indexConglomerateNumbers.length
616:                            : 0;
617:                    StaticCompiledOpenConglomInfo[] indexSCOCIs = new StaticCompiledOpenConglomInfo[numIndexes];
618:
619:                    for (int index = 0; index < numIndexes; index++) {
620:                        indexSCOCIs[index] = tc
621:                                .getStaticCompiledConglomInfo(indexConglomerateNumbers[index]);
622:                    }
623:
624:                    /*
625:                     ** If we're doing bulk insert, do table locking regardless of
626:                     ** what the optimizer decided.  This is because bulk insert is
627:                     ** generally done with a large number of rows into an empty table.
628:                     ** We also do table locking if the table's lock granularity is
629:                     ** set to table.
630:                     */
631:                    if (bulkInsert
632:                            || targetTableDescriptor.getLockGranularity() == TableDescriptor.TABLE_LOCK_GRANULARITY) {
633:                        lockMode = TransactionController.MODE_TABLE;
634:                    }
635:
636:                    return getGenericConstantActionFactory()
637:                            .getInsertConstantAction(
638:                                    targetTableDescriptor,
639:                                    heapConglomId,
640:                                    tc
641:                                            .getStaticCompiledConglomInfo(heapConglomId),
642:                                    indicesToMaintain,
643:                                    indexConglomerateNumbers,
644:                                    indexSCOCIs,
645:                                    indexNames,
646:                                    deferred,
647:                                    false,
648:                                    targetTableDescriptor.getUUID(),
649:                                    lockMode,
650:                                    null,
651:                                    null,
652:                                    targetProperties,
653:                                    getFKInfo(),
654:                                    getTriggerInfo(),
655:                                    resultColumnList
656:                                            .getStreamStorableColIds(targetTableDescriptor
657:                                                    .getNumberOfColumns()),
658:                                    getIndexedCols(), (UUID) null, null, null,
659:                                    resultSet.isOneRowResultSet(),
660:                                    autoincRowLocation);
661:                } else {
662:                    /* Return constant action for VTI
663:                     * NOTE: ConstantAction responsible for preserving instantiated
664:                     * VTIs for in-memory queries and for only preserving VTIs
665:                     * that implement Serializable for SPSs.
666:                     */
667:                    return getGenericConstantActionFactory()
668:                            .getUpdatableVTIConstantAction(
669:                                    DeferModification.INSERT_STATEMENT,
670:                                    deferred);
671:                }
672:            }
673:
674:            /**
675:             * Create a boolean[] to track the (0-based) columns which are indexed.
676:             *
677:             * @return A boolean[] to track the (0-based) columns which are indexed.
678:             *
679:             * @exception StandardException		Thrown on failure
680:             */
681:            public boolean[] getIndexedCols() throws StandardException {
682:                /* Create a boolean[] to track the (0-based) columns which are indexed */
683:                boolean[] indexedCols = new boolean[targetTableDescriptor
684:                        .getNumberOfColumns()];
685:                for (int index = 0; index < indicesToMaintain.length; index++) {
686:                    int[] colIds = indicesToMaintain[index]
687:                            .getIndexDescriptor().baseColumnPositions();
688:
689:                    for (int index2 = 0; index2 < colIds.length; index2++) {
690:                        indexedCols[colIds[index2] - 1] = true;
691:                    }
692:                }
693:
694:                return indexedCols;
695:            }
696:
697:            /**
698:             * Code generation for insert
699:             * creates an expression for:
700:             *   ResultSetFactory.getInsertResultSet(resultSet.generate(ps), this )
701:             *
702:             * @param acb	The ActivationClassBuilder for the class being built
703:             * @param mb the method  for the execute() method to be built
704:             *
705:             * @exception StandardException		Thrown on error
706:             */
707:            public void generate(ActivationClassBuilder acb, MethodBuilder mb)
708:                    throws StandardException {
709:                //If the DML is on the temporary table, generate the code to mark temporary table as modified in the current UOW
710:                generateCodeForTemporaryTable(acb, mb);
711:
712:                /* generate the parameters */
713:                generateParameterValueSet(acb);
714:                // Base table
715:                if (targetTableDescriptor != null) {
716:                    /*
717:                     ** Generate the insert result set, giving it either the original
718:                     ** source or the normalize result set, the constant action,
719:                     ** and "this".
720:                     */
721:
722:                    acb.pushGetResultSetFactoryExpression(mb);
723:
724:                    // arg 1
725:                    resultSet.generate(acb, mb);
726:
727:                    // arg 2 generate code to evaluate CHECK CONSTRAINTS
728:                    generateCheckConstraints(checkConstraints, acb, mb);
729:
730:                    mb.callMethod(VMOpcode.INVOKEINTERFACE, (String) null,
731:                            "getInsertResultSet", ClassName.ResultSet, 2);
732:                } else {
733:                    /* Generate code for the VTI
734:                     * NOTE: we need to create a dummy cost estimate for the
735:                     * targetVTI since we never optimized it.
736:                     * RESOLVEVTI - we will have to optimize it in order to 
737:                     * push predicates into the VTI.
738:                     */
739:                    targetVTI
740:                            .assignCostEstimate(resultSet.getNewCostEstimate());
741:
742:                    /*
743:                     ** Generate the insert VTI result set, giving it either the original
744:                     ** source or the normalize result set, the constant action,
745:                     */
746:                    acb.pushGetResultSetFactoryExpression(mb);
747:
748:                    // arg 1
749:                    resultSet.generate(acb, mb);
750:
751:                    // arg 2
752:                    targetVTI.generate(acb, mb);
753:
754:                    mb.callMethod(VMOpcode.INVOKEINTERFACE, (String) null,
755:                            "getInsertVTIResultSet", ClassName.ResultSet, 2);
756:                }
757:            }
758:
759:            /**
760:             * Return the type of statement, something from
761:             * StatementType.
762:             *
763:             * @return the type of statement
764:             */
765:            protected final int getStatementType() {
766:                return StatementType.INSERT;
767:            }
768:
769:            /**
770:             * Return the statement type, where it is dependent on
771:             * the targetProperties.  (insertMode = replace causes
772:             * statement type to be BULK_INSERT_REPLACE.
773:             *
774:             * @return the type of statement
775:             */
776:            static final int getStatementType(Properties targetProperties) {
777:                int retval = StatementType.INSERT;
778:
779:                // The only property that we're currently interested in is insertMode
780:                String insertMode = (targetProperties == null) ? null
781:                        : targetProperties.getProperty("insertMode");
782:                if (insertMode != null) {
783:                    String upperValue = StringUtil.SQLToUpperCase(insertMode);
784:                    if (upperValue.equals("REPLACE")) {
785:                        retval = StatementType.BULK_INSERT_REPLACE;
786:                    }
787:                }
788:                return retval;
789:            }
790:
791:            /**
792:             * Get the list of indexes on the table being inserted into.  This
793:             * is used by INSERT.  This is an optimized version of what
794:             * UPDATE and DELETE use. 
795:             *
796:             * @param td	TableDescriptor for the table being inserted into
797:             *				or deleted from
798:             *
799:             * @exception StandardException		Thrown on error
800:             */
801:            private void getAffectedIndexes(TableDescriptor td)
802:                    throws StandardException {
803:                IndexLister indexLister = td.getIndexLister();
804:
805:                indicesToMaintain = indexLister.getDistinctIndexRowGenerators();
806:                indexConglomerateNumbers = indexLister
807:                        .getDistinctIndexConglomerateNumbers();
808:                indexNames = indexLister.getDistinctIndexNames();
809:
810:                /* Add dependencies on all indexes in the list */
811:                ConglomerateDescriptor[] cds = td.getConglomerateDescriptors();
812:                CompilerContext cc = getCompilerContext();
813:
814:                for (int index = 0; index < cds.length; index++) {
815:                    cc.createDependency(cds[index]);
816:                }
817:            }
818:
819:        } // end of class InsertNode
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.