/** * This function prepares the from-clause for use by the planner to generate an actual execution * plan from the clause. This includes several important tasks: * * <ul> * <li>The schema of the from-clause's output is determined. * <li>If the from-clause is a join, and the join specifies <tt>NATURAL</tt>, <tt>USING (col, * ...)</tt>, or an <tt>ON</tt> clause, the join condition is determined * </ul> * * <p>Since a from-clause can be a SQL subquery or a join expression, it should be evident that * the method will recursively prepare its children as well. * * <p><b>This method really shouldn't be called directly.</b> Instead, the enclosing {@link * SelectClause} will calls this method when the clause's {@link SelectClause#computeSchema} * method is invoked. * * @return the schema of the from-clause's output * @throws IOException if a table's schema cannot be loaded, or some other IO issue occurs. */ public Schema prepare() throws IOException { Schema result = null; switch (clauseType) { case BASE_TABLE: logger.debug("Preparing BASE_TABLE from-clause."); TableFileInfo tblFileInfo = StorageManager.getInstance().openTable(tableName); result = tblFileInfo.getSchema(); if (aliasName != null) { // Make a copy of the result schema and change the table names. result = new Schema(result); result.setTableName(aliasName); } break; case SELECT_SUBQUERY: logger.debug("Preparing SELECT_SUBQUERY from-clause."); result = derivedTable.computeSchema(); assert aliasName != null; // Make a copy of the result schema and change the table names. result = new Schema(result); result.setTableName(aliasName); break; case JOIN_EXPR: logger.debug("Preparing JOIN_EXPR from-clause. Condition type = " + condType); result = new Schema(); Schema leftSchema = leftChild.prepare(); Schema rightSchema = rightChild.prepare(); // Depending on the join type, we might eliminate duplicate column // names. if (condType == JoinConditionType.NATURAL_JOIN) { // Make sure that each side of the join doesn't have any // duplicate column names. (A schema can have columns with the // same name, but from different table names. This is not // allowed for natural joins.) if (leftSchema.hasMultipleColumnsWithSameName()) { throw new SchemaNameException( "Natural join error: " + "left child table has multiple columns with same " + "column name"); } if (rightSchema.hasMultipleColumnsWithSameName()) { throw new SchemaNameException( "Natural join error: " + "right child table has multiple columns with same " + "column name"); } Set<String> commonCols = leftSchema.getCommonColumnNames(rightSchema); if (commonCols.isEmpty()) { // TODO: According to the SQL99 standard, this shouldn't // generate an error. throw new SchemaNameException( "Natural join error: " + "child tables share no common column names!"); } buildJoinSchema("Natural join", leftSchema, rightSchema, commonCols, result); } else if (condType == JoinConditionType.JOIN_USING) { LinkedHashSet<String> commonCols = new LinkedHashSet<String>(); for (String name : joinUsingNames) { if (!commonCols.add(name)) { throw new SchemaNameException( "Column name " + name + " was specified multiple times in USING clause"); } } buildJoinSchema("Join USING", leftSchema, rightSchema, commonCols, result); } else { // This join condition-type doesn't alter the result schema. // Just lump together the result schemas. result.append(leftSchema); result.append(rightSchema); preparedJoinExpr = joinOnExpr; } } // Don't need to do any schema validation in this function, since all the // validation takes place in the SELECT clause schema-computation code. preparedSchema = result; return result; }
/** * Initialize the tuple-remover object with the details it needs to delete tuples from the * specified table. * * @param tblFileInfo details of the table that will be modified */ public TupleRemover(TableFileInfo tblFileInfo) { this.tblFileInfo = tblFileInfo; this.tableMgr = tblFileInfo.getTableManager(); this.eventDispatch = EventDispatcher.getInstance(); }