KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > derby > impl > sql > compile > DMLModStatementNode


1 /*
2
3    Derby - Class org.apache.derby.impl.sql.compile.DMLModStatementNode
4
5    Licensed to the Apache Software Foundation (ASF) under one or more
6    contributor license agreements. See the NOTICE file distributed with
7    this work for additional information regarding copyright ownership.
8    The ASF licenses this file to you under the Apache License, Version 2.0
9    (the "License"); you may not use this file except in compliance with
10    the License. You may obtain a copy of the License at
11
12       http://www.apache.org/licenses/LICENSE-2.0
13
14    Unless required by applicable law or agreed to in writing, software
15    distributed under the License is distributed on an "AS IS" BASIS,
16    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17    See the License for the specific language governing permissions and
18    limitations under the License.
19
20  */

21
22 package org.apache.derby.impl.sql.compile;
23
24 import org.apache.derby.iapi.services.loader.GeneratedMethod;
25
26 import org.apache.derby.iapi.services.context.ContextManager;
27
28 import org.apache.derby.iapi.services.compiler.JavaFactory;
29 import org.apache.derby.iapi.services.compiler.MethodBuilder;
30
31 import org.apache.derby.iapi.services.sanity.SanityManager;
32
33 import org.apache.derby.iapi.sql.depend.Dependent;
34
35 import org.apache.derby.iapi.sql.compile.CompilerContext;
36 import org.apache.derby.iapi.sql.compile.Parser;
37 import org.apache.derby.iapi.sql.compile.CostEstimate;
38 import org.apache.derby.iapi.sql.compile.OptimizerFactory;
39 import org.apache.derby.iapi.sql.compile.C_NodeTypes;
40 import org.apache.derby.iapi.sql.compile.NodeFactory;
41
42 import org.apache.derby.iapi.sql.conn.Authorizer;
43
44 import org.apache.derby.iapi.reference.ClassName;
45 import org.apache.derby.iapi.reference.SQLState;
46
47 import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
48
49 import org.apache.derby.iapi.sql.dictionary.CheckConstraintDescriptor;
50 import org.apache.derby.iapi.sql.dictionary.IndexRowGenerator;
51 import org.apache.derby.iapi.sql.dictionary.ForeignKeyConstraintDescriptor;
52 import org.apache.derby.iapi.sql.dictionary.GenericDescriptorList;
53 import org.apache.derby.iapi.sql.dictionary.ReferencedKeyConstraintDescriptor;
54 import org.apache.derby.iapi.sql.dictionary.KeyConstraintDescriptor;
55 import org.apache.derby.iapi.sql.dictionary.ConstraintDescriptor;
56 import org.apache.derby.iapi.sql.dictionary.ConstraintDescriptorList;
57 import org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptor;
58 import org.apache.derby.iapi.sql.dictionary.DataDictionary;
59 import org.apache.derby.iapi.sql.dictionary.DataDictionaryContext;
60 import org.apache.derby.iapi.sql.dictionary.SchemaDescriptor;
61 import org.apache.derby.iapi.sql.dictionary.TableDescriptor;
62 import org.apache.derby.iapi.sql.dictionary.TriggerDescriptor;
63 import org.apache.derby.iapi.sql.dictionary.ColumnDescriptor;
64 import org.apache.derby.iapi.sql.dictionary.ColumnDescriptorList;
65
66 import org.apache.derby.iapi.sql.StatementType;
67
68 import org.apache.derby.iapi.store.access.TransactionController;
69
70 import org.apache.derby.impl.sql.compile.ActivationClassBuilder;
71 import org.apache.derby.impl.sql.compile.ExpressionClassBuilder;
72
73 import org.apache.derby.iapi.error.StandardException;
74
75 import org.apache.derby.impl.sql.execute.FKInfo;
76 import org.apache.derby.impl.sql.execute.TriggerInfo;
77
78 import org.apache.derby.iapi.types.RowLocation;
79
80 import org.apache.derby.catalog.UUID;
81 import java.util.Properties JavaDoc;
82 import java.util.Vector JavaDoc;
83 import java.util.Enumeration JavaDoc;
84 import java.util.Hashtable JavaDoc;
85 import org.apache.derby.iapi.services.io.FormatableBitSet;
86 import org.apache.derby.iapi.services.classfile.VMOpcode;
87
88 /**
89  * A DMLStatement for a table modification: to wit, INSERT
90  * UPDATE or DELETE.
91  *
92  * @author Jamie
93  */

94
95 abstract class DMLModStatementNode extends DMLStatementNode
96 {
97 // protected DataDictionary dataDictionary;
98
protected FromVTI targetVTI;
99     protected TableName targetTableName;
100     protected ResultColumnList resultColumnList;
101     protected int lockMode; // lock mode for the target table
102

103     protected FKInfo[] fkInfo; // array of FKInfo structures
104
// generated during bind
105
protected TriggerInfo triggerInfo; // generated during bind
106
public TableDescriptor targetTableDescriptor;
107
108
109     /* The indexes that could be affected by this statement */
110     public IndexRowGenerator[] indicesToMaintain;
111     public long[] indexConglomerateNumbers;
112     public String JavaDoc[] indexNames;
113     protected ConstraintDescriptorList relevantCdl;
114     protected GenericDescriptorList relevantTriggers;
115
116     // PRIVATE
117
private boolean requiresDeferredProcessing;
118     private int statementType;
119     private boolean bound;
120     private ValueNode checkConstraints;
121
122     /* Info required to perform referential actions */
123     protected String JavaDoc[] fkTableNames; // referencing table names.
124
protected int[] fkRefActions; //type of referential actions
125
protected ColumnDescriptorList[] fkColDescriptors;
126     protected long[] fkIndexConglomNumbers; //conglomerate number of the backing index
127
protected boolean isDependentTable;
128     protected int[][] fkColArrays;
129     protected Hashtable JavaDoc graphHashTable;
130                           // Hash Table which maitains the querytreenode graph
131
protected TableName synonymTableName;
132     
133     /**
134      * Initializer for a DMLModStatementNode -- delegate to DMLStatementNode
135      *
136      * @param resultSet A ResultSetNode for the result set of the
137      * DML statement
138      */

139     public void init(Object JavaDoc resultSet)
140     {
141         super.init(resultSet);
142         statementType = getStatementType();
143     }
144
145     /**
146      * Initializer for a DMLModStatementNode -- delegate to DMLStatementNode
147      *
148      * @param resultSet A ResultSetNode for the result set of the
149      * DML statement
150      * @param statementType used by nodes that allocate a DMLMod directly
151      * (rather than inheriting it).
152      */

153     public void init(Object JavaDoc resultSet, Object JavaDoc statementType)
154     {
155         super.init(resultSet);
156         this.statementType = ((Integer JavaDoc) statementType).intValue();
157     }
158
159     void setTarget(QueryTreeNode targetName)
160     {
161         if (targetName instanceof TableName)
162         {
163             this.targetTableName = (TableName) targetName;
164         }
165         else
166         {
167             if (SanityManager.DEBUG)
168             {
169                 if (! (targetName instanceof FromVTI))
170                 {
171                     SanityManager.THROWASSERT(
172                         "targetName expected to be FromVTI, not " +
173                         targetName.getClass().getName());
174                 }
175             }
176             this.targetVTI = (FromVTI) targetName;
177             targetVTI.setTarget();
178         }
179     }
180
181     /**
182      * If the DML is on a temporary table, generate the code to mark temporary table as modified in the current UOW.
183      * At rollback transaction (or savepoint), we will check if the temporary table was modified in that UOW.
184      * If yes, we will remove all the data from the temporary table
185      *
186      * @param acb The ActivationClassBuilder for the class being built
187      * @param mb The execute() method to be built
188      *
189      * @exception StandardException Thrown on error
190      */

191     protected void generateCodeForTemporaryTable(ActivationClassBuilder acb, MethodBuilder mb)
192         throws StandardException
193     {
194         if (targetTableDescriptor != null && targetTableDescriptor.getTableType() == TableDescriptor.GLOBAL_TEMPORARY_TABLE_TYPE &&
195             targetTableDescriptor.isOnRollbackDeleteRows() == true)
196         {
197             mb.pushThis();
198             mb.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.Activation,
199                                     "getLanguageConnectionContext", ClassName.LanguageConnectionContext, 0);
200             mb.push(targetTableDescriptor.getName());
201             mb.callMethod(VMOpcode.INVOKEINTERFACE, null, "markTempTableAsModifiedInUnitOfWork",
202                         "void", 1);
203             mb.endStatement();
204         }
205     }
206
207     /**
208      * Verify the target table. Get the TableDescriptor
209      * if the target table is not a VTI.
210      *
211      * @exception StandardException Thrown on error
212      */

213     void verifyTargetTable()
214         throws StandardException
215     {
216                 DataDictionary dataDictionary = getDataDictionary();
217         if (targetTableName != null)
218         {
219             /*
220             ** Get the TableDescriptor for the table we are inserting into
221             */

222             SchemaDescriptor sdtc = getSchemaDescriptor(targetTableName.getSchemaName());
223
224             targetTableDescriptor = getTableDescriptor(
225                             targetTableName.getTableName(), sdtc);
226
227             if (targetTableDescriptor == null)
228             {
229                 // Check if the reference is for a synonym.
230
TableName synonymTab = resolveTableToSynonym(targetTableName);
231                 if (synonymTab == null)
232                     throw StandardException.newException(SQLState.LANG_TABLE_NOT_FOUND, targetTableName);
233                 synonymTableName = targetTableName;
234                 targetTableName = synonymTab;
235                 sdtc = getSchemaDescriptor(targetTableName.getSchemaName());
236
237                 targetTableDescriptor = getTableDescriptor(synonymTab.getTableName(), sdtc);
238                 if (targetTableDescriptor == null)
239                     throw StandardException.newException(SQLState.LANG_TABLE_NOT_FOUND, targetTableName);
240             }
241             
242             switch (targetTableDescriptor.getTableType())
243             {
244             case TableDescriptor.VIEW_TYPE:
245                 // Views are currently not updatable
246
throw StandardException.newException(SQLState.LANG_VIEW_NOT_UPDATEABLE,
247                         targetTableName);
248             
249             case TableDescriptor.VTI_TYPE:
250                 // fall through - currently all vti tables are system tables.
251
case TableDescriptor.SYSTEM_TABLE_TYPE:
252                 // System tables are not updatable
253
throw StandardException.newException(SQLState.LANG_UPDATE_SYSTEM_TABLE_ATTEMPTED,
254                         targetTableName);
255                 default:
256                     break;
257                 
258             }
259
260             /* We need to get some kind of table lock (IX here), to prevent
261              * another thread from adding a new index while we are binding,
262              * if we are a reader in DDL mode. Just a row lock on system table
263              * SYSCONGLOMERATE is not enough: that wouldn't prevent another
264              * thread from adding a new entry. Part of the fix for Beetle 3976.
265              * Same lock as in exec, compatible with row lock, for concurrency.
266              */

267             targetTableDescriptor = lockTableForCompilation(targetTableDescriptor);
268
269             getCompilerContext().createDependency(targetTableDescriptor);
270         }
271         else
272         {
273             /* VTI - VTIs in DML Mod are version 2 VTIs - They
274              * must implement java.sql.PreparedStatement and have
275              * the JDBC2.0 getMetaData() and getResultSetConcurrency()
276              * methods and return an updatable ResultSet.
277              */

278             FromList dummyFromList = new FromList();
279             targetVTI = (FromVTI) targetVTI.bindNonVTITables(dataDictionary, dummyFromList);
280             targetVTI = (FromVTI) targetVTI.bindVTITables(dummyFromList);
281         }
282     }
283
284     /**
285      *
286      * INSERT/UPDATE/DELETE are always atomic.
287      *
288      * @return true
289      */

290     public boolean isAtomic()
291     {
292         return true;
293     }
294
295     /**
296     * Get a schema descriptor for the given table.
297     * Uses this.targetTableName.
298     *
299     * @return Schema Descriptor
300     *
301     * @exception StandardException throws on schema name
302     * that doesn't exist
303     */

304     public SchemaDescriptor getSchemaDescriptor() throws StandardException
305     {
306         SchemaDescriptor sd;
307
308         sd = getSchemaDescriptor(targetTableName.getSchemaName());
309
310         return sd;
311     }
312
313     /**
314       Get a map to efficiently find heap columns from a compressed set of
315       read columns. The returns a map such that
316
317       <PRE>
318       map[heapColId (0 based)] -> readCol id (0 based)
319       </PRE>
320
321       @param column_map_length The number of columns(ints) in the map.
322       @param readColsBitSet A language style (1 based) bit set with bits for
323       read heap columns set.
324
325       RESOLVE: Replace this with a call to RowUtil when the store and
326       the language both use 0 base or 1 base offsets for columns. Today
327       we can't use the store function because we have a 1 based FormatableBitSet.
328       */

329     public static int[] getReadColMap(int column_map_length,FormatableBitSet readColsBitSet)
330     {
331         if (readColsBitSet == null) return null;
332
333         int partial_col_cnt = 0;
334         int column_map[] = new int[column_map_length];
335         int readColsBitSetSize = readColsBitSet.size();
336
337         for (int base_index = 0; base_index < column_map.length; base_index++)
338         {
339             if (readColsBitSetSize > base_index && readColsBitSet.get(base_index+1))
340                 column_map[base_index] = partial_col_cnt++;
341             else
342                 // this column map offset entry should never be referenced.
343
column_map[base_index] = -1;
344         }
345
346         return(column_map);
347     }
348
349     /**
350      * Get and bind the ResultColumnList representing the columns in the
351      * target table, given the table's name.
352      *
353      * @exception StandardException Thrown on error
354      */

355     protected void getResultColumnList()
356         throws StandardException
357     {
358         if (targetVTI == null)
359         {
360             getResultColumnList((ResultColumnList) null);
361         }
362         else
363         {
364             /* binding VTI - just point to VTI's RCL,
365              * which was already bound.
366              */

367             resultColumnList = targetVTI.getResultColumns();
368         }
369     }
370
371     /**
372      * Get and bind the ResultColumnList representing the columns in the
373      * target table, given the table's name.
374      *
375      * @exception StandardException Thrown on error
376      */

377     protected FromBaseTable getResultColumnList(ResultColumnList inputRcl)
378         throws StandardException
379     {
380         /* Get a ResultColumnList representing all the columns in the target */
381         FromBaseTable fbt =
382             (FromBaseTable)
383                 (getNodeFactory().getNode(
384                                         C_NodeTypes.FROM_BASE_TABLE,
385                                         targetTableName,
386                                         null,
387                                         null,
388                                         null,
389                                         getContextManager())
390                 );
391
392         fbt.bindNonVTITables(
393             getDataDictionary(),
394             (FromList) getNodeFactory().getNode(
395                                 C_NodeTypes.FROM_LIST,
396                                 getNodeFactory().doJoinOrderOptimization(),
397                                 getContextManager()));
398
399         getResultColumnList(
400                             fbt,
401                             inputRcl
402                             );
403         return fbt;
404     }
405
406     /**
407      * Get and bind the ResultColumnList representing the columns in the
408      * target table, given a FromTable for the target table.
409      *
410      * @exception StandardException Thrown on error
411      */

412     private void getResultColumnList(FromBaseTable fromBaseTable,
413                                         ResultColumnList inputRcl)
414         throws StandardException
415     {
416         if (inputRcl == null)
417         {
418             resultColumnList = fromBaseTable.getAllResultColumns(null);
419             resultColumnList.bindResultColumnsByPosition(targetTableDescriptor);
420         }
421         else
422         {
423             resultColumnList = fromBaseTable.getResultColumnsForList(null, inputRcl,
424                                                     fromBaseTable.getTableNameField());
425
426             resultColumnList.bindResultColumnsByName(targetTableDescriptor,
427                                                     (DMLStatementNode) this);
428         }
429     }
430
431     /**
432      * Gets and binds all the constraints for an INSERT/UPDATE/DELETE.
433      * First finds the constraints that are relevant to this node.
434      * This is done by calling getAllRelevantConstriants(). If
435      * getAllRelevantConstraints() has already been called, then
436      * this list is used. Then it creates appropriate
437      * dependencies. Then binds check constraints. It also
438      * generates the array of FKInfo items that are used in
439      * code generation.
440
441      * Note: we have a new flag here to see if defer processing is enabled or
442      * not, the only scenario that is disabled is when we reapply the
443      * reply message we get from the source
444      *
445      *
446      * @param dataDictionary The DataDictionary
447      * @param nodeFactory Where to get query tree nodes.
448      * @param targetTableDescriptor The TableDescriptor
449      * @param dependent Parent object that will depend on all the constraints
450      * that we look up. If this argument is null, then we
451      * use the default dependent (the statement being compiled).
452      * @param sourceRCL RCL of the table being changed
453      * @param changedColumnIds If null, all columns being changed, otherwise array
454      * of 1-based column ids for columns being changed
455      * @param readColsBitSet bit set for the read scan
456      * @param skipCheckConstraints whether to skip check constraints or not
457      * @param includeTriggers whether triggers are included in the processing
458      *
459      * @return The bound, ANDed check constraints as a query tree.
460      *
461      * @exception StandardException Thrown on failure
462      */

463     public ValueNode bindConstraints
464     (
465         DataDictionary dataDictionary,
466         NodeFactory nodeFactory,
467         TableDescriptor targetTableDescriptor,
468         Dependent dependent,
469         ResultColumnList sourceRCL,
470         int[] changedColumnIds,
471         FormatableBitSet readColsBitSet,
472         boolean skipCheckConstraints,
473         boolean includeTriggers
474     )
475         throws StandardException
476     {
477         bound = true;
478
479         /* Nothing to do if updatable VTI */
480         if (targetVTI != null)
481         {
482             return null;
483         }
484
485         // Donot need privileges to execute constraints
486
getCompilerContext().pushCurrentPrivType( Authorizer.NULL_PRIV);
487         try {
488             getAllRelevantConstraints(dataDictionary,
489                                             targetTableDescriptor,
490                                             skipCheckConstraints,
491                                             changedColumnIds);
492             createConstraintDependencies(dataDictionary, relevantCdl, dependent);
493             generateFKInfo(relevantCdl, dataDictionary, targetTableDescriptor, readColsBitSet);
494
495             getAllRelevantTriggers(dataDictionary, targetTableDescriptor,
496                                changedColumnIds, includeTriggers);
497             createTriggerDependencies(relevantTriggers, dependent);
498             generateTriggerInfo(relevantTriggers, targetTableDescriptor, changedColumnIds);
499
500             if (skipCheckConstraints)
501             {
502                 return null;
503             }
504
505             checkConstraints = generateCheckTree(relevantCdl,
506                                                         targetTableDescriptor);
507
508             if (checkConstraints != null)
509             {
510                 bindCheckConstraint(nodeFactory,
511                                 targetTableDescriptor,
512                                 sourceRCL,
513                                 checkConstraints);
514             }
515         }
516         finally
517         {
518             getCompilerContext().popCurrentPrivType();
519         }
520
521         return checkConstraints;
522     }
523
524     /**
525      * Binds an already parsed check constraint
526      *
527      * @param nodeFactory Where to get query tree nodes.
528      * @param targetTableDescriptor The TableDescriptor for the constrained table.
529      * @param sourceRCL Result columns.
530      * @param checkConstraint Parsed query tree for check constraint
531      *
532      * @exception StandardException Thrown on failure
533      */

534     public void bindCheckConstraint
535     (
536         NodeFactory nodeFactory,
537         TableDescriptor targetTableDescriptor,
538         ResultColumnList sourceRCL,
539         ValueNode checkConstraint
540     )
541         throws StandardException
542     {
543
544         TableName targetTableName =
545                         makeTableName(targetTableDescriptor.getSchemaName(),
546                                       targetTableDescriptor.getName());
547
548
549         /* We now have the check constraints as a query tree. Now, we prepare
550          * to bind that query tree to the source's RCL. That way, the
551          * generated code for the check constraints will be evaluated against the
552          * source row to be inserted into the target table or
553          * against the after portion of the source row for the update
554          * into the target table.
555          * o Goober up a new FromList which has a single table,
556          * a goobered up FromBaseTable for the target table
557          * which has the source's RCL as it RCL.
558          * (This allows the ColumnReferences in the check constraint
559          * tree to be bound to the right RCs.)
560          *
561          * Note that in some circumstances we may not actually verify
562          * the constraint against the source RCL but against a temp
563          * row source used for deferred processing because of a trigger.
564          * In this case, the caller of bindConstraints (UpdateNode)
565          * has chosen to pass in the correct RCL to bind against.
566          */

567         FromList fakeFromList =
568             (FromList) nodeFactory.getNode(
569                             C_NodeTypes.FROM_LIST,
570                             nodeFactory.doJoinOrderOptimization(),
571                             getContextManager());
572         FromBaseTable table = (FromBaseTable)
573             nodeFactory.getNode(
574                 C_NodeTypes.FROM_BASE_TABLE,
575                 targetTableName,
576                 null,
577                 sourceRCL,
578                 null,
579                 getContextManager());
580         table.setTableNumber(0);
581         fakeFromList.addFromTable(table);
582
583         // Now we can do the bind.
584
checkConstraint = checkConstraint.bindExpression(
585                                         fakeFromList,
586                                         (SubqueryList) null,
587                                         (Vector JavaDoc) null);
588     }
589
590     /**
591      * Determine whether or not there are check constraints on the
592      * specified table.
593      *
594      * @param dd The DataDictionary to use
595      * @param td The TableDescriptor for the table
596      *
597      * @return Whether or not there are check constraints on the specified table.
598      *
599      * @exception StandardException Thrown on failure
600      */

601     protected boolean hasCheckConstraints(DataDictionary dd,
602                                           TableDescriptor td)
603         throws StandardException
604     {
605         ConstraintDescriptorList cdl = dd.getConstraintDescriptors(td);
606         if (cdl == null)
607             return false;
608         ConstraintDescriptorList ccCDL = cdl.getSubList(DataDictionary.CHECK_CONSTRAINT);
609
610         return (ccCDL.size() > 0);
611     }
612
613
614     /**
615      * Get the ANDing of all appropriate check constraints as 1 giant query tree.
616      *
617      * Makes the calling object (usually a Statement) dependent on all the constraints.
618      *
619      * @param cdl The constriant descriptor list
620      * @param td The TableDescriptor
621      *
622      * @return The ANDing of all appropriate check constraints as a query tree.
623      *
624      * @exception StandardException Thrown on failure
625      */

626     private ValueNode generateCheckTree
627     (
628         ConstraintDescriptorList cdl,
629         TableDescriptor td
630     )
631         throws StandardException
632     {
633         ConstraintDescriptorList ccCDL = cdl.getSubList(DataDictionary.CHECK_CONSTRAINT);
634         int ccCDLSize = ccCDL.size();
635         ValueNode checkTree = null;
636
637         // Get the text of all the check constraints
638
for (int index = 0; index < ccCDLSize; index++)
639         {
640             ConstraintDescriptor cd = ccCDL.elementAt(index);
641
642             String JavaDoc constraintText = cd.getConstraintText();
643
644             // Get the query tree for this constraint
645
ValueNode oneConstraint =
646                 parseCheckConstraint(constraintText, td);
647
648             // Put a TestConstraintNode above the constraint tree
649
TestConstraintNode tcn =
650                 (TestConstraintNode) getNodeFactory().getNode(
651                     C_NodeTypes.TEST_CONSTRAINT_NODE,
652                     oneConstraint,
653                     SQLState.LANG_CHECK_CONSTRAINT_VIOLATED,
654                     td.getQualifiedName(),
655                     cd.getConstraintName(),
656                     getContextManager());
657                     
658             // Link consecutive TestConstraintNodes with AND nodes
659
if (checkTree == null)
660             {
661                 checkTree = tcn;
662             }
663             else
664             {
665                 checkTree = (ValueNode) getNodeFactory().getNode(
666                     C_NodeTypes.AND_NODE,
667                     tcn,
668                     checkTree,
669                     getContextManager());
670             }
671         }
672
673         return checkTree;
674     }
675     
676     /**
677      * Generate the FKInfo structures used during code generation.
678      * For each constraint that isn't a check constraint, add another
679      * one of these FKInfo structures and then package them up into
680      * a single array.
681      *
682      * @param cdl The constriant descriptor list
683      * @param dd The DataDictionary
684      * @param td The TableDescriptor
685      * @param readColsBitSet columns read
686      *
687      * @exception StandardException Thrown on failure
688      */

689     private void generateFKInfo
690     (
691         ConstraintDescriptorList cdl,
692         DataDictionary dd,
693         TableDescriptor td,
694         FormatableBitSet readColsBitSet
695     )
696         throws StandardException
697     {
698         Vector JavaDoc fkVector = new Vector JavaDoc(10);
699         int type;
700         UUID[] uuids = null;
701         long[] conglomNumbers = null;
702         String JavaDoc[] fkNames = null;
703         ConstraintDescriptorList fkcdl;
704         ReferencedKeyConstraintDescriptor refcd;
705         boolean[] isSelfReferencingFK;
706         ConstraintDescriptorList activeList = dd.getActiveConstraintDescriptors(cdl);
707         int[] rowMap = getRowMap(readColsBitSet, td);
708         int[] raRules = null;
709         Vector JavaDoc refTableNames = new Vector JavaDoc(1);
710         Vector JavaDoc refIndexConglomNum = new Vector JavaDoc(1);
711         Vector JavaDoc refActions = new Vector JavaDoc(1);
712         Vector JavaDoc refColDescriptors = new Vector JavaDoc(1);
713         Vector JavaDoc fkColMap = new Vector JavaDoc(1);
714         int activeSize = activeList.size();
715         for (int index = 0; index < activeSize; index++)
716         {
717             ConstraintDescriptor cd = activeList.elementAt(index);
718
719             if (cd instanceof ForeignKeyConstraintDescriptor)
720             {
721                 /*
722                 ** We are saving information for checking the
723                 ** primary/unique key that is referenced by this
724                 ** foreign key, so type is FOREIGN KEY.
725                 */

726                 type = FKInfo.FOREIGN_KEY;
727                 refcd = ((ForeignKeyConstraintDescriptor)cd).getReferencedConstraint();
728                 uuids = new UUID[1];
729                 conglomNumbers = new long[1];
730                 fkNames = new String JavaDoc[1];
731                 isSelfReferencingFK = new boolean[1];
732                 raRules = new int[1];
733                 fkSetupArrays(dd, (ForeignKeyConstraintDescriptor)cd,
734                         0, uuids, conglomNumbers,
735                         fkNames, isSelfReferencingFK, raRules);
736
737                 // oops, get the right constraint name -- for error
738
// handling we want the FK name, not refcd name
739
fkNames[0] = cd.getConstraintName();
740             }
741             else if (cd instanceof ReferencedKeyConstraintDescriptor)
742             {
743                 refcd = (ReferencedKeyConstraintDescriptor)cd;
744
745                 /*
746                 ** We are saving information for checking the
747                 ** foreign key(s) that is dependent on this referenced
748                 ** key, so type is REFERENCED KEY.
749                 */

750                 type = FKInfo.REFERENCED_KEY;
751                 fkcdl = dd.getActiveConstraintDescriptors
752                     ( ((ReferencedKeyConstraintDescriptor)cd).getForeignKeyConstraints(ConstraintDescriptor.ENABLED) );
753     
754                 int size = fkcdl.size();
755                 if (size == 0)
756                 {
757                     continue;
758                 }
759
760                 uuids = new UUID[size];
761                 fkNames = new String JavaDoc[size];
762                 conglomNumbers = new long[size];
763                 isSelfReferencingFK = new boolean[size];
764                 raRules = new int[size];
765                 ForeignKeyConstraintDescriptor fkcd = null;
766                 TableDescriptor fktd;
767                 ColumnDescriptorList coldl;
768                 int[] refColumns;
769                 ColumnDescriptor cold;
770                 int[] colArray = remapReferencedColumns(cd, rowMap);
771                 for (int inner = 0; inner < size; inner++)
772                 {
773                     fkcd = (ForeignKeyConstraintDescriptor) fkcdl.elementAt(inner);
774                     fkSetupArrays(dd, fkcd,
775                                 inner, uuids, conglomNumbers, fkNames,
776                                 isSelfReferencingFK, raRules);
777                     if((raRules[inner] == StatementType.RA_CASCADE) ||
778                        (raRules[inner] ==StatementType.RA_SETNULL))
779                     {
780                         //find the referencing table Name
781
fktd = fkcd.getTableDescriptor();
782                         refTableNames.addElement(fktd.getSchemaName() + "." + fktd.getName());
783                         refActions.addElement(new Integer JavaDoc(raRules[inner]));
784                         //find the referencing column name required for update null.
785
refColumns = fkcd.getReferencedColumns();
786                         coldl = fktd.getColumnDescriptorList();
787                         ColumnDescriptorList releventColDes = new ColumnDescriptorList();
788                         for(int i = 0 ; i < refColumns.length; i++)
789                         {
790                             cold =(ColumnDescriptor)coldl.elementAt(refColumns[i]-1);
791                             releventColDes.add(cold);
792                         }
793                         refColDescriptors.addElement(releventColDes);
794                         refIndexConglomNum.addElement(new Long JavaDoc(conglomNumbers[inner]));
795                         fkColMap.addElement(colArray);
796                     }
797                 }
798             }
799             else
800             {
801                 continue;
802             }
803
804             TableDescriptor pktd = refcd.getTableDescriptor();
805             UUID pkuuid = refcd.getIndexId();
806             ConglomerateDescriptor pkIndexConglom = pktd.getConglomerateDescriptor(pkuuid);
807
808             TableDescriptor refTd = cd.getTableDescriptor();
809             fkVector.addElement(new FKInfo(
810                                     fkNames, // foreign key names
811
refTd.getName(), // table being modified
812
statementType, // INSERT|UPDATE|DELETE
813
type, // FOREIGN_KEY|REFERENCED_KEY
814
pkuuid, // referenced backing index uuid
815
pkIndexConglom.getConglomerateNumber(), // referened backing index conglom
816
uuids, // fk backing index uuids
817
conglomNumbers, // fk backing index congloms
818
isSelfReferencingFK, // is self ref array of bool
819
remapReferencedColumns(cd, rowMap), // column referened by key
820
dd.getRowLocationTemplate(getLanguageConnectionContext(), refTd),
821                                                                     // row location template for table being modified
822
raRules)); // referential action rules
823

824         }
825         
826         /*
827         ** Now convert the vector into an array.
828         */

829         int size = fkVector.size();
830         if (size > 0)
831         {
832             fkInfo = new FKInfo[size];
833             for (int i = 0; i < size; i++)
834             {
835                 fkInfo[i] = (FKInfo)fkVector.elementAt(i);
836             }
837         }
838
839         //convert the ref action info vectors to to arrays
840
size = refActions.size();
841         if (size > 0)
842         {
843             fkTableNames = new String JavaDoc[size];
844             fkRefActions = new int[size];
845             fkColDescriptors = new ColumnDescriptorList[size];
846             fkIndexConglomNumbers = new long[size];
847             fkColArrays = new int[size][];
848             for (int i = 0; i < size; i++)
849             {
850                 fkTableNames[i] = (String JavaDoc)refTableNames.elementAt(i);
851                 fkRefActions[i] = ((Integer JavaDoc) refActions.elementAt(i)).intValue();
852                 fkColDescriptors[i] =
853                     (ColumnDescriptorList)refColDescriptors.elementAt(i);
854                 fkIndexConglomNumbers[i] =
855                     ((Long JavaDoc)refIndexConglomNum.elementAt(i)).longValue();
856                 fkColArrays[i] = ((int[])fkColMap.elementAt(i));
857             }
858         }
859
860     }
861
862     /*
863     ** Simple little helper method
864     */

865     private void fkSetupArrays
866     (
867         DataDictionary dd,
868         ForeignKeyConstraintDescriptor fkcd,
869         int index,
870         UUID[] uuids,
871         long[] conglomNumbers,
872         String JavaDoc[] fkNames,
873         boolean[] isSelfReferencingFK,
874         int[] raRules
875     )
876         throws StandardException
877     {
878         fkNames[index] = fkcd.getConstraintName();
879         uuids[index] = fkcd.getIndexId();
880         conglomNumbers[index] = fkcd.getIndexConglomerateDescriptor(dd).getConglomerateNumber();
881         isSelfReferencingFK[index] = fkcd.isSelfReferencingFK();
882         if(statementType == StatementType.DELETE)
883             raRules[index] = fkcd.getRaDeleteRule();
884         else if(statementType == StatementType.UPDATE)
885             raRules[index] = fkcd.getRaUpdateRule();
886     }
887
888     /**
889      * Generate the TriggerInfo structures used during code generation.
890      *
891      * @param triggerList The trigger descriptor list
892      * @param td The TableDescriptor
893      * @param changedCols The columns that are being modified
894      *
895      * @exception StandardException Thrown on failure
896      */

897     private void generateTriggerInfo
898     (
899         GenericDescriptorList triggerList,
900         TableDescriptor td,
901         int[] changedCols
902     )
903         throws StandardException
904     {
905         if ((triggerList != null) && (triggerList.size() > 0))
906         {
907             triggerInfo = new TriggerInfo(td, changedCols, triggerList);
908         }
909     }
910
911     /**
912      * Return the FKInfo structure. Just a little wrapper
913      * to make sure we don't try to access it until after
914      * binding.
915      *
916      * @return the array of fkinfos
917      */

918     public FKInfo[] getFKInfo()
919     {
920         if (SanityManager.DEBUG)
921         {
922             SanityManager.ASSERT(bound, "attempt to access FKInfo "+
923                     "before binding");
924         }
925         return fkInfo;
926     }
927
928     /**
929      * Return the TriggerInfo structure. Just a little wrapper
930      * to make sure we don't try to access it until after
931      * binding.
932      *
933      * @return the trigger info
934      */

935     public TriggerInfo getTriggerInfo()
936     {
937         if (SanityManager.DEBUG)
938         {
939             SanityManager.ASSERT(bound, "attempt to access TriggerInfo "+
940                     "before binding");
941         }
942         return triggerInfo;
943     }
944
945     /**
946      * Get the check constraints for this node
947      *
948      * @return the check constraints, may be null
949      */

950     public ValueNode getCheckConstraints()
951     {
952         if (SanityManager.DEBUG)
953         {
954             SanityManager.ASSERT(bound, "attempt to access FKInfo "+
955                     "before binding");
956         }
957         return checkConstraints;
958     }
959             
960     /**
961      * Makes the calling object (usually a Statement) dependent on all the constraints.
962      *
963      * @param tdl The trigger descriptor list
964      * @param dependent Parent object that will depend on all the constraints
965      * that we look up. If this argument is null, then we
966      * use the default dependent (the statement being compiled).
967      *
968      * @exception StandardException Thrown on failure
969      */

970     private void createTriggerDependencies
971     (
972         GenericDescriptorList tdl,
973         Dependent dependent
974     )
975         throws StandardException
976     {
977         CompilerContext compilerContext = getCompilerContext();
978
979         Enumeration JavaDoc descs = tdl.elements();
980
981         while (descs.hasMoreElements())
982         {
983             TriggerDescriptor td = (TriggerDescriptor)descs.nextElement();
984
985             /*
986             ** The dependent now depends on this trigger.
987             ** the default dependent is the statement
988             ** being compiled.
989             */

990             if (dependent == null)
991             {
992                 compilerContext.createDependency(td);
993             }
994             else
995             {
996                 compilerContext.createDependency(dependent, td);
997             }
998         }
999     }
1000
1001    /**
1002     * Get all the triggers relevant to this DML operation
1003     *
1004     * @param dd The data dictionary
1005     * @param td The TableDescriptor
1006     * @param changedColumnIds If null, all columns being changed, otherwise array
1007     * of 1-based column ids for columns being changed
1008     * @param includeTriggers whether we allow trigger processing or not for
1009     * this table
1010     *
1011     * @return the constraint descriptor list
1012     *
1013     * @exception StandardException Thrown on failure
1014     */

1015    protected GenericDescriptorList getAllRelevantTriggers
1016    (
1017        DataDictionary dd,
1018        TableDescriptor td,
1019        int[] changedColumnIds,
1020        boolean includeTriggers
1021    )
1022        throws StandardException
1023    {
1024        if ( relevantTriggers != null ) { return relevantTriggers; }
1025
1026        relevantTriggers = new GenericDescriptorList();
1027
1028        if(!includeTriggers)
1029            return relevantTriggers;
1030
1031        td.getAllRelevantTriggers( statementType, changedColumnIds, relevantTriggers );
1032        adjustDeferredFlag( relevantTriggers.size() > 0 );
1033        return relevantTriggers;
1034    }
1035
1036    protected void adjustDeferredFlag( boolean adjustment )
1037    {
1038        if( !requiresDeferredProcessing ) { requiresDeferredProcessing = adjustment; }
1039    }
1040
1041    /**
1042     * Get all of our dependents due to a constraint.
1043     *
1044     * Makes the calling object (usually a Statement) dependent on all the constraints.
1045     *
1046     * @param dd The data dictionary
1047     * @param cdl The constraint descriptor list
1048     * @param dependent Parent object that will depend on all the constraints
1049     * that we look up. If this argument is null, then we
1050     * use the default dependent (the statement being compiled).
1051     *
1052     * @exception StandardException Thrown on failure
1053     */

1054    private void createConstraintDependencies
1055    (
1056        DataDictionary dd,
1057        ConstraintDescriptorList cdl,
1058        Dependent dependent
1059    )
1060        throws StandardException
1061    {
1062        CompilerContext compilerContext = getCompilerContext();
1063
1064        int cdlSize = cdl.size();
1065        for (int index = 0; index < cdlSize; index++)
1066        {
1067            ConstraintDescriptor cd = cdl.elementAt(index);
1068
1069            /*
1070            ** The dependent now depends on this constraint.
1071            ** the default dependent is the statement
1072            ** being compiled.
1073            */

1074            if (dependent == null)
1075            {
1076                compilerContext.createDependency(cd);
1077            }
1078            else
1079            {
1080                compilerContext.createDependency(dependent, cd);
1081            }
1082
1083            /*
1084            ** We are also dependent on all referencing keys --
1085            ** if one of them is deleted, we'll have to recompile.
1086            ** Also, if there is a BULK_INSERT on the table
1087            ** we are going to scan to validate the constraint,
1088            ** the index number will change, so we'll add a
1089            ** dependency on all tables we will scan.
1090            */

1091            if (cd instanceof ReferencedKeyConstraintDescriptor)
1092            {
1093                ConstraintDescriptorList fkcdl = dd.getActiveConstraintDescriptors
1094                    ( ((ReferencedKeyConstraintDescriptor)cd).getForeignKeyConstraints(ConstraintDescriptor.ENABLED) );
1095    
1096                int fklSize = fkcdl.size();
1097                for (int inner = 0; inner < fklSize; inner++)
1098                {
1099                    ConstraintDescriptor fkcd = fkcdl.elementAt(inner);
1100                    if (dependent == null)
1101                    {
1102                        compilerContext.createDependency(fkcd);
1103                        compilerContext.createDependency(fkcd.getTableDescriptor());
1104                    }
1105                    else
1106                    {
1107                        compilerContext.createDependency(dependent, fkcd);
1108                        compilerContext.createDependency(dependent, fkcd.getTableDescriptor());
1109                    }
1110                }
1111            }
1112            else if (cd instanceof ForeignKeyConstraintDescriptor)
1113            {
1114                ForeignKeyConstraintDescriptor fkcd = (ForeignKeyConstraintDescriptor) cd;
1115                if (dependent == null)
1116                {
1117                    compilerContext.createDependency(fkcd.getReferencedConstraint().getTableDescriptor());
1118                }
1119                else
1120                {
1121                    compilerContext.createDependency(dependent,
1122                                    fkcd.getReferencedConstraint().getTableDescriptor());
1123                }
1124            }
1125        }
1126    }
1127
1128    /**
1129     * Get all the constraints relevant to this DML operation
1130     *
1131     * @param dd The DataDictionary
1132     * @param td The TableDescriptor
1133     * @param skipCheckConstraints Skip check constraints
1134     * @param changedColumnIds If null, all columns being changed, otherwise array
1135     * of 1-based column ids for columns being changed
1136     *
1137     * @return the constraint descriptor list
1138     *
1139     * @exception StandardException Thrown on failure
1140     */

1141    protected ConstraintDescriptorList getAllRelevantConstraints
1142    (
1143        DataDictionary dd,
1144        TableDescriptor td,
1145        boolean skipCheckConstraints,
1146        int[] changedColumnIds
1147    )
1148        throws StandardException
1149    {
1150        if ( relevantCdl != null ) { return relevantCdl; }
1151
1152        boolean[] needsDeferredProcessing = new boolean[1];
1153        relevantCdl = new ConstraintDescriptorList();
1154
1155        needsDeferredProcessing[0] = requiresDeferredProcessing;
1156        td.getAllRelevantConstraints
1157            ( statementType, skipCheckConstraints, changedColumnIds,
1158              needsDeferredProcessing, relevantCdl );
1159
1160        adjustDeferredFlag( needsDeferredProcessing[0] );
1161
1162        return relevantCdl;
1163    }
1164
1165    /**
1166     * Does this DML Node require deferred processing?
1167     * Set to true if we have triggers or referential
1168     * constraints that need deferred processing.
1169     *
1170     * @return true/false
1171     */

1172    public boolean requiresDeferredProcessing()
1173    {
1174        return requiresDeferredProcessing;
1175    }
1176
1177    /**
1178      * Parse a check constraint and turn it into a query tree.
1179      *
1180      * @param checkConstraintText Text of CHECK CONSTRAINT.
1181      * @param td The TableDescriptor for the table the the constraint is on.
1182      *
1183      *
1184      * @return The parsed check constraint as a query tree.
1185      *
1186      * @exception StandardException Thrown on failure
1187      */

1188    public ValueNode parseCheckConstraint
1189    (
1190        String JavaDoc checkConstraintText,
1191        TableDescriptor td
1192    )
1193        throws StandardException
1194    {
1195        Parser p;
1196        ValueNode checkTree;
1197        LanguageConnectionContext lcc = getLanguageConnectionContext();
1198        CompilerContext compilerContext = getCompilerContext();
1199
1200        /* Get a Statement to pass to the parser */
1201
1202        /* We're all set up to parse. We have to build a compile SQL statement
1203         * before we can parse - we just have a WHERE clause right now.
1204         * So, we goober up a SELECT * FROM table WHERE checkDefs.
1205         */

1206        String JavaDoc select = "SELECT * FROM " +
1207                        td.getQualifiedName() +
1208                        " WHERE " +
1209                        checkConstraintText;
1210        
1211        /*
1212        ** Get a new compiler context, so the parsing of the select statement
1213        ** doesn't mess up anything in the current context (it could clobber
1214        ** the ParameterValueSet, for example).
1215        */

1216        CompilerContext newCC = lcc.pushCompilerContext();
1217
1218        p = newCC.getParser();
1219                
1220        /* Finally, we can call the parser */
1221        // Since this is always nested inside another SQL statement, so topLevel flag
1222
// should be false
1223
QueryTreeNode qt = p.parseStatement(select);
1224        if (SanityManager.DEBUG)
1225        {
1226            if (! (qt instanceof CursorNode))
1227            {
1228                SanityManager.THROWASSERT(
1229                    "qt expected to be instanceof CursorNode, not " +
1230                    qt.getClass().getName());
1231            }
1232            CursorNode cn = (CursorNode) qt;
1233            if (! (cn.getResultSetNode() instanceof SelectNode))
1234            {
1235                SanityManager.THROWASSERT(
1236                    "cn.getResultSetNode() expected to be instanceof SelectNode, not " +
1237                    cn.getResultSetNode().getClass().getName());
1238            }
1239        }
1240
1241        checkTree = ((SelectNode) ((CursorNode) qt).getResultSetNode()).getWhereClause();
1242
1243        lcc.popCompilerContext(newCC);
1244
1245        return checkTree;
1246    }
1247
1248
1249    /**
1250      * Generate the code to evaluate a tree of CHECK CONSTRAINTS.
1251      *
1252      * @param checkConstraints Bound query tree of ANDed check constraints.
1253      * @param ecb Expression Class Builder
1254      *
1255      *
1256      *
1257      * @exception StandardException Thrown on error
1258      */

1259    public void generateCheckConstraints
1260    (
1261        ValueNode checkConstraints,
1262        ExpressionClassBuilder ecb,
1263        MethodBuilder mb
1264    )
1265                            throws StandardException
1266    {
1267        // for the check constraints, we generate an exprFun
1268
// that evaluates the expression of the clause
1269
// against the current row of the child's result.
1270
// if there are no check constraints, simply pass null
1271
// to optimize for run time performance.
1272

1273        // generate the function and initializer:
1274
// Note: Boolean lets us return nulls (boolean would not)
1275
// private Boolean exprN()
1276
// {
1277
// return <<checkConstraints.generate(ps)>>;
1278
// }
1279
// static Method exprN = method pointer to exprN;
1280

1281        // if there is no check constraint, we just want to pass null.
1282
if (checkConstraints == null)
1283        {
1284            mb.pushNull(ClassName.GeneratedMethod);
1285        }
1286        else
1287        {
1288            MethodBuilder userExprFun = generateCheckConstraints(checkConstraints, ecb);
1289
1290            // check constraint is used in the final result set
1291
// as an access of the new static
1292
// field holding a reference to this new method.
1293
ecb.pushMethodReference(mb, userExprFun);
1294        }
1295    }
1296
1297    /**
1298      * Generate a method to evaluate a tree of CHECK CONSTRAINTS.
1299      *
1300      * @param checkConstraints Bound query tree of ANDed check constraints.
1301      * @param ecb Expression Class Builder
1302      *
1303      *
1304      *
1305      * @exception StandardException Thrown on error
1306      */

1307    public MethodBuilder generateCheckConstraints
1308    (
1309        ValueNode checkConstraints,
1310        ExpressionClassBuilder ecb
1311    )
1312        throws StandardException
1313    {
1314        // this sets up the method and the static field.
1315
// generates:
1316
// java.lang.Object userExprFun { }
1317
MethodBuilder userExprFun = ecb.newUserExprFun();
1318        
1319        // check constraint knows it is returning its value;
1320

1321        /* generates:
1322         * return <checkExpress.generate(ecb)>;
1323         * and adds it to userExprFun
1324         */

1325
1326        checkConstraints.generateExpression(ecb, userExprFun);
1327        userExprFun.methodReturn();
1328        
1329        // we are done modifying userExprFun, complete it.
1330
userExprFun.complete();
1331
1332        return userExprFun;
1333    }
1334
1335  /**
1336   * Generate an optimized QueryTree from a bound QueryTree. Actually,
1337   * it can annotate the tree in place rather than generate a new tree,
1338   * but this interface allows the root node of the optimized QueryTree
1339   * to be different from the root node of the bound QueryTree.
1340   *
1341   * For non-optimizable statements, this method is a no-op.
1342   *
1343   * Throws an exception if the tree is not bound, or if the binding
1344   * is out of date.
1345   *
1346   * @return An optimized QueryTree
1347   *
1348   * @exception StandardException Thrown on failure
1349   */

1350    public QueryTreeNode optimize() throws StandardException
1351    {
1352        ResultSetNode originalRSNode = getResultSetNode();
1353
1354        /* First optimize the query */
1355        QueryTreeNode retval = super.optimize();
1356
1357        /* In language we always set it to row lock, it's up to store to
1358         * upgrade it to table lock. This makes sense for the default read
1359         * committed isolation level and update lock. For more detail, see
1360         * Beetle 4133.
1361         */

1362        lockMode = TransactionController.MODE_RECORD;
1363
1364        return retval;
1365    }
1366
1367    /**
1368     * Get the list of indexes that must be updated by this DML statement.
1369     * WARNING: As a side effect, it creates dependencies on those indexes.
1370     *
1371     * @param td The table descriptor for the table being updated
1372     * @param updatedColumns The updated column list. If not update, null
1373     * @param colBitSet a 1 based bit set of the columns in the list
1374     *
1375     * @exception StandardException Thrown on error
1376     */

1377    protected void getAffectedIndexes
1378    (
1379        TableDescriptor td,
1380        ResultColumnList updatedColumns,
1381        FormatableBitSet colBitSet
1382    )
1383                    throws StandardException
1384    {
1385        Vector JavaDoc conglomVector = new Vector JavaDoc();
1386
1387        DMLModStatementNode.getXAffectedIndexes(td, updatedColumns, colBitSet, conglomVector );
1388
1389        markAffectedIndexes( conglomVector );
1390    }
1391    /**
1392      * Marks which indexes are affected by an UPDATE of the
1393      * desired shape.
1394      *
1395      * Is passed a list of updated columns. Does the following:
1396      *
1397      * 1) finds all indices which overlap the updated columns
1398      * 2) adds the index columns to a bitmap of affected columns
1399      * 3) adds the index descriptors to a list of conglomerate
1400      * descriptors.
1401      *
1402      * @param updatedColumns a list of updated columns
1403      * @param colBitSet OUT: evolving bitmap of affected columns
1404      * @param conglomVector OUT: vector of affected indices
1405      *
1406      * @exception StandardException Thrown on error
1407      */

1408    static void getXAffectedIndexes
1409    (
1410        TableDescriptor baseTable,
1411        ResultColumnList updatedColumns,
1412        FormatableBitSet colBitSet,
1413        Vector JavaDoc conglomVector
1414    )
1415        throws StandardException
1416    {
1417        ConglomerateDescriptor[] cds = baseTable.getConglomerateDescriptors();
1418
1419        /* we only get distinct conglomerate numbers. If duplicate indexes
1420         * share one conglomerate, we only return one number.
1421         */

1422        long[] distinctConglomNums = new long[cds.length - 1];
1423        int distinctCount = 0;
1424
1425        for (int index = 0; index < cds.length; index++)
1426        {
1427            ConglomerateDescriptor cd = cds[index];
1428
1429            if (!cd.isIndex()) { continue; }
1430
1431            /*
1432            ** If this index doesn't contain any updated
1433            ** columns, then we can skip it.
1434            */

1435            if ((updatedColumns != null) &&
1436                (!updatedColumns.updateOverlaps(
1437                    cd.getIndexDescriptor().baseColumnPositions())))
1438            { continue; }
1439
1440            if ( conglomVector != null )
1441            {
1442                int i;
1443                for (i = 0; i < distinctCount; i++)
1444                {
1445                    if (distinctConglomNums[i] == cd.getConglomerateNumber())
1446                        break;
1447                }
1448                if (i == distinctCount) // first appearence
1449
{
1450                    distinctConglomNums[distinctCount++] = cd.getConglomerateNumber();
1451                    conglomVector.addElement( cd );
1452                }
1453            }
1454
1455            IndexRowGenerator ixd = cd.getIndexDescriptor();
1456            int[] cols = ixd.baseColumnPositions();
1457
1458            if (colBitSet != null)
1459            {
1460                for (int i = 0; i < cols.length; i++)
1461                {
1462                    colBitSet.set(cols[i]);
1463                }
1464            } // end IF
1465
} // end loop through conglomerates
1466

1467    }
1468
1469    protected void markAffectedIndexes
1470    (
1471        Vector JavaDoc affectedConglomerates
1472    )
1473        throws StandardException
1474    {
1475        ConglomerateDescriptor cd;
1476        int indexCount = affectedConglomerates.size();
1477        CompilerContext cc = getCompilerContext();
1478
1479        indicesToMaintain = new IndexRowGenerator[ indexCount ];
1480        indexConglomerateNumbers = new long[ indexCount ];
1481        indexNames = new String JavaDoc[indexCount];
1482
1483        for ( int ictr = 0; ictr < indexCount; ictr++ )
1484        {
1485            cd = (ConglomerateDescriptor) affectedConglomerates.elementAt( ictr );
1486
1487            indicesToMaintain[ ictr ] = cd.getIndexDescriptor();
1488            indexConglomerateNumbers[ ictr ] = cd.getConglomerateNumber();
1489            indexNames[ictr] =
1490                ((cd.isConstraint()) ? null : cd.getConglomerateName());
1491
1492            cc.createDependency(cd);
1493        }
1494
1495    }
1496
1497
1498    public String JavaDoc statementToString()
1499    {
1500        return "DML MOD";
1501    }
1502
1503    /**
1504     * Remap referenced columns in the cd to reflect the
1505     * passed in row map.
1506     *
1507     * @param cd constraint descriptor
1508     * @param rowMap 1 based row map
1509     */

1510    private int[] remapReferencedColumns(ConstraintDescriptor cd, int[] rowMap)
1511    {
1512        int[] oldCols = cd.getReferencedColumns();
1513        if (rowMap == null)
1514        {
1515            return oldCols;
1516        }
1517
1518        int[] newCols = new int[oldCols.length];
1519        for (int i = 0; i<oldCols.length; i++)
1520        {
1521            newCols[i] = rowMap[oldCols[i]];
1522            if (SanityManager.DEBUG)
1523            {
1524                SanityManager.ASSERT(newCols[i] != 0, "attempt to map a column "+
1525                    oldCols[i]+" which is not in our new column map. Something is "+
1526                    "wrong with the logic to do partial reads for an update stmt");
1527            }
1528        }
1529        return newCols;
1530    }
1531
1532    /**
1533     * Get a integer based row map from a bit set.
1534     *
1535     * @param bitSet
1536     * @param td
1537     *
1538     */

1539    private int[] getRowMap(FormatableBitSet bitSet, TableDescriptor td)
1540        throws StandardException
1541    {
1542        if (bitSet == null)
1543        {
1544            return (int[])null;
1545        }
1546
1547        int size = td.getMaxColumnID();
1548        int[] iArray = new int[size+1];
1549        int j = 1;
1550        for (int i = 1; i <= size; i++)
1551        {
1552            if (bitSet.get(i))
1553            {
1554                iArray[i] = j++;
1555            }
1556        }
1557        return iArray;
1558    }
1559
1560
1561    public void setRefActionInfo(long fkIndexConglomId,
1562                                 int[]fkColArray,
1563                                 String JavaDoc parentResultSetId,
1564                                 boolean dependentScan)
1565    {
1566        resultSet.setRefActionInfo(fkIndexConglomId,
1567                                   fkColArray,
1568                                   parentResultSetId,
1569                                   dependentScan);
1570    }
1571
1572    /**
1573     * Normalize synonym column references to have the name of the base table.
1574     *
1575     * @param rcl The result column list of the target table
1576     * @param targetTableName The target tablename
1577     *
1578     * @exception StandardException Thrown on error
1579     */

1580    public void normalizeSynonymColumns(
1581    ResultColumnList rcl,
1582    TableName targetTableName)
1583        throws StandardException
1584    {
1585        if (synonymTableName == null)
1586            return;
1587        
1588        String JavaDoc synTableName = synonymTableName.getTableName();
1589        
1590        int count = rcl.size();
1591        for (int i = 0; i < count; i++)
1592        {
1593            ResultColumn column = (ResultColumn) rcl.elementAt(i);
1594            ColumnReference reference = column.getReference();
1595
1596            if ( reference != null )
1597            {
1598                String JavaDoc crTableName = reference.getTableName();
1599                if ( crTableName != null )
1600                {
1601                    if ( synTableName.equals( crTableName ) )
1602                    {
1603                        reference.setTableNameNode( targetTableName );
1604                    }
1605                    else
1606                    {
1607                        throw StandardException.newException(
1608                                SQLState.LANG_TABLE_NAME_MISMATCH,
1609                                synTableName,
1610                                crTableName);
1611                    }
1612                }
1613            }
1614        }
1615    }
1616}
1617
1618
1619
Popular Tags