📄 fromvti.java
字号:
* If version2 is true, then it must implement PreparedStatement, otherwise * it can implement either PreparedStatement or ResultSet. (We check for * PreparedStatement first.) */ if (!newInvocation.assignableTo("java.sql.PreparedStatement")) { if (version2) { throw StandardException.newException(SQLState.LANG_DOES_NOT_IMPLEMENT, getVTIName(), "java.sql.PreparedStatement"); } else if (! newInvocation.assignableTo("java.sql.ResultSet")) { throw StandardException.newException(SQLState.LANG_DOES_NOT_IMPLEMENT, getVTIName(), "java.sql.ResultSet"); } } else { version2 = true; } /* If this is a version 2 VTI */ if (version2) { // Does it support predicates implementsPushable = newInvocation.assignableTo("org.apache.derby.vti.IQualifyable"); } // Remember whether or not the VTI implements the VTICosting interface implementsVTICosting = newInvocation.assignableTo(ClassName.VTICosting); // Is the parameter list to the constructor valid for a VTI? methodParms = newInvocation.getMethodParms(); /* Build the RCL for this VTI. We instantiate an object in order * to get the ResultSetMetaData. * * If we have a special trigger vti, then we branch off and get * its rcl from the trigger table that is waiting for us in * the compiler context. */ UUID triggerTableId; if ((triggerTableId = getSpecialTriggerVTITableName(lcc, newInvocation.getJavaClassName())) != null) { TableDescriptor td = getDataDictionary().getTableDescriptor(triggerTableId); resultColumns = genResultColList(td); // costing info vtiCosted = true; estimatedCost = 50d; estimatedRowCount = 5d; supportsMultipleInstantiations = true; } else { ResultSetMetaData rsmd = getResultSetMetaData(); /* Wouldn't it be nice if we knew that the class/object would never * return a null ResultSetMetaData. */ if (rsmd == null) { throw StandardException.newException(SQLState.LANG_NULL_RESULT_SET_META_DATA, getVTIName()); } // Remember how many columns VTI returns for partial row calculation try { numVTICols = rsmd.getColumnCount(); } catch (SQLException sqle) { numVTICols = 0; } try { for( int i = 1; i <= numVTICols; i++) { int columnType = rsmd.getColumnType(i); if( columnType == Types.BLOB || columnType == Types.CLOB) throw StandardException.newException(SQLState.LANG_VTI_BLOB_CLOB_UNSUPPORTED, getVTIName(), rsmd.getColumnName( i)); } } catch( SQLException sqle) { throw StandardException.unexpectedUserException(sqle); } resultColumns = (ResultColumnList) getNodeFactory().getNode( C_NodeTypes.RESULT_COLUMN_LIST, getContextManager()); resultColumns.createListFromResultSetMetaData(rsmd, exposedName, newInvocation.getJavaClassName()); } numVTICols = resultColumns.size(); /* Propagate the name info from the derived column list */ if (derivedRCL != null) { resultColumns.propagateDCLInfo(derivedRCL, correlationName); } return this; } /** * Get the ResultSetMetaData for the class/object. We first look for * the optional static method which has the same signature as the constructor. * If it doesn't exist, then we instantiate an object and get the ResultSetMetaData * from that object. * * @return The ResultSetMetaData from the class/object. * * @exception StandardException Thrown on error */ public ResultSetMetaData getResultSetMetaData() throws StandardException { // Get the actual ResultSetMetaData rsmd = null; try { if (version2) { ps = (PreparedStatement) getNewInstance(); if (ps.getResultSetConcurrency() != JDBC20Translation.CONCUR_UPDATABLE) { throw StandardException.newException(SQLState.LANG_UPDATABLE_VTI_NON_UPDATABLE_RS, getVTIName()); } rsmd = ps.getMetaData(); controlsDeferral = (ps instanceof DeferModification); /* See if the result set is known to be insensitive or not. * * Some older VTI implementations do not implement getResultSetType(). UpdatableVTITemplate * does not implement it at all. UpdatableVTITemplate.getResultSetType throws an * exception. In either of these cases make the conservative assumption that the result set is sensitive. */ try { resultSetType = ps.getResultSetType(); } catch( SQLException sqle){} catch( java.lang.AbstractMethodError ame){} catch( java.lang.NoSuchMethodError nsme){} isInsensitive = (resultSetType == ResultSet.TYPE_SCROLL_INSENSITIVE); if (!implementsVTICosting) { ps.close(); ps = null; } } else { rs = (ResultSet) getNewInstance(); rsmd = rs.getMetaData(); if (!implementsVTICosting) { rs.close(); rs = null; } } } catch(Throwable t) { throw StandardException.unexpectedUserException(t); } return rsmd; } private Object getNewInstance() throws StandardException { Class[] paramTypeClasses = newInvocation.getMethodParameterClasses(); Object[] paramObjects = null; if (paramTypeClasses != null) { paramObjects = new Object[paramTypeClasses.length]; for (int index = 0; index < paramTypeClasses.length; index++) { Class paramClass = paramTypeClasses[index]; paramObjects[index] = methodParms[index].getConstantValueAsObject(); // As-per the JDBC spec SMALLINT and TINYINT map to java.lang.Integer // as objects. This means if getConstantValueAsObject() has returned an // Integer obejct in these cases, whereas Java method calling requires // Short or Byte object. if ((paramObjects[index] != null) && paramClass.isPrimitive()) { if (paramClass.equals(Short.TYPE)) { paramObjects[index] = new Short(((Integer) paramObjects[index]).shortValue()); } else if (paramClass.equals(Byte.TYPE)) { paramObjects[index] = new Byte(((Integer) paramObjects[index]).byteValue()); } } // Pass defaults for unknown primitive values if (paramObjects[index] == null && paramClass.isPrimitive()) { if (paramClass.equals(Integer.TYPE)) { paramObjects[index] = new Integer(0); } else if (paramClass.equals(Short.TYPE)) { paramObjects[index] = new Short((short) 0); } else if (paramClass.equals(Byte.TYPE)) { paramObjects[index] = new Byte((byte) 0); } else if (paramClass.equals(Long.TYPE)) { paramObjects[index] = new Long((long) 0); } else if (paramClass.equals(Float.TYPE)) { paramObjects[index] = new Float((float) 0); } else if (paramClass.equals(Double.TYPE)) { paramObjects[index] = new Double((double) 0); } else if (paramClass.equals(Boolean.TYPE)) { paramObjects[index] = Boolean.FALSE; } else if (paramClass.equals(Character.TYPE)) { paramObjects[index] = new Character(Character.MIN_VALUE); } } } } else { paramTypeClasses = new Class[0]; paramObjects = new Object[0]; } try { ClassInspector classInspector = getClassFactory().getClassInspector(); String javaClassName = newInvocation.getJavaClassName(); Constructor constructor = classInspector.getClass(javaClassName).getConstructor(paramTypeClasses); return constructor.newInstance(paramObjects); } catch(Throwable t) { if( t instanceof InvocationTargetException) { InvocationTargetException ite = (InvocationTargetException) t; Throwable wrappedThrowable = ite.getTargetException(); if( wrappedThrowable instanceof StandardException) throw (StandardException) wrappedThrowable; } throw StandardException.unexpectedUserException(t); } } // end of getNewInstance /** * Get the DeferModification interface associated with this VTI * * @return null if the VTI uses the default modification deferral */ public DeferModification getDeferralControl( ) throws StandardException { if( ! controlsDeferral) return null; try { return (DeferModification) getNewInstance(); } catch(Throwable t) { throw StandardException.unexpectedUserException(t); } } // end of getDeferralControl /** * @return the ResultSet type of the VTI, TYPE_FORWARD_ONLY if the getResultSetType() method * of the VTI class throws an exception. */ public int getResultSetType() { return resultSetType; } /** * Bind the expressions in this VTI. This means * binding the sub-expressions, as well as figuring out what the return * type is for each expression. * * @param typeCompilationFactory The factory to get DataTypeServices * from, if necessary. * @return Nothing * * @exception StandardException Thrown on error */ public void bindExpressions(FromList fromListParam) throws StandardException { ResultColumnList derivedRCL = resultColumns; /* Figure out if the VTIs parameters are QUERY_INVARIANT. If so, * then the VTI is a candidate for materialization at execution time * if it is the inner table of a join or in a subquery. */ materializable = newInvocation.areParametersQueryInvariant(); /* NOTE: We need to rebind any ColumnReferences that are parameters and are * from other VTIs that appear after this one in the FROM list. * These CRs will have uninitialized column and table numbers. */ Vector colRefs = getNodesFromParameters(ColumnReference.class); Vector aggregateVector = null; for (Enumeration e = colRefs.elements(); e.hasMoreElements(); ) { ColumnReference ref = (ColumnReference)e.nextElement(); // Rebind the CR if the tableNumber is uninitialized if (ref.getTableNumber() == -1) { // we need a fake agg list if (aggregateVector == null) { aggregateVector = new Vector(); } ref.bindExpression(fromListParam, subqueryList, aggregateVector); } } } /** * Get all of the nodes of the specified class * from the parameters to this VTI. * * @param nodeClass The Class of interest. * * @return A vector containing all of the nodes of interest. * * @exception StandardException Thrown on error */ Vector getNodesFromParameters(Class nodeClass) throws StandardException { CollectNodesVisitor getCRs = new CollectNodesVisitor(nodeClass); newInvocation.accept(getCRs); return getCRs.getList(); } /** * Expand a "*" into a ResultColumnList with all of the * result columns from the subquery. * @exception StandardException Thrown on error */ public ResultColumnList getAllResultColumns(TableName allTableName) throws StandardException { ResultColumnList rcList = null; ResultColumn resultColumn; ValueNode valueNode; String columnName; TableName toCompare; if(allTableName != null) toCompare = makeTableName(allTableName.getSchemaName(),correlationName); else toCompare = makeTableName(null,correlationName); if ( allTableName != null && ! allTableName.equals(toCompare)) { return null; } rcList = (ResultColumnList) getNodeFactory().getNode( C_NodeTypes.RESULT_COLUMN_LIST, getContextManager()); /* Build a new result column list based off of resultColumns. * NOTE: This method will capture any column renaming due to * a derived column list. */ int rclSize = resultColumns.size(); for (int index = 0; index < rclSize; index++) { resultColumn = (ResultColumn) resultColumns.elementAt(index); if (resultColumn.isGenerated()) { continue; } // Build a ResultColumn/ColumnReference pair for the column // columnName = resultColumn.getName(); valueNode = (ValueNode) getNodeFactory().getNode( C_NodeTypes.COLUMN_REFERENCE, columnName, exposedName, getContextManager()); resultColumn = (ResultColumn) getNodeFactory().getNode( C_NodeTypes.RESULT_COLUMN, columnName, valueNode, getContextManager()); // Build the ResultColumnList to return // rcList.addResultColumn(resultColumn); } return rcList; } /** * Try to find a ResultColumn in the table represented by this FromBaseTable * that matches the name in the given ColumnReference. * * @param columnReference The columnReference whose name we're looking * for in the given table. * * @return A ResultColumn whose expression is the ColumnNode * that matches the ColumnReference. * Returns null if there is no match. * * @exception StandardException Thrown on error */ public ResultColumn getMatchingColumn(ColumnReference columnReference) throws StandardException { /* We could get called before our RCL is built. That's okay, we'll * just say that we don't match. */ if (resultColumns == null) { return null; } ResultColumn resultColumn = null; TableName columnsTableName; TableName exposedTableName; columnsTableName = columnReference.getTableNameNode(); /* ** If the column did not specify a name, or the specified name ** matches the table we're looking at, see whether the column ** is in this table. */ if (columnsTableName == null || columnsTableName.equals(exposedName)) { resultColumn = resultColumns.getResultColumn(columnReference.getColumnName()); /* Did we find a match? */ if (resultColumn != null) { columnReference.setTableNumber(tableNumber); } } return resultColumn; } /** * Preprocess a ResultSetNode - this currently means: * o Generating a referenced table map for each ResultSetNode. * o Putting the WHERE and HAVING clauses in conjunctive normal form (CNF). * o Converting the WHERE and HAVING clauses into PredicateLists and * classifying them. * o Ensuring that a ProjectRestrictNode is generated on top of every * FromBaseTable and generated in place of every FromSubquery. * o Pushing single table predicates down to the new ProjectRestrictNodes. * * @param numTables The number of tables in the DML Statement * @param gbl The group by list, if any * @param fromList The from list, if any * * @return ResultSetNode at top of preprocessed tree. * * @exception StandardException Thrown on error */ public ResultSetNode preprocess(int numTables, GroupByList gbl, FromList fromList) throws StandardException { newInvocation.preprocess( numTables, (FromList) getNodeFactory().getNode( C_NodeTypes.FROM_LIST,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -