/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to you under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.eigenbase.rel; import java.util.*; import org.eigenbase.rel.metadata.*; import org.eigenbase.relopt.*; import org.eigenbase.reltype.*; import org.eigenbase.rex.*; import org.eigenbase.sql.*; import org.eigenbase.sql.type.*; import org.eigenbase.util.Pair; import net.hydromatic.linq4j.function.Function1; import net.hydromatic.linq4j.function.Functions; /** * <code>ValuesRelBase</code> is an abstract base class for implementations of * {@link ValuesRel}. */ public abstract class ValuesRelBase extends AbstractRelNode { /** * Lambda that helps render tuples as strings. */ private static final Function1<List<RexLiteral>, Object> F = new Function1<List<RexLiteral>, Object>() { public Object apply(List<RexLiteral> tuple) { String s = tuple.toString(); assert s.startsWith("["); assert s.endsWith("]"); return "{ " + s.substring(1, s.length() - 1) + " }"; } }; //~ Instance fields -------------------------------------------------------- protected final List<List<RexLiteral>> tuples; //~ Constructors ----------------------------------------------------------- /** * Creates a new ValuesRelBase. Note that tuples passed in become owned by * this rel (without a deep copy), so caller must not modify them after this * call, otherwise bad things will happen. * * @param cluster . * @param rowType row type for tuples produced by this rel * @param tuples 2-dimensional array of tuple values to be produced; outer * list contains tuples; each inner list is one tuple; all * tuples must be of same length, conforming to rowType */ protected ValuesRelBase( RelOptCluster cluster, RelDataType rowType, List<List<RexLiteral>> tuples, RelTraitSet traits) { super(cluster, traits); this.rowType = rowType; this.tuples = tuples; assert assertRowType(); } /** * Creates a ValuesRelBase by parsing serialized output. */ public ValuesRelBase(RelInput input) { this( input.getCluster(), input.getRowType("type"), input.getTuples("tuples"), input.getTraitSet()); } //~ Methods ---------------------------------------------------------------- public List<List<RexLiteral>> getTuples(RelInput input) { return input.getTuples("tuples"); } /** * @return rows of literals represented by this rel */ public List<List<RexLiteral>> getTuples() { return tuples; } /** * @return true if all tuples match rowType; otherwise, assert on mismatch */ private boolean assertRowType() { for (List<RexLiteral> tuple : tuples) { assert tuple.size() == rowType.getFieldCount(); for (Pair<RexLiteral, RelDataTypeField> pair : Pair.zip(tuple, rowType.getFieldList())) { RexLiteral literal = pair.left; RelDataType fieldType = pair.right.getType(); // TODO jvs 19-Feb-2006: strengthen this a bit. For example, // overflow, rounding, and padding/truncation must already have // been dealt with. if (!RexLiteral.isNullLiteral(literal)) { assert SqlTypeUtil.canAssignFrom(fieldType, literal.getType()) : "to " + fieldType + " from " + literal; } } } return true; } // implement RelNode protected RelDataType deriveRowType() { return rowType; } // implement RelNode public RelOptCost computeSelfCost(RelOptPlanner planner) { double dRows = RelMetadataQuery.getRowCount(this); // Assume CPU is negligible since values are precomputed. double dCpu = 1; double dIo = 0; return planner.getCostFactory().makeCost(dRows, dCpu, dIo); } // implement RelNode public double getRows() { return tuples.size(); } // implement RelNode public RelWriter explainTerms(RelWriter pw) { // A little adapter just to get the tuples to come out // with curly brackets instead of square brackets. Plus // more whitespace for readability. return super.explainTerms(pw) // For rel digest, include the row type since a rendered // literal may leave the type ambiguous (e.g. "null"). .itemIf( "type", rowType, pw.getDetailLevel() == SqlExplainLevel.DIGEST_ATTRIBUTES) .itemIf( "type", rowType.getFieldList(), pw.nest()) .itemIf("tuples", Functions.adapt(tuples, F), !pw.nest()) .itemIf("tuples", tuples, pw.nest()); } } // End ValuesRelBase.java