001/* 002// This software is subject to the terms of the Eclipse Public License v1.0 003// Agreement, available at the following URL: 004// http://www.eclipse.org/legal/epl-v10.html. 005// You must accept the terms of that agreement to use this software. 006// 007// Copyright (C) 2006-2012 Pentaho and others 008// All Rights Reserved. 009*/ 010package mondrian.spi; 011 012import mondrian.olap.Util; 013import mondrian.util.ArraySortedSet; 014 015import java.io.Serializable; 016import java.util.SortedSet; 017 018 019/** 020 * Constrained columns are part of the SegmentHeader and SegmentCache. 021 * They uniquely identify a constrained column within a segment. 022 * Each segment can have many constrained columns. Each column can 023 * be constrained by multiple values at once (similar to a SQL in() 024 * predicate). 025 * 026 * <p>They are immutable and serializable. 027 */ 028public class SegmentColumn implements Serializable { 029 private static final long serialVersionUID = -5227838916517784720L; 030 public final String columnExpression; 031 public final int valueCount; 032 public final SortedSet<Comparable> values; 033 private final int hashCode; 034 035 /** 036 * Creates a SegmentColumn. 037 * 038 * @param columnExpression SQL expression for the column. Unique within the 039 * star schema, including accesses to the same physical column via 040 * different join paths. 041 * 042 * @param valueCount Number of distinct values of this column in the 043 * database. For these purposes, null is counted as a value. If there 044 * are N distinct values of the column, and we have a collection of 045 * segments that cover N values, then Mondrian assumes that it is safe 046 * to roll up. 047 * 048 * @param valueList List of values to constrain the 049 * column to, or null if unconstrained. Values must be 050 * {@link Comparable} and immutable. For example, Integer, Boolean, 051 * String or Double. 052 */ 053 public SegmentColumn( 054 String columnExpression, 055 int valueCount, 056 SortedSet<Comparable> valueList) 057 { 058 this.columnExpression = columnExpression; 059 this.valueCount = valueCount; 060 this.values = valueList; 061 this.hashCode = computeHashCode(); 062 } 063 064 private int computeHashCode() { 065 return Util.hash( 066 this.columnExpression.hashCode(), 067 this.values); 068 } 069 070 /** 071 * Merges this column with another 072 * resulting in another whose values are super set of both. 073 */ 074 public SegmentColumn merge(SegmentColumn col) { 075 assert col != null; 076 assert col.columnExpression.equals(this.columnExpression); 077 078 // If any values are wildcard, the merged result is a wildcard. 079 if (this.values == null || col.values == null) { 080 return new SegmentColumn( 081 columnExpression, 082 valueCount, 083 null); 084 } 085 086 return new SegmentColumn( 087 columnExpression, 088 valueCount, 089 ((ArraySortedSet) this.values).merge( 090 (ArraySortedSet) col.values)); 091 } 092 093 /** 094 * Returns the column expression of this constrained column. 095 * @return A column expression. 096 */ 097 public String getColumnExpression() { 098 return columnExpression; 099 } 100 101 /** 102 * Returns an array of predicate values for this column. 103 * @return An array of object values. 104 */ 105 public SortedSet<Comparable> getValues() { 106 return values; 107 } 108 109 @Override 110 public boolean equals(Object obj) { 111 if (!(obj instanceof SegmentColumn)) { 112 return false; 113 } 114 SegmentColumn that = (SegmentColumn) obj; 115 if (this.values == null && that.values == null) { 116 return true; 117 } 118 return this.columnExpression.equals(that.columnExpression) 119 && Util.equals(this.values, that.values); 120 } 121 122 @Override 123 public int hashCode() { 124 return hashCode; 125 } 126 127 /** 128 * Returns the number of distinct values that occur for this column in the 129 * database. 130 * 131 * <p>Mondrian uses this to know that it can safely combine multiple 132 * segments to roll up. For example, if for the "quarter" column, one 133 * segment has values {"Q1", "Q2"} and another has values {"Q3", "Q4"}, 134 * and Mondrian knows that there are 4 values, then it can roll up. 135 * 136 * <p>If this method returns a value that is too low, Mondrian may generate 137 * incorrect results. If you don't know the number of values, return -1.</p> 138 * 139 * @return Number of distinct values, including null, that occur for this 140 * column 141 */ 142 public int getValueCount() { 143 return valueCount; 144 } 145} 146 147// End SegmentColumn.java