diff --git a/saiku-bi-platform-plugin/pom.xml b/saiku-bi-platform-plugin/pom.xml index 82adce5192..730111146c 100644 --- a/saiku-bi-platform-plugin/pom.xml +++ b/saiku-bi-platform-plugin/pom.xml @@ -297,7 +297,11 @@ pentaho-third-party http://repo.pentaho.org/artifactory/third-party/ - + + alabs-repo + alabs repository + http://repo.analytical-labs.com/repo/ + ibiblio http://ibiblio.org/maven2/ diff --git a/saiku-core/saiku-service/src/main/java/org/saiku/olap/query/MdxQuery.java b/saiku-core/saiku-service/src/main/java/org/saiku/olap/query/MdxQuery.java index daddd747cb..c8a53014c1 100644 --- a/saiku-core/saiku-service/src/main/java/org/saiku/olap/query/MdxQuery.java +++ b/saiku-core/saiku-service/src/main/java/org/saiku/olap/query/MdxQuery.java @@ -47,7 +47,7 @@ public class MdxQuery implements IQuery { private static final Logger log = LoggerFactory.getLogger(MdxQuery.class); - + private Properties properties = new Properties(); private String mdx; private SaikuCube cube; @@ -56,14 +56,14 @@ public class MdxQuery implements IQuery { private Scenario scenario; private CellSet cellset; private OlapStatement statement; - + public MdxQuery(OlapConnection con, SaikuCube cube, String name, String mdx) { this.cube = cube; this.connection = con; this.name = name; this.mdx = mdx; } - + public String getName() { return name; } @@ -87,60 +87,69 @@ public SaikuCube getSaikuCube() { return cube; } - public String getMdx() { - return mdx; - } - - public void setMdx(String mdx) { - this.mdx = mdx; - } + public String getMdx() { + return mdx; + } + + public void setMdx(String mdx) { + this.mdx = mdx; + } public void resetQuery() { this.mdx = ""; } - - public void setProperties(Properties props) { - this.properties.putAll(props); - } - - public Properties getProperties() { - Properties props = new Properties(this.properties); - props.put(QueryProperties.KEY_IS_DRILLTHROUGH, isDrillThroughEnabled().toString()); - props.put("org.saiku.connection.scenario", Boolean.toString(false)); - try { - props.put("org.saiku.query.explain", Boolean.toString(connection.isWrapperFor(RolapConnection.class))); - } catch (Exception e) { - props.put("org.saiku.query.explain", Boolean.toString(false)); - } - return props; - } - - public String toXml() { - QuerySerializer qs = new QuerySerializer(this); - return qs.createXML(); - } - - public Boolean isDrillThroughEnabled() { - try { - Cube cube = getCube(); - return (cube != null && cube.isDrillThroughEnabled()); - } catch (Exception e) { - e.printStackTrace(); - }; - return false; - } + + public void setProperties(Properties props) { + this.properties.putAll(props); + } + + public Properties getProperties() { + Properties props = this.properties; + props.put(QueryProperties.KEY_IS_DRILLTHROUGH, isDrillThroughEnabled().toString()); + props.put("org.saiku.connection.scenario", Boolean.toString(false)); + try { + props.put("org.saiku.query.explain", Boolean.toString(connection.isWrapperFor(RolapConnection.class))); + } catch (Exception e) { + props.put("org.saiku.query.explain", Boolean.toString(false)); + } + return props; + } + + public String toXml() { + QuerySerializer qs = new QuerySerializer(this); + return qs.createXML(); + } + + public Boolean isDrillThroughEnabled() { + try { + Cube cube = getCube(); + return (cube != null && cube.isDrillThroughEnabled()); + } catch (Exception e) { + e.printStackTrace(); + }; + return false; + } public CellSet execute() throws Exception { - OlapConnection con = connection; - con.setCatalog(getSaikuCube().getCatalogName()); - OlapStatement stmt = con.createStatement(); - this.statement = stmt; - CellSet cs = stmt.executeOlapQuery(mdx); - if (statement != null) { - statement.close(); + try { + if (statement != null) { + statement.close(); + statement = null; + } + + OlapConnection con = connection; + con.setCatalog(getSaikuCube().getCatalogName()); + OlapStatement stmt = con.createStatement(); + this.statement = stmt; + CellSet cs = stmt.executeOlapQuery(mdx); + + return cs; + } finally { + if (statement != null) { + statement.close(); + statement = null; + } } - this.statement = null; - return cs; } public QueryType getType() { @@ -164,47 +173,49 @@ public QueryAxis getAxis(String name) throws SaikuOlapException { } public Cube getCube() { - final MdxParserFactory parserFactory = - connection.getParserFactory(); - MdxParser mdxParser = - parserFactory.createMdxParser(connection); - MdxValidator mdxValidator = - parserFactory.createMdxValidator(connection); - - String mdx = getMdx(); - try { - - if (mdx != null && mdx.length() > 0 && mdx.toUpperCase().contains("FROM")) { - SelectNode select = - mdxParser.parseSelect(getMdx()); - select = mdxValidator.validateSelect(select); - CubeType cubeType = (CubeType) select.getFrom().getType(); - return cubeType.getCube(); - } - } catch (Exception e) { - log.debug("Parsing MDX to get the Cube failed. Using fallback scenario.", e); - } - try { - // ok seems like we failed to get the cube, lets try it differently - if (connection != null && mdx != null && mdx.length() > 0) { - for (Database db : connection.getOlapDatabases()) { - Catalog cat = db.getCatalogs().get(cube.getCatalogName()); - if (cat != null) { - for (Schema schema : cat.getSchemas()) { - for (Cube cub : schema.getCubes()) { - if (cub.getName().equals(cube.getName()) || cub.getUniqueName().equals(cube.getName())) { - return cub; - } - } - } - } - } - } - } catch (OlapException e) { - e.printStackTrace(); + final MdxParserFactory parserFactory = + connection.getParserFactory(); + MdxParser mdxParser = + parserFactory.createMdxParser(connection); + MdxValidator mdxValidator = + parserFactory.createMdxValidator(connection); + + String mdx = getMdx(); + try { + + if (mdx != null && mdx.length() > 0 && mdx.toUpperCase().contains("FROM")) { + SelectNode select = + mdxParser.parseSelect(getMdx()); + select = mdxValidator.validateSelect(select); + CubeType cubeType = (CubeType) select.getFrom().getType(); + return cubeType.getCube(); + } + } catch (Exception e) { + log.debug("Parsing MDX to get the Cube failed. Using fallback scenario.", e); + } finally { + mdxValidator = null; + } + try { + // ok seems like we failed to get the cube, lets try it differently + if (connection != null && mdx != null && mdx.length() > 0) { + for (Database db : connection.getOlapDatabases()) { + Catalog cat = db.getCatalogs().get(cube.getCatalogName()); + if (cat != null) { + for (Schema schema : cat.getSchemas()) { + for (Cube cub : schema.getCubes()) { + if (cub.getName().equals(cube.getName()) || cub.getUniqueName().equals(cube.getName())) { + return cub; + } + } + } + } + } + } + } catch (OlapException e) { + e.printStackTrace(); } - + return null; } @@ -231,7 +242,7 @@ public void resetAxisSelections(QueryAxis axis) { public void clearAllQuerySelections() { throw new UnsupportedOperationException(); } - + public void clearAxis(String axisName) throws SaikuOlapException { throw new UnsupportedOperationException(); } @@ -239,7 +250,7 @@ public void clearAxis(String axisName) throws SaikuOlapException { public void setScenario(Scenario scenario) { this.scenario = scenario; } - + public Scenario getScenario() { return scenario; } @@ -257,7 +268,7 @@ public void removeTag() { public void storeCellset(CellSet cs) { this.cellset = cs; - + } public CellSet getCellset() { @@ -266,13 +277,13 @@ public CellSet getCellset() { public void setStatement(OlapStatement os) { this.statement = os; - + } public OlapStatement getStatement() { return this.statement; } - + public void cancel() throws Exception { if (this.statement != null && !this.statement.isClosed()) { statement.close(); diff --git a/saiku-core/saiku-service/src/main/java/org/saiku/olap/query/OlapQuery.java b/saiku-core/saiku-service/src/main/java/org/saiku/olap/query/OlapQuery.java index c5845a9c9c..36b5daa880 100644 --- a/saiku-core/saiku-service/src/main/java/org/saiku/olap/query/OlapQuery.java +++ b/saiku-core/saiku-service/src/main/java/org/saiku/olap/query/OlapQuery.java @@ -53,25 +53,25 @@ public class OlapQuery implements IQuery { - private static final Logger log = LoggerFactory.getLogger(OlapQuery.class); + private static final Logger log = LoggerFactory.getLogger(OlapQuery.class); - private static final String SCENARIO = "Scenario"; + private static final String SCENARIO = "Scenario"; private Query query; private Properties properties = new Properties(); private SaikuCube cube; - + private Scenario scenario; - + private SaikuTag tag = null; - + private CellSet cellset = null; private OlapStatement statement = null; private OlapConnection connection; - + public OlapQuery(Query query, OlapConnection connection, SaikuCube cube, boolean applyDefaultProperties) { this.query = query; this.cube = cube; @@ -84,14 +84,14 @@ public OlapQuery(Query query, OlapConnection connection, SaikuCube cube, boolean public OlapQuery(Query query, OlapConnection connection, SaikuCube cube) { this(query,connection, cube,true); } - + public void swapAxes() { this.query.swapAxes(); QueryAxis rows = query.getAxis(Axis.ROWS); QueryAxis cols = query.getAxis(Axis.COLUMNS); - + // 3-way swap String colFilter = cols.getFilterCondition(); LimitFunction colLimit = cols.getLimitFunction(); @@ -103,7 +103,7 @@ public void swapAxes() { cols.clearFilter(); cols.clearLimitFunction(); cols.clearSort(); - + // columns if (rows.getSortOrder() != null) { cols.sort(rows.getSortOrder(), rows.getSortIdentifierNodeName()); @@ -114,11 +114,11 @@ public void swapAxes() { if (StringUtils.isNotBlank(rows.getFilterCondition())) { cols.filter(rows.getFilterCondition()); } - + rows.clearFilter(); rows.clearLimitFunction(); rows.clearSort(); - + // rows if (colSort != null) { rows.sort(colSort, colSortIdentifier); @@ -129,18 +129,18 @@ public void swapAxes() { if (StringUtils.isNotBlank(colFilter)) { rows.filter(colFilter); } - + } - + public Map getAxes() { return this.query.getAxes(); } - + public QueryAxis getAxis(Axis axis) { return this.query.getAxis(axis); } - + public QueryAxis getAxis(String name) throws SaikuOlapException { if ("UNUSED".equals(name)) { return getUnusedAxis(); @@ -148,26 +148,26 @@ public QueryAxis getAxis(String name) throws SaikuOlapException { Standard standardAxis = Standard.valueOf(name); if (standardAxis == null) throw new SaikuOlapException("Axis ("+name+") not found for query ("+ query.getName() + ")"); - + Axis queryAxis = Axis.Factory.forOrdinal(standardAxis.axisOrdinal()); return query.getAxis(queryAxis); } - + public Cube getCube() { return this.query.getCube(); } - + public QueryAxis getUnusedAxis() { return this.query.getUnusedAxis(); } - + public void moveDimension(QueryDimension dimension, Axis axis) { moveDimension(dimension, axis, -1); } public void moveDimension(QueryDimension dimension, Axis axis, int position) { - QueryAxis oldQueryAxis = findAxis(dimension); - QueryAxis newQueryAxis = query.getAxis(axis); + QueryAxis oldQueryAxis = findAxis(dimension); + QueryAxis newQueryAxis = query.getAxis(axis); if (dimension.getName() != "Measures" && !Axis.FILTER.equals(axis)) { dimension.setHierarchyConsistent(true); dimension.setHierarchizeMode(HierarchizeMode.PRE); @@ -175,7 +175,7 @@ public void moveDimension(QueryDimension dimension, Axis axis, int position) { dimension.setHierarchyConsistent(false); dimension.clearHierarchizeMode(); } - + if (oldQueryAxis != null && newQueryAxis != null && (oldQueryAxis.getLocation() != newQueryAxis.getLocation()) && oldQueryAxis.getLocation() != null) { for (QueryAxis qAxis : query.getAxes().values()) { @@ -189,20 +189,20 @@ public void moveDimension(QueryDimension dimension, Axis axis, int position) { } } - if (oldQueryAxis != null && newQueryAxis != null && (position > -1 || (oldQueryAxis.getLocation() != newQueryAxis.getLocation()))) { - oldQueryAxis.removeDimension(dimension); - if (position > -1) { - newQueryAxis.addDimension(position, dimension); - } else { - newQueryAxis.addDimension(dimension); - } - } - } - + if (oldQueryAxis != null && newQueryAxis != null && (position > -1 || (oldQueryAxis.getLocation() != newQueryAxis.getLocation()))) { + oldQueryAxis.removeDimension(dimension); + if (position > -1) { + newQueryAxis.addDimension(position, dimension); + } else { + newQueryAxis.addDimension(dimension); + } + } + } + public QueryDimension getDimension(String name) { return this.query.getDimension(name); } - + private QueryAxis findAxis(QueryDimension dimension) { if (query.getUnusedAxis().getDimensions().contains(dimension)) { return query.getUnusedAxis(); @@ -214,65 +214,72 @@ private QueryAxis findAxis(QueryDimension dimension) { return axes.get(axis); } } - + } return null; } - public String getMdx() { - final Writer writer = new StringWriter(); - this.query.getSelect().unparse(new ParseTreeWriter(new PrintWriter(writer))); - return writer.toString(); - } - - public SaikuCube getSaikuCube() { - return cube; - } - - public String getName() { - return query.getName(); - } - - public CellSet execute() throws Exception { - - if (scenario != null && query.getDimension(SCENARIO) != null) { - QueryDimension dimension = query.getDimension(SCENARIO); - moveDimension(dimension, Axis.FILTER); - Selection sel = dimension.createSelection(IdentifierParser.parseIdentifier("[Scenario].[" + getScenario().getId() + "]")); - if (!dimension.getInclusions().contains(sel)) { - dimension.getInclusions().add(sel); - } - } - - String mdx = getMdx(); - - log.trace("Executing query (" + this.getName() + ") :\n" + mdx); - - final Catalog catalog = query.getCube().getSchema().getCatalog(); - this.connection.setCatalog(catalog.getName()); - OlapStatement stmt = connection.createStatement(); - this.statement = stmt; - CellSet cellSet = stmt.executeOlapQuery(mdx); - if (this.statement != null) { - this.statement.close(); + public String getMdx() { + final Writer writer = new StringWriter(); + this.query.getSelect().unparse(new ParseTreeWriter(new PrintWriter(writer))); + return writer.toString(); + } + + public SaikuCube getSaikuCube() { + return cube; + } + + public String getName() { + return query.getName(); + } + + public CellSet execute() throws Exception { + try { + if (statement != null) { + statement.close(); + statement = null; + } + + if (scenario != null && query.getDimension(SCENARIO) != null) { + QueryDimension dimension = query.getDimension(SCENARIO); + moveDimension(dimension, Axis.FILTER); + Selection sel = dimension.createSelection(IdentifierParser.parseIdentifier("[Scenario].[" + getScenario().getId() + "]")); + if (!dimension.getInclusions().contains(sel)) { + dimension.getInclusions().add(sel); + } + } + + String mdx = getMdx(); + + log.trace("Executing query (" + this.getName() + ") :\n" + mdx); + + final Catalog catalog = query.getCube().getSchema().getCatalog(); + this.connection.setCatalog(catalog.getName()); + OlapStatement stmt = connection.createStatement(); + this.statement = stmt; + CellSet cellSet = stmt.executeOlapQuery(mdx); + if (scenario != null && query.getDimension(SCENARIO) != null) { + QueryDimension dimension = query.getDimension(SCENARIO); + dimension.getInclusions().clear(); + moveDimension(dimension, null); + } + + return cellSet; + } finally { + if (this.statement != null) { + this.statement.close(); + } } - this.statement = null; - if (scenario != null && query.getDimension(SCENARIO) != null) { - QueryDimension dimension = query.getDimension(SCENARIO); - dimension.getInclusions().clear(); - moveDimension(dimension, null); - } - - return cellSet; - } - - private void applyDefaultProperties() { - if (SaikuProperties.olapDefaultNonEmpty) { - query.getAxis(Axis.ROWS).setNonEmpty(true); - query.getAxis(Axis.COLUMNS).setNonEmpty(true); - } - } - + + } + + private void applyDefaultProperties() { + if (SaikuProperties.olapDefaultNonEmpty) { + query.getAxis(Axis.ROWS).setNonEmpty(true); + query.getAxis(Axis.COLUMNS).setNonEmpty(true); + } + } + public void resetAxisSelections(QueryAxis axis) { for (QueryDimension dim : axis.getDimensions()) { dim.clearInclusions(); @@ -284,7 +291,7 @@ public void resetAxisSelections(QueryAxis axis) { axis.clearLimitFunction(); axis.clearSort(); } catch (NoSuchMethodError e) {} - + } public void clearAllQuerySelections() { @@ -294,7 +301,7 @@ public void clearAllQuerySelections() { resetAxisSelections(axes.get(axis)); } } - + public void resetQuery() { clearAllQuerySelections(); Map axes = getAxes(); @@ -306,7 +313,7 @@ public void resetQuery() { } } } - + public void clearAxis(String axisName) throws SaikuOlapException { if (StringUtils.isNotBlank(axisName)) { QueryAxis qAxis = getAxis(axisName); @@ -317,7 +324,7 @@ public void clearAxis(String axisName) throws SaikuOlapException { } } } - + public void setProperties(Properties props) { if (props != null) { this.properties.putAll(props); @@ -329,11 +336,11 @@ public void setProperties(Properties props) { } } } - - public Properties getProperties() { - this.properties.putAll(QueryPropertyFactory.forQuery(this)); + + public Properties getProperties() { + this.properties.putAll(QueryPropertyFactory.forQuery(this)); try { - + connection.createScenario(); if (query.getDimension("Scenario") != null) { this.properties.put("org.saiku.connection.scenario", Boolean.toString(true)); @@ -346,30 +353,30 @@ public Properties getProperties() { this.properties.put("org.saiku.connection.scenario", Boolean.toString(false)); this.properties.put("org.saiku.query.explain", Boolean.toString(false)); } - return this.properties; - } - - public String toXml() { - QuerySerializer qs = new QuerySerializer(this); - return qs.createXML(); - } - - public Boolean isDrillThroughEnabled() { - return query.getCube().isDrillThroughEnabled(); - } + return this.properties; + } + + public String toXml() { + QuerySerializer qs = new QuerySerializer(this); + return qs.createXML(); + } + + public Boolean isDrillThroughEnabled() { + return query.getCube().isDrillThroughEnabled(); + } public QueryType getType() { return QueryType.QM; } - + public void setMdx(String mdx) { throw new UnsupportedOperationException(); } - + public void setScenario(Scenario scenario) { this.scenario = scenario; } - + public Scenario getScenario() { return scenario; } @@ -388,7 +395,7 @@ public void removeTag() { public void storeCellset(CellSet cs) { this.cellset = cs; - + } public CellSet getCellset() { @@ -397,7 +404,7 @@ public CellSet getCellset() { public void setStatement(OlapStatement os) { this.statement = os; - + } public OlapStatement getStatement() { diff --git a/saiku-core/saiku-service/src/main/java/org/saiku/service/olap/OlapQueryService.java b/saiku-core/saiku-service/src/main/java/org/saiku/service/olap/OlapQueryService.java index e457cce7c9..6fe583d698 100644 --- a/saiku-core/saiku-service/src/main/java/org/saiku/service/olap/OlapQueryService.java +++ b/saiku-core/saiku-service/src/main/java/org/saiku/service/olap/OlapQueryService.java @@ -393,27 +393,34 @@ public List getResultMetadataMembers(String queryName, boolean pref } public ResultSet explain(String queryName) { + OlapStatement stmt = null; try { final OlapConnection con = olapDiscoverService.getNativeConnection(getQuery(queryName).getCube().getConnectionName()); if (!con.isWrapperFor(RolapConnection.class)) throw new IllegalArgumentException("Cannot only get explain plan for Mondrian connections"); - final OlapStatement stmt = con.createStatement(); + stmt = con.createStatement(); String mdx = getMDXQuery(queryName); mdx = "EXPLAIN PLAN FOR \n" + mdx; - return stmt.executeQuery(mdx); + ResultSet rs = stmt.executeQuery(mdx); + return rs; } catch (Exception e) { throw new SaikuServiceException("Error EXPLAIN: " + queryName,e); - } + } finally { + try { + if (stmt != null) stmt.close(); + } catch (Exception e) {} + } } public ResultSet drillthrough(String queryName, int maxrows, String returns) { + OlapStatement stmt = null; try { final OlapConnection con = olapDiscoverService.getNativeConnection(getQuery(queryName).getCube().getConnectionName()); - final OlapStatement stmt = con.createStatement(); + stmt = con.createStatement(); String mdx = getMDXQuery(queryName); if (maxrows > 0) { mdx = "DRILLTHROUGH MAXROWS " + maxrows + " " + mdx; @@ -424,19 +431,25 @@ public ResultSet drillthrough(String queryName, int maxrows, String returns) { if (StringUtils.isNotBlank(returns)) { mdx += "\r\n RETURN " + returns; } - return stmt.executeQuery(mdx); + ResultSet rs = stmt.executeQuery(mdx); + return rs; } catch (SQLException e) { throw new SaikuServiceException("Error DRILLTHROUGH: " + queryName,e); + } finally { + try { + if (stmt != null) stmt.close(); + } catch (Exception e) {} } } public ResultSet drillthrough(String queryName, List cellPosition, Integer maxrows, String returns) { + OlapStatement stmt = null; try { IQuery query = getIQuery(queryName); CellSet cs = query.getCellset(); SaikuCube cube = getQuery(queryName).getCube(); final OlapConnection con = olapDiscoverService.getNativeConnection(cube.getConnectionName()); - final OlapStatement stmt = con.createStatement(); + stmt = con.createStatement(); String select = null; StringBuffer buf = new StringBuffer(); @@ -472,19 +485,24 @@ public ResultSet drillthrough(String queryName, List cellPosition, Inte } log.debug("Drill Through for query (" + queryName + ") : \r\n" + select); - return stmt.executeQuery(select); - - + ResultSet rs = stmt.executeQuery(select); + return rs; } catch (Exception e) { throw new SaikuServiceException("Error DRILLTHROUGH: " + queryName,e); + } finally { + try { + if (stmt != null) stmt.close(); + } catch (Exception e) {} } + } public byte[] exportDrillthroughCsv(String queryName, int maxrows) { + OlapStatement stmt = null; try { final OlapConnection con = olapDiscoverService.getNativeConnection(getQuery(queryName).getCube().getConnectionName()); - final OlapStatement stmt = con.createStatement(); + stmt = con.createStatement(); String mdx = getMDXQuery(queryName); if (maxrows > 0) { mdx = "DRILLTHROUGH MAXROWS " + maxrows + " " + mdx; @@ -492,11 +510,17 @@ public byte[] exportDrillthroughCsv(String queryName, int maxrows) { else { mdx = "DRILLTHROUGH " + mdx; } + ResultSet rs = stmt.executeQuery(mdx); return CsvExporter.exportCsv(rs); } catch (SQLException e) { throw new SaikuServiceException("Error DRILLTHROUGH: " + queryName,e); + } finally { + try { + if (stmt != null) stmt.close(); + } catch (Exception e) {} } + } public byte[] exportResultSetCsv(ResultSet rs) { @@ -975,12 +999,20 @@ private void putIQuery(String queryName, IQuery query) { } private void removeIQuery(String queryName) { - queries.remove(queryName); + if (queries.containsKey(queryName)) { + IQuery q = queries.remove(queryName); + try { + q.cancel(); + } catch (Exception e) {} + q = null; + } } - - + private IQuery getIQuery(String queryName) { - return queries.get(queryName); + if (queries.containsKey(queryName)) { + return queries.get(queryName); + } + throw new SaikuServiceException("No query found using name: " + queryName); } private Map getIQueryMap() { diff --git a/saiku-ui b/saiku-ui index e96372acaa..0e9d60d693 160000 --- a/saiku-ui +++ b/saiku-ui @@ -1 +1 @@ -Subproject commit e96372acaabb916d0c16b27843b17f478466b4bc +Subproject commit 0e9d60d693aeabcfe9e50c76d6cd8e9cf687b6a8