Search in sources :

Example 1 with Pair

use of mondrian.util.Pair in project pentaho-platform by pentaho.

the class MDXBaseComponent method getConnection.

protected IPentahoConnection getConnection() {
    // first attempt to get the connection metadata from the catalog service. if that is not successful,
    // get the connection using the original approach.
    MdxConnectionAction connAction = (MdxConnectionAction) getActionDefinition();
    String catalogName = connAction.getCatalog().getStringValue();
    IMondrianCatalogService mondrianCatalogService = // $NON-NLS-1$
    PentahoSystem.get(IMondrianCatalogService.class, "IMondrianCatalogService", PentahoSessionHolder.getSession());
    MondrianCatalog catalog = mondrianCatalogService.getCatalog(catalogName, PentahoSessionHolder.getSession());
    if (catalog == null) {
        return getConnectionOrig();
    }
    Util.PropertyList connectProperties = Util.parseConnectString(catalog.getDataSourceInfo());
    Properties properties = new Properties();
    Iterator<Pair<String, String>> iter = connectProperties.iterator();
    while (iter.hasNext()) {
        Pair<String, String> pair = iter.next();
        properties.put(pair.getKey(), pair.getValue());
    }
    properties.put("Catalog", catalog.getDefinition());
    properties.put("Provider", "mondrian");
    properties.put("PoolNeeded", "false");
    properties.put(RolapConnectionProperties.Locale.name(), LocaleHelper.getLocale().toString());
    debug("Mondrian Connection Properties: " + properties.toString());
    MDXConnection mdxConnection = (MDXConnection) PentahoConnectionFactory.getConnection(IPentahoConnection.MDX_DATASOURCE, properties, PentahoSessionHolder.getSession(), this);
    if (connAction != null) {
        if ((connAction.getExtendedColumnNames() != ActionInputConstant.NULL_INPUT)) {
            mdxConnection.setUseExtendedColumnNames(connAction.getExtendedColumnNames().getBooleanValue());
        }
    }
    return mdxConnection;
}
Also used : MDXConnection(org.pentaho.platform.plugin.services.connections.mondrian.MDXConnection) MondrianCatalog(org.pentaho.platform.plugin.action.mondrian.catalog.MondrianCatalog) TemplateUtil(org.pentaho.platform.engine.services.runtime.TemplateUtil) Util(mondrian.olap.Util) MdxConnectionAction(org.pentaho.actionsequence.dom.actions.MdxConnectionAction) IMondrianCatalogService(org.pentaho.platform.plugin.action.mondrian.catalog.IMondrianCatalogService) RolapConnectionProperties(mondrian.rolap.RolapConnectionProperties) Properties(java.util.Properties) Pair(mondrian.util.Pair)

Example 2 with Pair

use of mondrian.util.Pair in project pentaho-platform by pentaho.

the class MondrianModelComponent method getInitialQuery.

public static String getInitialQuery(final Properties properties, final String cubeName, IPentahoSession session) throws Throwable {
    // Apply any properties for this catalog specified in datasource.xml
    IMondrianCatalogService mondrianCatalogService = PentahoSystem.get(IMondrianCatalogService.class, "IMondrianCatalogService", PentahoSessionHolder.getSession());
    List<MondrianCatalog> catalogs = mondrianCatalogService.listCatalogs(PentahoSessionHolder.getSession(), true);
    String propCat = properties.getProperty(RolapConnectionProperties.Catalog.name());
    for (MondrianCatalog cat : catalogs) {
        if (cat.getDefinition().equalsIgnoreCase(propCat)) {
            Util.PropertyList connectProperties = Util.parseConnectString(cat.getDataSourceInfo());
            Iterator<Pair<String, String>> iter = connectProperties.iterator();
            while (iter.hasNext()) {
                Pair<String, String> pair = iter.next();
                if (// Only set if not set already
                !properties.containsKey(pair.getKey())) {
                    properties.put(pair.getKey(), pair.getValue());
                }
            }
            break;
        }
    }
    MDXConnection mdxConnection = (MDXConnection) PentahoConnectionFactory.getConnection(IPentahoConnection.MDX_DATASOURCE, properties, session, null);
    // mdxConnection.setProperties( properties );
    Connection connection = mdxConnection.getConnection();
    if (connection == null) {
        Logger.error("MondrianModelComponent", Messages.getInstance().getErrorString("MondrianModel.ERROR_0001_INVALID_CONNECTION", // $NON-NLS-1$ //$NON-NLS-2$
        properties.toString()));
        return null;
    }
    try {
        return MondrianModelComponent.getInitialQuery(connection, cubeName);
    } catch (Throwable t) {
        if (t instanceof MondrianException) {
            // pull the cause out, otherwise it never gets logged
            Throwable cause = ((MondrianException) t).getCause();
            if (cause != null) {
                throw cause;
            } else {
                throw t;
            }
        } else {
            throw t;
        }
    }
}
Also used : MondrianCatalog(org.pentaho.platform.plugin.action.mondrian.catalog.MondrianCatalog) SQLConnection(org.pentaho.platform.plugin.services.connections.sql.SQLConnection) MDXConnection(org.pentaho.platform.plugin.services.connections.mondrian.MDXConnection) IPentahoConnection(org.pentaho.commons.connection.IPentahoConnection) Connection(mondrian.olap.Connection) RolapConnection(mondrian.rolap.RolapConnection) Util(mondrian.olap.Util) IMondrianCatalogService(org.pentaho.platform.plugin.action.mondrian.catalog.IMondrianCatalogService) MDXConnection(org.pentaho.platform.plugin.services.connections.mondrian.MDXConnection) MondrianException(mondrian.olap.MondrianException) Pair(mondrian.util.Pair)

Example 3 with Pair

use of mondrian.util.Pair in project mondrian by pentaho.

the class SegmentBuilder method rollup.

/**
 * Given a collection of segments, all of the same dimensionality, rolls up
 * to create a segment with reduced dimensionality.
 *
 * @param map Source segment headers and bodies
 * @param keepColumns A list of column names to keep as part of
 * the rolled up segment.
 * @param targetBitkey The column bit key to match with the
 * resulting segment.
 * @param rollupAggregator The aggregator to use to rollup.
 * @return Segment header and body of requested dimensionality
 * @param datatype The data type to use.
 */
public static Pair<SegmentHeader, SegmentBody> rollup(Map<SegmentHeader, SegmentBody> map, Set<String> keepColumns, BitKey targetBitkey, Aggregator rollupAggregator, Datatype datatype) {
    class AxisInfo {

        SegmentColumn column;

        SortedSet<Comparable> requestedValues;

        SortedSet<Comparable> valueSet;

        Comparable[] values;

        boolean hasNull;

        int src;

        boolean lostPredicate;
    }
    assert allHeadersHaveSameDimensionality(map.keySet());
    // store the map values in a list to assure the first header
    // loaded here is consistent w/ the first segment processed below.
    List<Map.Entry<SegmentHeader, SegmentBody>> segments = UnmodifiableArrayList.of(map.entrySet());
    final SegmentHeader firstHeader = segments.get(0).getKey();
    final List<AxisInfo> axes = new ArrayList<AxisInfo>(keepColumns.size());
    int z = 0, j = 0;
    List<SegmentColumn> firstHeaderConstrainedColumns = firstHeader.getConstrainedColumns();
    for (SegmentColumn column : firstHeaderConstrainedColumns) {
        if (keepColumns.contains(column.columnExpression)) {
            final AxisInfo axisInfo = new AxisInfo();
            axes.add(axisInfo);
            axisInfo.src = j;
            axisInfo.column = column;
            axisInfo.requestedValues = column.values;
        }
        j++;
    }
    // are the intersection of the input axes.
    for (Map.Entry<SegmentHeader, SegmentBody> entry : segments) {
        final SegmentHeader header = entry.getKey();
        for (AxisInfo axis : axes) {
            final SortedSet<Comparable> values = entry.getValue().getAxisValueSets()[axis.src];
            final SegmentColumn headerColumn = header.getConstrainedColumn(axis.column.columnExpression);
            final boolean hasNull = entry.getValue().getNullAxisFlags()[axis.src];
            final SortedSet<Comparable> requestedValues = headerColumn.getValues();
            if (axis.valueSet == null) {
                axis.valueSet = new TreeSet<Comparable>(values);
                axis.hasNull = hasNull;
                axis.requestedValues = requestedValues;
            } else {
                final SortedSet<Comparable> filteredValues;
                final boolean filteredHasNull;
                if (axis.requestedValues == null && requestedValues == null) {
                    // there are 2+ segments that are unconstrained for
                    // this axis.  While unconstrained, individually
                    // they may not have all values present.
                    // Make sure we don't lose any values.
                    filteredValues = axis.valueSet;
                    filteredValues.addAll(new TreeSet<Comparable>(values));
                    filteredHasNull = hasNull || axis.hasNull;
                } else if (axis.requestedValues == null) {
                    filteredValues = values;
                    filteredHasNull = hasNull;
                    axis.column = headerColumn;
                } else if (requestedValues == null) {
                    // this axis is wildcarded
                    filteredValues = axis.requestedValues;
                    filteredHasNull = axis.hasNull;
                } else {
                    filteredValues = Util.intersect(requestedValues, axis.requestedValues);
                    // SegmentColumn predicates cannot ask for the null
                    // value (at present).
                    filteredHasNull = false;
                }
                axis.valueSet = filteredValues;
                axis.hasNull = axis.hasNull || filteredHasNull;
                if (!Util.equals(axis.requestedValues, requestedValues)) {
                    if (axis.requestedValues == null) {
                        // Downgrade from wildcard to a specific list.
                        axis.requestedValues = requestedValues;
                    } else if (requestedValues != null) {
                        // Segment requests have incompatible predicates.
                        // Best we can say is "we must have asked for the
                        // values that came back".
                        axis.lostPredicate = true;
                    }
                }
            }
        }
    }
    for (AxisInfo axis : axes) {
        axis.values = axis.valueSet.toArray(new Comparable[axis.valueSet.size()]);
    }
    // Populate cells.
    // 
    // (This is a rough implementation, very inefficient. It makes all
    // segment types pretend to be sparse, for purposes of reading. It
    // maps all axis ordinals to a value, then back to an axis ordinal,
    // even if this translation were not necessary, say if the source and
    // target axes had the same set of values. And it always creates a
    // sparse segment.
    // 
    // We should do really efficient rollup if the source is an array: we
    // should box values (e.g double to Double and back), and we should read
    // a stripe of values from the and add them up into a single cell.
    final Map<CellKey, List<Object>> cellValues = new HashMap<CellKey, List<Object>>();
    List<List<Comparable>> addedIntersections = new ArrayList<List<Comparable>>();
    for (Map.Entry<SegmentHeader, SegmentBody> entry : map.entrySet()) {
        final int[] pos = new int[axes.size()];
        final Comparable[][] valueArrays = new Comparable[firstHeaderConstrainedColumns.size()][];
        final SegmentBody body = entry.getValue();
        // Copy source value sets into arrays. For axes that are being
        // projected away, store null.
        z = 0;
        for (SortedSet<Comparable> set : body.getAxisValueSets()) {
            valueArrays[z] = keepColumns.contains(firstHeaderConstrainedColumns.get(z).columnExpression) ? set.toArray(new Comparable[set.size()]) : null;
            ++z;
        }
        Map<CellKey, Object> v = body.getValueMap();
        entryLoop: for (Map.Entry<CellKey, Object> vEntry : v.entrySet()) {
            z = 0;
            for (int i = 0; i < vEntry.getKey().size(); i++) {
                final Comparable[] valueArray = valueArrays[i];
                if (valueArray == null) {
                    continue;
                }
                final int ordinal = vEntry.getKey().getOrdinals()[i];
                final int targetOrdinal;
                if (axes.get(z).hasNull && ordinal == valueArray.length) {
                    targetOrdinal = axes.get(z).valueSet.size();
                } else {
                    final Comparable value = valueArray[ordinal];
                    if (value == null) {
                        targetOrdinal = axes.get(z).valueSet.size();
                    } else {
                        targetOrdinal = Util.binarySearch(axes.get(z).values, 0, axes.get(z).values.length, value);
                    }
                }
                if (targetOrdinal >= 0) {
                    pos[z++] = targetOrdinal;
                } else {
                    // contain the requested cell.
                    continue entryLoop;
                }
            }
            final CellKey ck = CellKey.Generator.newCellKey(pos);
            if (!cellValues.containsKey(ck)) {
                cellValues.put(ck, new ArrayList<Object>());
            }
            List<Comparable> colValues = getColumnValsAtCellKey(body, vEntry.getKey());
            if (!addedIntersections.contains(colValues)) {
                // only add the cell value if we haven't already.
                // there is a potential double add if segments overlap
                cellValues.get(ck).add(vEntry.getValue());
                addedIntersections.add(colValues);
            }
        }
    }
    // Build the axis list.
    final List<Pair<SortedSet<Comparable>, Boolean>> axisList = new ArrayList<Pair<SortedSet<Comparable>, Boolean>>();
    BigInteger bigValueCount = BigInteger.ONE;
    for (AxisInfo axis : axes) {
        axisList.add(Pair.of(axis.valueSet, axis.hasNull));
        int size = axis.values.length;
        bigValueCount = bigValueCount.multiply(BigInteger.valueOf(axis.hasNull ? size + 1 : size));
    }
    // The logic used here for the sparse check follows
    // SegmentLoader.setAxisDataAndDecideSparseUse.
    // The two methods use different data structures (AxisInfo/SegmentAxis)
    // so combining logic is probably more trouble than it's worth.
    final boolean sparse = bigValueCount.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) > 0 || SegmentLoader.useSparse(bigValueCount.doubleValue(), cellValues.size());
    final int[] axisMultipliers = computeAxisMultipliers(axisList);
    final SegmentBody body;
    // (whether to use a dense native dataset or a sparse one.
    if (cellValues.size() == 0) {
        // Just store the data into an empty dense object dataset.
        body = new DenseObjectSegmentBody(new Object[0], axisList);
    } else if (sparse) {
        // The rule says we must use a sparse dataset.
        // First, aggregate the values of each key.
        final Map<CellKey, Object> data = new HashMap<CellKey, Object>();
        for (Entry<CellKey, List<Object>> entry : cellValues.entrySet()) {
            data.put(CellKey.Generator.newCellKey(entry.getKey().getOrdinals()), rollupAggregator.aggregate(entry.getValue(), datatype));
        }
        body = new SparseSegmentBody(data, axisList);
    } else {
        final BitSet nullValues;
        final int valueCount = bigValueCount.intValue();
        switch(datatype) {
            case Integer:
                final int[] ints = new int[valueCount];
                nullValues = Util.bitSetBetween(0, valueCount);
                for (Entry<CellKey, List<Object>> entry : cellValues.entrySet()) {
                    final int offset = CellKey.Generator.getOffset(entry.getKey().getOrdinals(), axisMultipliers);
                    final Object value = rollupAggregator.aggregate(entry.getValue(), datatype);
                    if (value != null) {
                        ints[offset] = (Integer) value;
                        nullValues.clear(offset);
                    }
                }
                body = new DenseIntSegmentBody(nullValues, ints, axisList);
                break;
            case Numeric:
                final double[] doubles = new double[valueCount];
                nullValues = Util.bitSetBetween(0, valueCount);
                for (Entry<CellKey, List<Object>> entry : cellValues.entrySet()) {
                    final int offset = CellKey.Generator.getOffset(entry.getKey().getOrdinals(), axisMultipliers);
                    final Object value = rollupAggregator.aggregate(entry.getValue(), datatype);
                    if (value != null) {
                        doubles[offset] = (Double) value;
                        nullValues.clear(offset);
                    }
                }
                body = new DenseDoubleSegmentBody(nullValues, doubles, axisList);
                break;
            default:
                final Object[] objects = new Object[valueCount];
                for (Entry<CellKey, List<Object>> entry : cellValues.entrySet()) {
                    final int offset = CellKey.Generator.getOffset(entry.getKey().getOrdinals(), axisMultipliers);
                    objects[offset] = rollupAggregator.aggregate(entry.getValue(), datatype);
                }
                body = new DenseObjectSegmentBody(objects, axisList);
        }
    }
    // Create header.
    final List<SegmentColumn> constrainedColumns = new ArrayList<SegmentColumn>();
    for (int i = 0; i < axes.size(); i++) {
        AxisInfo axisInfo = axes.get(i);
        constrainedColumns.add(new SegmentColumn(axisInfo.column.getColumnExpression(), axisInfo.column.getValueCount(), axisInfo.lostPredicate ? axisList.get(i).left : axisInfo.column.values));
    }
    final SegmentHeader header = new SegmentHeader(firstHeader.schemaName, firstHeader.schemaChecksum, firstHeader.cubeName, firstHeader.measureName, constrainedColumns, firstHeader.compoundPredicates, firstHeader.rolapStarFactTableName, targetBitkey, Collections.<SegmentColumn>emptyList());
    if (LOGGER.isDebugEnabled()) {
        StringBuilder builder = new StringBuilder();
        builder.append("Rolling up segments with parameters: \n");
        builder.append("keepColumns=" + keepColumns + "\n");
        builder.append("aggregator=" + rollupAggregator + "\n");
        builder.append("datatype=" + datatype + "\n");
        for (Map.Entry<SegmentHeader, SegmentBody> segment : segments) {
            builder.append(segment.getKey() + "\n");
        }
        builder.append("AxisInfos constructed:");
        for (AxisInfo axis : axes) {
            SortedSet<Comparable> colVals = axis.column.getValues();
            builder.append(String.format("column.columnExpression=%s\n" + "column.valueCount=%s\n" + "column.values=%s\n" + "requestedValues=%s\n" + "valueSet=%s\n" + "values=%s\n" + "hasNull=%b\n" + "src=%d\n" + "lostPredicate=%b\n", axis.column.columnExpression, axis.column.getValueCount(), Arrays.toString(colVals == null ? null : colVals.toArray()), axis.requestedValues, axis.valueSet, Arrays.asList(axis.values), axis.hasNull, axis.src, axis.lostPredicate));
        }
        builder.append("Resulted in Segment:  \n");
        builder.append(header);
        builder.append(body.toString());
        LOGGER.debug(builder.toString());
    }
    return Pair.of(header, body);
}
Also used : UnmodifiableArrayList(org.olap4j.impl.UnmodifiableArrayList) ArraySortedSet(mondrian.util.ArraySortedSet) Entry(java.util.Map.Entry) UnmodifiableArrayList(org.olap4j.impl.UnmodifiableArrayList) Pair(mondrian.util.Pair) BigInteger(java.math.BigInteger) BigInteger(java.math.BigInteger)

Aggregations

Pair (mondrian.util.Pair)3 Util (mondrian.olap.Util)2 IMondrianCatalogService (org.pentaho.platform.plugin.action.mondrian.catalog.IMondrianCatalogService)2 MondrianCatalog (org.pentaho.platform.plugin.action.mondrian.catalog.MondrianCatalog)2 MDXConnection (org.pentaho.platform.plugin.services.connections.mondrian.MDXConnection)2 BigInteger (java.math.BigInteger)1 Entry (java.util.Map.Entry)1 Properties (java.util.Properties)1 Connection (mondrian.olap.Connection)1 MondrianException (mondrian.olap.MondrianException)1 RolapConnection (mondrian.rolap.RolapConnection)1 RolapConnectionProperties (mondrian.rolap.RolapConnectionProperties)1 ArraySortedSet (mondrian.util.ArraySortedSet)1 UnmodifiableArrayList (org.olap4j.impl.UnmodifiableArrayList)1 MdxConnectionAction (org.pentaho.actionsequence.dom.actions.MdxConnectionAction)1 IPentahoConnection (org.pentaho.commons.connection.IPentahoConnection)1 TemplateUtil (org.pentaho.platform.engine.services.runtime.TemplateUtil)1 SQLConnection (org.pentaho.platform.plugin.services.connections.sql.SQLConnection)1