📄 dmlmodstatementnode.java
字号:
* So, we goober up a SELECT * FROM table WHERE checkDefs. */ String select = "SELECT * FROM " + td.getQualifiedName() + " WHERE " + checkConstraintText; /* ** Get a new compiler context, so the parsing of the select statement ** doesn't mess up anything in the current context (it could clobber ** the ParameterValueSet, for example). */ CompilerContext newCC = lcc.pushCompilerContext(); p = newCC.getParser(); /* Finally, we can call the parser */ // Since this is always nested inside another SQL statement, so topLevel flag // should be false QueryTreeNode qt = p.parseStatement(select); if (SanityManager.DEBUG) { if (! (qt instanceof CursorNode)) { SanityManager.THROWASSERT( "qt expected to be instanceof CursorNode, not " + qt.getClass().getName()); } CursorNode cn = (CursorNode) qt; if (! (cn.getResultSetNode() instanceof SelectNode)) { SanityManager.THROWASSERT( "cn.getResultSetNode() expected to be instanceof SelectNode, not " + cn.getResultSetNode().getClass().getName()); } } checkTree = ((SelectNode) ((CursorNode) qt).getResultSetNode()).getWhereClause(); lcc.popCompilerContext(newCC); return checkTree; } /** * Generate the code to evaluate a tree of CHECK CONSTRAINTS. * * @param checkConstraints Bound query tree of ANDed check constraints. * @param generatedMethodName Name to give the generated method. If null, we will * generate a unique name. * @param ecb Expression Class Builder * @param executeEB Statement block of generated execute() method. * * * * @exception StandardException Thrown on error */ public void generateCheckConstraints ( ValueNode checkConstraints, ExpressionClassBuilder ecb, MethodBuilder mb ) throws StandardException { // for the check constraints, we generate an exprFun // that evaluates the expression of the clause // against the current row of the child's result. // if there are no check constraints, simply pass null // to optimize for run time performance. // generate the function and initializer: // Note: Boolean lets us return nulls (boolean would not) // private Boolean exprN() // { // return <<checkConstraints.generate(ps)>>; // } // static Method exprN = method pointer to exprN; // if there is no check constraint, we just want to pass null. if (checkConstraints == null) { mb.pushNull(ClassName.GeneratedMethod); } else { MethodBuilder userExprFun = generateCheckConstraints(checkConstraints, ecb); // check constraint is used in the final result set // as an access of the new static // field holding a reference to this new method. ecb.pushMethodReference(mb, userExprFun); } } /** * Generate a method to evaluate a tree of CHECK CONSTRAINTS. * * @param checkConstraints Bound query tree of ANDed check constraints. * @param ecb Expression Class Builder * * * * @exception StandardException Thrown on error */ public MethodBuilder generateCheckConstraints ( ValueNode checkConstraints, ExpressionClassBuilder ecb ) throws StandardException { // this sets up the method and the static field. // generates: // java.lang.Object userExprFun { } MethodBuilder userExprFun = ecb.newUserExprFun(); // check constraint knows it is returning its value; /* generates: * return <checkExpress.generate(ecb)>; * and adds it to userExprFun */ checkConstraints.generateExpression(ecb, userExprFun); userExprFun.methodReturn(); // we are done modifying userExprFun, complete it. userExprFun.complete(); return userExprFun; } /** * Generate an optimized QueryTree from a bound QueryTree. Actually, * it can annotate the tree in place rather than generate a new tree, * but this interface allows the root node of the optimized QueryTree * to be different from the root node of the bound QueryTree. * * For non-optimizable statements, this method is a no-op. * * Throws an exception if the tree is not bound, or if the binding * is out of date. * * @return An optimized QueryTree * * @exception StandardException Thrown on failure */ public QueryTreeNode optimize() throws StandardException { ResultSetNode originalRSNode = getResultSetNode(); /* First optimize the query */ QueryTreeNode retval = super.optimize(); /* In language we always set it to row lock, it's up to store to * upgrade it to table lock. This makes sense for the default read * committed isolation level and update lock. For more detail, see * Beetle 4133. */ lockMode = TransactionController.MODE_RECORD; return retval; } /** * Get the list of indexes that must be updated by this DML statement. * WARNING: As a side effect, it creates dependencies on those indexes. * * @param td The table descriptor for the table being updated * @param updatedColumns The updated column list. If not update, null * @param colBitSet a 1 based bit set of the columns in the list * * @exception StandardException Thrown on error */ protected void getAffectedIndexes ( TableDescriptor td, ResultColumnList updatedColumns, FormatableBitSet colBitSet ) throws StandardException { Vector conglomVector = new Vector(); DMLModStatementNode.getXAffectedIndexes(td, updatedColumns, colBitSet, conglomVector ); markAffectedIndexes( conglomVector ); } /** * Marks which indexes are affected by an UPDATE of the * desired shape. * * Is passed a list of updated columns. Does the following: * * 1) finds all indices which overlap the updated columns * 2) adds the index columns to a bitmap of affected columns * 3) adds the index descriptors to a list of conglomerate * descriptors. * * @param updatedColumns a list of updated columns * @param colBitSet OUT: evolving bitmap of affected columns * @param conglomVector OUT: vector of affected indices * * @exception StandardException Thrown on error */ static void getXAffectedIndexes ( TableDescriptor baseTable, ResultColumnList updatedColumns, FormatableBitSet colBitSet, Vector conglomVector ) throws StandardException { ConglomerateDescriptor[] cds = baseTable.getConglomerateDescriptors(); /* we only get distinct conglomerate numbers. If duplicate indexes * share one conglomerate, we only return one number. */ long[] distinctConglomNums = new long[cds.length - 1]; int distinctCount = 0; for (int index = 0; index < cds.length; index++) { ConglomerateDescriptor cd = cds[index]; if (!cd.isIndex()) { continue; } /* ** If this index doesn't contain any updated ** columns, then we can skip it. */ if ((updatedColumns != null) && (!updatedColumns.updateOverlaps( cd.getIndexDescriptor().baseColumnPositions()))) { continue; } if ( conglomVector != null ) { int i; for (i = 0; i < distinctCount; i++) { if (distinctConglomNums[i] == cd.getConglomerateNumber()) break; } if (i == distinctCount) // first appearence { distinctConglomNums[distinctCount++] = cd.getConglomerateNumber(); conglomVector.addElement( cd ); } } IndexRowGenerator ixd = cd.getIndexDescriptor(); int[] cols = ixd.baseColumnPositions(); if (colBitSet != null) { for (int i = 0; i < cols.length; i++) { colBitSet.set(cols[i]); } } // end IF } // end loop through conglomerates } protected void markAffectedIndexes ( Vector affectedConglomerates ) throws StandardException { ConglomerateDescriptor cd; int indexCount = affectedConglomerates.size(); CompilerContext cc = getCompilerContext(); indicesToMaintain = new IndexRowGenerator[ indexCount ]; indexConglomerateNumbers = new long[ indexCount ]; indexNames = new String[indexCount]; for ( int ictr = 0; ictr < indexCount; ictr++ ) { cd = (ConglomerateDescriptor) affectedConglomerates.elementAt( ictr ); indicesToMaintain[ ictr ] = cd.getIndexDescriptor(); indexConglomerateNumbers[ ictr ] = cd.getConglomerateNumber(); indexNames[ictr] = ((cd.isConstraint()) ? null : cd.getConglomerateName()); /* ** This is a nasty hack to deal with the fact that ** some testing wind up calling this method w/o ** going through the normal setup -- so there is ** no connection context. So, in the debug codeline, ** we'll skip setting the dependency if isn't on ** in the compilation context. */ if (SanityManager.DEBUG) { if (cc.getCurrentDependent() != null) { cc.createDependency(cd); } } else { cc.createDependency(cd); } } } public String statementToString() { return "DML MOD"; } /** * Remap referenced columns in the cd to reflect the * passed in row map. * * @param cd constraint descriptor * @param rowMap 1 based row map */ private int[] remapReferencedColumns(ConstraintDescriptor cd, int[] rowMap) { int[] oldCols = cd.getReferencedColumns(); if (rowMap == null) { return oldCols; } int[] newCols = new int[oldCols.length]; for (int i = 0; i<oldCols.length; i++) { newCols[i] = rowMap[oldCols[i]]; if (SanityManager.DEBUG) { SanityManager.ASSERT(newCols[i] != 0, "attempt to map a column "+ oldCols[i]+" which is not in our new column map. Something is "+ "wrong with the logic to do partial reads for an update stmt"); } } return newCols; } /** * Get a integer based row map from a bit set. * * @param bitSet * @param td * */ private int[] getRowMap(FormatableBitSet bitSet, TableDescriptor td) throws StandardException { if (bitSet == null) { return (int[])null; } int size = td.getMaxColumnID(); int[] iArray = new int[size+1]; int j = 1; for (int i = 1; i <= size; i++) { if (bitSet.get(i)) { iArray[i] = j++; } } return iArray; } public void setRefActionInfo(long fkIndexConglomId, int[]fkColArray, String parentResultSetId, boolean dependentScan) { resultSet.setRefActionInfo(fkIndexConglomId, fkColArray, parentResultSetId, dependentScan); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -