001 /* 002 // $Id: //open/mondrian/src/main/mondrian/rolap/agg/DrillThroughQuerySpec.java#14 $ 003 // This software is subject to the terms of the Common Public License 004 // Agreement, available at the following URL: 005 // http://www.opensource.org/licenses/cpl.html. 006 // Copyright (C) 2005-2008 Julian Hyde 007 // All Rights Reserved. 008 // You must accept the terms of that agreement to use this software. 009 */ 010 011 package mondrian.rolap.agg; 012 013 import mondrian.olap.Util; 014 import mondrian.olap.MondrianDef; 015 import mondrian.rolap.RolapStar; 016 import mondrian.rolap.StarColumnPredicate; 017 import mondrian.rolap.sql.SqlQuery; 018 import java.util.ArrayList; 019 import java.util.List; 020 import java.util.HashSet; 021 import java.util.Set; 022 023 /** 024 * Provides the information necessary to generate SQL for a drill-through 025 * request. 026 * 027 * @author jhyde 028 * @author Richard M. Emberson 029 * @version $Id: //open/mondrian/src/main/mondrian/rolap/agg/DrillThroughQuerySpec.java#14 $ 030 */ 031 class DrillThroughQuerySpec extends AbstractQuerySpec { 032 private final CellRequest request; 033 private final List<String> columnNames; 034 private final int maxColumnNameLength; 035 036 public DrillThroughQuerySpec(CellRequest request, boolean countOnly) { 037 super(request.getMeasure().getStar(), countOnly); 038 this.request = request; 039 int tmpMaxColumnNameLength = 040 getStar().getSqlQueryDialect().getMaxColumnNameLength(); 041 if (tmpMaxColumnNameLength == 0) { 042 // From java.sql.DatabaseMetaData: "a result of zero means that 043 // there is no limit or the limit is not known" 044 maxColumnNameLength = Integer.MAX_VALUE; 045 } else { 046 maxColumnNameLength = tmpMaxColumnNameLength; 047 } 048 this.columnNames = computeDistinctColumnNames(); 049 } 050 051 private List<String> computeDistinctColumnNames() { 052 final List<String> columnNames = new ArrayList<String>(); 053 final Set<String> columnNameSet = new HashSet<String>(); 054 055 final RolapStar.Column[] columns = getColumns(); 056 for (RolapStar.Column column : columns) { 057 addColumnName(column, columnNames, columnNameSet); 058 } 059 060 addColumnName(request.getMeasure(), columnNames, columnNameSet); 061 062 return columnNames; 063 } 064 065 private void addColumnName( 066 final RolapStar.Column column, 067 final List<String> columnNames, 068 final Set<String> columnNameSet) 069 { 070 String columnName = column.getName(); 071 if (columnName != null) { 072 // nothing 073 } else if (column.getExpression() instanceof MondrianDef.Column) { 074 columnName = ((MondrianDef.Column) column.getExpression()).name; 075 } else { 076 columnName = "c" + Integer.toString(columnNames.size()); 077 } 078 // Register the column name, and if it's not unique, append numeric 079 // suffixes until it is. Also make sure that it is within the 080 // range allowed by this SQL dialect. 081 String originalColumnName = columnName; 082 if (columnName.length() > maxColumnNameLength) { 083 columnName = columnName.substring(0, maxColumnNameLength); 084 } 085 for (int j = 0; !columnNameSet.add(columnName); j++) { 086 final String suffix = "_" + Integer.toString(j); 087 columnName = originalColumnName; 088 if (originalColumnName.length() + suffix.length() 089 > maxColumnNameLength) { 090 columnName = 091 originalColumnName.substring( 092 0, maxColumnNameLength - suffix.length()); 093 } 094 columnName += suffix; 095 } 096 columnNames.add(columnName); 097 } 098 099 public int getMeasureCount() { 100 return 1; 101 } 102 103 public RolapStar.Measure getMeasure(final int i) { 104 Util.assertTrue(i == 0); 105 return request.getMeasure(); 106 } 107 108 public String getMeasureAlias(final int i) { 109 Util.assertTrue(i == 0); 110 return columnNames.get(columnNames.size() - 1); 111 } 112 113 public RolapStar.Column[] getColumns() { 114 return request.getConstrainedColumns(); 115 } 116 117 public String getColumnAlias(final int i) { 118 return columnNames.get(i); 119 } 120 121 public StarColumnPredicate getColumnPredicate(final int i) { 122 final StarColumnPredicate constr = request.getValueList().get(i); 123 return (constr == null) 124 ? LiteralStarPredicate.TRUE 125 : constr; 126 } 127 128 public String generateSqlQuery() { 129 SqlQuery sqlQuery = newSqlQuery(); 130 nonDistinctGenerateSql(sqlQuery); 131 return sqlQuery.toString(); 132 } 133 134 protected void addMeasure(final int i, final SqlQuery sqlQuery) { 135 RolapStar.Measure measure = getMeasure(i); 136 137 Util.assertTrue(measure.getTable() == getStar().getFactTable()); 138 measure.getTable().addToFrom(sqlQuery, false, true); 139 140 String expr = measure.generateExprString(sqlQuery); 141 sqlQuery.addSelect(expr, getMeasureAlias(i)); 142 } 143 144 protected boolean isAggregate() { 145 return false; 146 } 147 148 protected boolean isOrdered() { 149 return true; 150 } 151 } 152 153 // End DrillThroughQuerySpec.java